diff --git a/.helmignore b/.helmignore
new file mode 100644
index 0000000000000000000000000000000000000000..f7ccba7339b7222d2c9c9ddc9b7e944f689fee64
--- /dev/null
+++ b/.helmignore
@@ -0,0 +1 @@
+unit-tests/
\ No newline at end of file
diff --git a/README.md b/README.md
index ac57b09280ad8fa48c020a9ad8f91ec12e564457..181fd1c3b1e5dcd980742f50851c58b363294c72 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,5 @@
-# KOP VorgangManager
+
+## Configuration
+### Create mongodb user
+
+db.createUser({user:"sh-kiel-pluto",pwd:"...",roles:[{role:"readWrite",database:"sh-kiel"}]})
diff --git a/bescheid-manager/pom.xml b/bescheid-manager/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..00cc9ba50886e652b280b71239b03d7e17c62c1a
--- /dev/null
+++ b/bescheid-manager/pom.xml
@@ -0,0 +1,135 @@
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-parent</artifactId>
+		<version>3.0.1</version>
+		<relativePath />
+	</parent>
+
+	<groupId>de.ozgcloud.bescheid</groupId>
+	<artifactId>bescheid-manager</artifactId>
+	<name>OZG-Cloud Bescheid Manager</name>
+	<version>1.8.0</version>
+
+	<properties>
+		<vorgang-manager.version>2.4.0</vorgang-manager.version>
+		<api-lib.version>0.5.0</api-lib.version>
+	</properties>
+
+	<dependencies>
+		<!-- ozg-cloud -->
+		<dependency>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-interface</artifactId>
+			<version>${vorgang-manager.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.command</groupId>
+			<artifactId>command-manager</artifactId>
+			<version>${vorgang-manager.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-utils</artifactId>
+			<version>${vorgang-manager.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>de.ozgcloud.common</groupId>
+			<artifactId>ozgcloud-common-lib</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.api-lib</groupId>
+			<artifactId>api-lib-core</artifactId>
+			<version>${api-lib.version}</version>
+		</dependency>
+
+
+		<!-- spring -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-validation</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.devh</groupId>
+			<artifactId>grpc-client-spring-boot-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.devh</groupId>
+			<artifactId>grpc-server-spring-boot-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-freemarker</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-webflux</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>io.projectreactor.netty</groupId>
+			<artifactId>reactor-netty-http</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.security</groupId>
+			<artifactId>spring-security-core</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-configuration-processor</artifactId>
+			<optional>true</optional>
+		</dependency>
+
+
+		<dependency>
+			<groupId>com.fasterxml.jackson.datatype</groupId>
+			<artifactId>jackson-datatype-jsr310</artifactId>
+		</dependency>
+
+
+		<!--dev tools-->
+		<dependency>
+			<groupId>org.mapstruct</groupId>
+			<artifactId>mapstruct</artifactId>
+		</dependency>
+
+		<!--TEST-->
+		<dependency>
+			<groupId>de.ozgcloud.command</groupId>
+			<artifactId>command-manager</artifactId>
+			<version>${vorgang-manager.version}</version>
+			<type>test-jar</type>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7c925e703216740e72ace1f21a8139e4c697312
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/Bescheid.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import java.io.File;
+import java.util.Optional;
+
+import de.ozgcloud.bescheid.vorgang.Vorgang;
+import de.ozgcloud.bescheid.vorgang.VorgangId;
+import de.ozgcloud.common.binaryfile.FileId;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.With;
+
+@Builder(toBuilder = true)
+@Getter
+public class Bescheid {
+
+	private VorgangId vorgangId;
+
+	private boolean genehmigt;
+	private UserId createdBy;
+
+	private String bescheidFileName;
+	private File bescheidFile;
+	@With
+	private FileId bescheidFileId;
+	private String contentType;
+	private long size;
+
+	@Builder.Default
+	private Optional<String> nachrichtText = Optional.empty();
+
+	private Vorgang.ServiceKonto serviceKonto;
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidCallContextAttachingInterceptor.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidCallContextAttachingInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a1e047f43cfde20bd3e2dccb24aa8725055fcd7
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidCallContextAttachingInterceptor.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
+
+import java.util.UUID;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.bescheid.common.callcontext.CurrentUserService;
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.ClientInterceptor;
+import io.grpc.ForwardingClientCall.SimpleForwardingClientCall;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+
+@Component("bescheidCallContextInterceptor")
+public class BescheidCallContextAttachingInterceptor implements ClientInterceptor {
+
+	public static final String BESCHEID_MANAGER_CLIENT_NAME = "OzgCloud_BescheidManager";
+
+	@Autowired
+	private CurrentUserService userService;
+
+	// <A> = Request, <B> = Response
+	@Override
+	public <A, B> ClientCall<A, B> interceptCall(MethodDescriptor<A, B> method, CallOptions callOptions, Channel next) {
+		return new CallContextAttachingClientCall<>(next.newCall(method, callOptions));
+	}
+
+	final class CallContextAttachingClientCall<A, B> extends SimpleForwardingClientCall<A, B> {
+
+		protected CallContextAttachingClientCall(ClientCall<A, B> delegate) {
+			super(delegate);
+		}
+
+		@Override
+		public void start(Listener<B> responseListener, Metadata headers) {
+			headers.merge(buildCallContextMetadata());
+			super.start(responseListener, headers);
+		}
+
+		private Metadata buildCallContextMetadata() {
+			var metadata = new Metadata();
+
+			userService.getUser().getUserId().ifPresent(userId -> metadata.put(HEADER_KEY_USER_ID, userId.getBytes()));
+			metadata.put(HEADER_KEY_CLIENT_NAME, BESCHEID_MANAGER_CLIENT_NAME.getBytes());
+			metadata.put(HEADER_KEY_REQUEST_ID, generateRequestId().getBytes());
+
+			return metadata;
+		}
+
+		// TODO requestId für command handling uebertragen / erstellen
+		private String generateRequestId() {
+			return UUID.randomUUID().toString();
+		}
+
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidCreatedEvent.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidCreatedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..57dfb1fc10dd84e3000d01a1b92384b2abf96fe7
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidCreatedEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
+
+class BescheidCreatedEvent extends CommandExecutedEvent {
+
+	public BescheidCreatedEvent(Command command) {
+		super(command.getId());
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1f45e3838875daa383795f983364c11aa69a08f
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidEventListener.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import java.time.LocalDate;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.event.EventListener;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.bescheid.binaryfile.BinaryFileService;
+import de.ozgcloud.bescheid.common.callcontext.CurrentUserService;
+import de.ozgcloud.bescheid.nachricht.NachrichtService;
+import de.ozgcloud.bescheid.vorgang.VorgangId;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@Component
+@RequiredArgsConstructor
+class BescheidEventListener {
+
+	public static final String ORDER = "CREATE_BESCHEID";
+
+	private static final String IS_CREATE_BESCHEID = "{T(de.ozgcloud.bescheid.BescheidEventListener).IS_CREATE_BESCHEID_COMMAND.test(event.getSource())}";
+
+	public static final Predicate<Command> IS_CREATE_BESCHEID_COMMAND = command -> command.getOrder().equals(ORDER);
+
+	static final String VORGANG_ID_BODYKEY = "vorgangId";
+	static final String BESCHEID_VOM_BODYKEY = "bescheidVom";
+	static final String GENEHMIGT_BODYKEY = "genehmigt";
+
+	private static final String ERROR_MESSAGE = "Error on executing Create Bescheid Command.";
+
+	private final BescheidService service;
+	private final BinaryFileService fileService;
+	private final NachrichtService nachrichtService;
+
+	private final ApplicationEventPublisher eventPublisher;
+	private final CurrentUserService userService;
+
+	@EventListener(condition = IS_CREATE_BESCHEID)
+	public void onCreateBescheidCommand(CommandCreatedEvent event) {
+		Command command = event.getSource();
+
+		doCreateBescheid(command);
+	}
+
+	private void doCreateBescheid(Command command) {
+		SecurityContext prevContext = null;
+		try {
+			prevContext = userService.startSecurityContext(command);
+			doCreateBescheidBiz(command);
+			eventPublisher.publishEvent(new BescheidCreatedEvent(command));
+		} catch (Exception e) {
+			LOG.error("Error on executing Create Bescheid Command. Command failed.", e);
+			eventPublisher.publishEvent(new CommandFailedEvent(command.getId(), buildErrorMessage(e)));
+		} finally {
+			userService.resetSecurityContext(prevContext);
+		}
+	}
+
+	public void doCreateBescheidBiz(@NonNull Command command) {
+		var bescheid = service.createBescheid(createRequest(command));
+		bescheid = fileService.uploadBescheidFile(bescheid);
+
+		nachrichtService.createNachrichtDraft(bescheid);
+	}
+
+	BescheidRequest createRequest(Command command) {
+		var eventBody = command.getBodyObject();
+		var builder = BescheidRequest.builder();
+
+		builder.vorgangId(VorgangId.from(command.getVorgangId()));
+		Optional.ofNullable(eventBody.get(BESCHEID_VOM_BODYKEY))
+				.map(String.class::cast).map(LocalDate::parse).ifPresent(builder::bescheidVom);
+		Optional.ofNullable(eventBody.get(GENEHMIGT_BODYKEY))
+				.map(Object::toString).map(Boolean::valueOf)
+				.ifPresentOrElse(builder::genehmigt, () -> builder.genehmigt(true));
+		builder.createFor(userService.getUserProfile());
+
+		return builder.build();
+	}
+
+	private String buildErrorMessage(Exception e) {
+		try {
+			StringBuilder sb = new StringBuilder(ERROR_MESSAGE);
+
+			if (Objects.nonNull(e.getCause()) && StringUtils.isNotBlank(e.getCause().getMessage())) {
+				sb.append(" Cause: " + e.getCause().getMessage());
+			}
+
+			if (e instanceof TechnicalException techException) {
+				sb.append(" ExceptionId: " + techException);
+			}
+
+			return sb.toString();
+		} catch (Exception e2) {
+			LOG.error("Error in building Error Message (sick).", e2);
+			return ERROR_MESSAGE;
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidGrpcService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidGrpcService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f67418314ed89822074cc4db5b945649ac47382
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidGrpcService.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import de.ozgcloud.bescheid.BescheidServiceGrpc.BescheidServiceImplBase;
+import io.grpc.stub.StreamObserver;
+import lombok.RequiredArgsConstructor;
+import net.devh.boot.grpc.server.service.GrpcService;
+
+@GrpcService
+@RequiredArgsConstructor
+class BescheidGrpcService extends BescheidServiceImplBase {
+
+	private final GrpcBescheidMapper mapper;
+
+	@Override
+	public void getBescheidDraft(GrpcGetBescheidDraftRequest request, StreamObserver<GrpcGetBescheidDraftResponse> responseObserver) {
+		// dummy implementation
+		// TODO OZG-5099 du real implementation - load Bescheid
+		var bescheid = Bescheid.builder().build();
+
+		responseObserver.onNext(buildResponse(bescheid));
+		responseObserver.onCompleted();
+
+	}
+
+	GrpcGetBescheidDraftResponse buildResponse(Bescheid bescheid) {
+		return GrpcGetBescheidDraftResponse.newBuilder()
+				.setBescheid(mapper.fromBescheid(bescheid))
+				.build();
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1b827db05db07e3c12747b43f29e23cede6c455
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidRemoteService.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import de.ozgcloud.bescheid.vorgang.Vorgang;
+
+public interface BescheidRemoteService {
+
+	Bescheid create(BescheidRequest request, Vorgang vorgang);
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidRequest.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f06f583f0cc8a56ea70e9a0c94248ba3ae3e809a
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidRequest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import java.time.LocalDate;
+
+import de.ozgcloud.bescheid.common.callcontext.UserProfile;
+import de.ozgcloud.bescheid.vorgang.VorgangId;
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class BescheidRequest {
+
+	private VorgangId vorgangId;
+
+	private LocalDate bescheidVom;
+	private boolean genehmigt;
+
+	private UserProfile createFor;
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java
new file mode 100644
index 0000000000000000000000000000000000000000..c55d2d83ec23cb1fad88819c19b3657fb4efeaef
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/BescheidService.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import java.util.Objects;
+
+import jakarta.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.bescheid.vorgang.VorgangService;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.extern.log4j.Log4j2;
+
+@Service
+@Log4j2
+class BescheidService {
+
+	private static final String ERROR_MESSAGE_NO_SERVICE = "'CREATE_BESCHEID' Command received but no Bescheid Endpoint is configured.";
+
+	@Autowired
+	private VorgangService vorgangService;
+	@Autowired(required = false)
+	private BescheidRemoteService remoteService;
+
+	@PostConstruct
+	void logStatus() {
+		if (Objects.isNull(ERROR_MESSAGE_NO_SERVICE)) {
+			LOG.info("No BescheidRemoteService configured - Bescheid creation is not possible.");
+		} else {
+			LOG.info("Bescheid-Manager is configured.");
+		}
+	}
+
+	public Bescheid createBescheid(BescheidRequest request) {
+		checkRemoteService();
+
+		return doCreateBescheid(request);
+	}
+
+	private Bescheid doCreateBescheid(BescheidRequest request) {
+		var vorgang = vorgangService.getById(request.getVorgangId());
+		return remoteService.create(request, vorgang)
+				.toBuilder().vorgangId(vorgang.getId()).serviceKonto(vorgang.getServiceKonto())
+				.build();
+	}
+
+	private void checkRemoteService() {
+		if (Objects.isNull(remoteService)) {
+			LOG.error(ERROR_MESSAGE_NO_SERVICE);
+			throw new TechnicalException(ERROR_MESSAGE_NO_SERVICE);
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/GrpcBescheidMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/GrpcBescheidMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..361143658bca9c57383d2193484b46b4f020955f
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/GrpcBescheidMapper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+@Mapper
+public interface GrpcBescheidMapper {
+
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "bescheidDocument", ignore = true)
+	@Mapping(target = "bescheidDocumentBytes", ignore = true)
+	@Mapping(target = "beschiedenAm", ignore = true)
+	@Mapping(target = "beschiedenAmBytes", ignore = true)
+	@Mapping(target = "nachrichtSubject", ignore = true)
+	@Mapping(target = "nachrichtSubjectBytes", ignore = true)
+	@Mapping(target = "nachrichtTextBytes", ignore = true)
+	@Mapping(target = "sendBy", ignore = true)
+	@Mapping(target = "sendByBytes", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	@Mapping(target = "attachmentsList", ignore = true)
+
+	@Mapping(target = "nachrichtText", source = "nachrichtText")
+	@Mapping(target = "bewilligt", source = "genehmigt")
+	GrpcBescheid fromBescheid(Bescheid bescheid);
+
+	default String fromOptional(Optional<String> optionalString) {
+		return optionalString.orElse(StringUtils.EMPTY);
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/UserId.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/UserId.java
new file mode 100644
index 0000000000000000000000000000000000000000..cda26df4c51a0d59ca0d2184e5882315ed261d7d
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/UserId.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import java.util.Objects;
+
+import de.ozgcloud.common.datatype.StringBasedValue;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+public class UserId extends StringBasedValue {
+
+	UserId(String userId) {
+		super(userId);
+	}
+
+	public static UserId from(String userId) {
+		if (Objects.nonNull(userId)) {
+			return new UserId(userId);
+		}
+		return null;
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/binaryfile/BinaryFileRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/binaryfile/BinaryFileRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..ede39f95bd38b101fe3f037f07077aed1cdad8a9
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/binaryfile/BinaryFileRemoteService.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.binaryfile;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.stereotype.Service;
+
+import com.google.protobuf.ByteString;
+
+import de.ozgcloud.bescheid.Bescheid;
+import de.ozgcloud.common.binaryfile.FileId;
+import de.ozgcloud.common.binaryfile.GrpcFileUploadUtils;
+import de.ozgcloud.common.binaryfile.GrpcFileUploadUtils.FileSender;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceStub;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileMetaData;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcCallContext;
+import io.grpc.stub.CallStreamObserver;
+import io.grpc.stub.StreamObserver;
+import lombok.NonNull;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Service
+class BinaryFileRemoteService {
+
+	private static final String CALL_CONTEXT_CLIENT = "bescheid-manager";
+	private static final String VORGANG_ATTACHMENT_FIELD = "bescheid";
+
+	@GrpcClient("vorgang-manager")
+	private BinaryFileServiceStub binaryFileRemoteStub;
+
+	public FileId uploadBescheidFile(@NonNull Bescheid bescheid) {
+		try (var in = openFile(bescheid.getBescheidFile())) {
+			var resultFuture = GrpcFileUploadUtils.createSender(this::buildChunkRequest, in,
+					this::buildCallStreamObserver)
+					.withMetaData(buildMetaDataRequest(bescheid))
+					.send();
+
+			return FileId.from(waitUntilFutureToComplete(resultFuture, in).getFileId());
+		} catch (IOException e) {
+			throw new TechnicalException("Error on uploading file.", e);
+		}
+	}
+
+	private InputStream openFile(File file) {
+		try {
+			return new FileInputStream(file);
+		} catch (FileNotFoundException e) {
+			throw new TechnicalException("File to upload not found.", e);
+		}
+	}
+
+	private GrpcUploadBinaryFileRequest buildMetaDataRequest(Bescheid bescheid) {
+		return GrpcUploadBinaryFileRequest.newBuilder()
+				.setMetadata(GrpcUploadBinaryFileMetaData.newBuilder()
+						// TODO remove context - check why needed!
+						.setContext(GrpcCallContext.newBuilder().setClient(CALL_CONTEXT_CLIENT).build())
+						.setVorgangId(bescheid.getVorgangId().toString())
+						.setField(VORGANG_ATTACHMENT_FIELD)
+						.setContentType(bescheid.getContentType())
+						.setSize(bescheid.getBescheidFile().length())
+						.setFileName(bescheid.getBescheidFileName())
+						.build())
+				.build();
+	}
+
+	private GrpcUploadBinaryFileRequest buildChunkRequest(byte[] bytes, Integer length) {
+		return GrpcUploadBinaryFileRequest.newBuilder().setFileContent((ByteString.copyFrom(bytes, 0, length))).build();
+	}
+
+	private CallStreamObserver<GrpcUploadBinaryFileRequest> buildCallStreamObserver(
+			StreamObserver<GrpcUploadBinaryFileResponse> responseObserver) {
+		return (CallStreamObserver<GrpcUploadBinaryFileRequest>) binaryFileRemoteStub.uploadBinaryFileAsStream(responseObserver);
+	}
+
+	GrpcUploadBinaryFileResponse waitUntilFutureToComplete(FileSender<GrpcUploadBinaryFileRequest, GrpcUploadBinaryFileResponse> fileSender,
+			InputStream fileContentStream) {
+		try {
+			return fileSender.getResultFuture().get(10, TimeUnit.MINUTES);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+			fileSender.cancelOnError(e);
+			throw new TechnicalException("Waiting for finishing upload was interrupted.", e);
+		} catch (ExecutionException | TimeoutException e) {
+			fileSender.cancelOnTimeout();
+			throw new TechnicalException("Error / Timeout on uploading data.", e);
+		} finally {
+			IOUtils.closeQuietly(fileContentStream);
+		}
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/binaryfile/BinaryFileService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/binaryfile/BinaryFileService.java
new file mode 100644
index 0000000000000000000000000000000000000000..07ef1477b6f687c0444da7bb2405417964428fe8
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/binaryfile/BinaryFileService.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.binaryfile;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.bescheid.Bescheid;
+import lombok.NonNull;
+
+@Service
+public class BinaryFileService {
+
+	@Autowired
+	private BinaryFileRemoteService remoteService;
+
+	public Bescheid uploadBescheidFile(@NonNull Bescheid bescheid) {
+		var fileId = remoteService.uploadBescheidFile(bescheid);
+
+		return bescheid.withBescheidFileId(fileId);
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CallContextAuthenticationToken.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CallContextAuthenticationToken.java
new file mode 100644
index 0000000000000000000000000000000000000000..975d435ceb6cda3f7a7959c007720c04a11f8a3d
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CallContextAuthenticationToken.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.common.callcontext;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+public class CallContextAuthenticationToken extends AbstractAuthenticationToken {
+
+	private final CallContextUser user;
+
+	static CallContextAuthenticationToken authenticate(CallContextUser user) {
+		return new CallContextAuthenticationToken(user);
+	}
+
+	private CallContextAuthenticationToken(CallContextUser user) {
+		super(user.getOrganisatorischeEinheitenIds().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet()));
+		this.user = user;
+		super.setAuthenticated(true);
+	}
+
+	@Override
+	public Object getCredentials() {
+		return null;
+	}
+
+	@Override
+	public Object getPrincipal() {
+		return user;
+	}
+
+	@Override
+	public Collection<GrantedAuthority> getAuthorities() {
+		return user.getOrganisatorischeEinheitenIds().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toUnmodifiableSet());
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CallContextUser.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CallContextUser.java
new file mode 100644
index 0000000000000000000000000000000000000000..d180bf15496491b82cfa840ffb35ff66688fceba
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CallContextUser.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.common.callcontext;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Optional;
+
+import org.springframework.security.core.AuthenticatedPrincipal;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Singular;
+
+@Builder
+@Getter
+public class CallContextUser implements AuthenticatedPrincipal, Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	private final String clientName;
+
+	@Builder.Default
+	private final transient Optional<String> userId = Optional.empty();
+	@Builder.Default
+	private final transient Optional<String> userName = Optional.empty();
+	@Singular
+	private final Collection<String> organisatorischeEinheitenIds;
+	@Builder.Default
+	private final transient boolean organisationEinheitenIdCheckNecessary = false;
+
+	@Override
+	public String getName() {
+		return clientName;
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CurrentUserService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CurrentUserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..458ea68d667987004faaa07f5f2aa01b42666a8c
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/CurrentUserService.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.common.callcontext;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.security.authentication.AuthenticationTrustResolver;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.apilib.user.OzgCloudUserId;
+import de.ozgcloud.apilib.user.OzgCloudUserProfileService;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@Service("bescheid_currentUserService")
+public class CurrentUserService {
+
+	private final AuthenticationTrustResolver trustResolver;
+	private final Optional<OzgCloudUserProfileService> userProfileService;
+	private final UserProfileMapper mapper;
+
+	public CallContextUser getUser() {
+		return findUser().orElseThrow(() -> new IllegalStateException("No authenticated User found"));
+	}
+
+	public UserProfile getUserProfile() {
+		var service = userProfileService.orElseThrow(() -> new IllegalStateException("No connection to user-manager configured."));
+
+		return getUser().getUserId().map(OzgCloudUserId::from)
+				.map(service::getById)
+				.map(mapper::mapProfile).orElseThrow(() -> new TechnicalException("Unknown UserId or cannot load user profile."));
+	}
+
+	public Optional<CallContextUser> findUser() {
+		return findTrustedAuthentication()
+				.map(this::mapToCallContextUser)
+				// remove this filter as soon we have a trusted authentication
+				.filter(user -> StringUtils.isNotBlank(user.getClientName()));
+	}
+
+	private CallContextUser mapToCallContextUser(Authentication auth) {
+		if (auth instanceof CallContextAuthenticationToken) {
+			return (CallContextUser) auth.getPrincipal();
+		} else {
+			return CallContextUser.builder()
+					.clientName(auth.getName())
+					.organisatorischeEinheitenIds(
+							auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toUnmodifiableSet()))
+					.build();
+		}
+	}
+
+	public Optional<Authentication> findAuthentication() {
+		return findTrustedAuthentication();
+	}
+
+	Optional<Authentication> findTrustedAuthentication() {
+		return Optional.ofNullable(SecurityContextHolder.getContext())
+				.map(SecurityContext::getAuthentication)
+				.filter(auth -> !trustResolver.isAnonymous(auth))
+				.filter(Authentication::isAuthenticated);
+	}
+
+	public SecurityContext startSecurityContext(Command command) {
+		var prevContext = SecurityContextHolder.getContext();
+
+		SecurityContextHolder.clearContext();
+		SecurityContextHolder.getContext().setAuthentication(CallContextAuthenticationToken.authenticate(createUser(command)));
+
+		return prevContext;
+	}
+
+	CallContextUser createUser(Command command) {
+		var builder = CallContextUser.builder()
+				.userId(Optional.ofNullable(command.getCreatedBy()))
+				.userName(Optional.ofNullable(command.getCreatedByName()))
+				.clientName("Alfa") // FIXME read client name from command
+				.organisationEinheitenIdCheckNecessary(false);
+
+		return builder.build();
+	}
+
+	public void resetSecurityContext(SecurityContext context) {
+		SecurityContextHolder.clearContext();
+		if (Objects.nonNull(context)) {
+			SecurityContextHolder.setContext(context);
+		}
+	}
+}
\ No newline at end of file
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfile.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfile.java
new file mode 100644
index 0000000000000000000000000000000000000000..0410ae56cdb76738ad539858a8bf8fa12dade1a7
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfile.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.common.callcontext;
+
+import de.ozgcloud.bescheid.UserId;
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class UserProfile {
+
+	private UserId id;
+	private String firstName;
+	private String lastName;
+	private String email;
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfileMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfileMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..e02f8c19148103610af7de962bb22d915f02a660
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfileMapper.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.common.callcontext;
+
+import org.mapstruct.Mapper;
+
+import de.ozgcloud.apilib.user.OzgCloudUserId;
+import de.ozgcloud.apilib.user.OzgCloudUserProfile;
+import de.ozgcloud.bescheid.UserId;
+
+@Mapper
+public interface UserProfileMapper {
+
+	UserProfile mapProfile(OzgCloudUserProfile userProfile);
+
+	default UserId mapUserId(OzgCloudUserId id) {
+		return UserId.from(id.toString());
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfileTestFactory.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfileTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..cabb76f676cc2e100366715e25d69e2b91bfcd52
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/UserProfileTestFactory.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.common.callcontext;
+
+import java.util.UUID;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.bescheid.UserId;
+
+public class UserProfileTestFactory {
+
+	private static final LoremIpsum LOREM_IPSUM = LoremIpsum.getInstance();
+
+	public static final UserId ID = UserId.from(UUID.randomUUID().toString());
+
+	public static final String FIRST_NAME = LOREM_IPSUM.getFirstName();
+	public static final String LAST_NAME = LOREM_IPSUM.getLastName();
+	public static final String EMAIL = "test-email@local";
+
+	public static UserProfile create() {
+		return createBuilder().build();
+	}
+
+	public static UserProfile.UserProfileBuilder createBuilder() {
+		return UserProfile.builder()
+				.id(ID)
+				.firstName(FIRST_NAME)
+				.lastName(LAST_NAME)
+				.email(EMAIL);
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/dummy/DummyBescheidRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/dummy/DummyBescheidRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..2cf1edff97076d6d27272f97c70f190ded27d4ac
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/dummy/DummyBescheidRemoteService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.dummy;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.stereotype.Service;
+
+import com.google.common.net.MediaType;
+
+import de.ozgcloud.bescheid.Bescheid;
+import de.ozgcloud.bescheid.BescheidRemoteService;
+import de.ozgcloud.bescheid.BescheidRequest;
+import de.ozgcloud.bescheid.vorgang.Vorgang;
+import de.ozgcloud.common.binaryfile.TempFileUtils;
+
+@Service
+@ConditionalOnMissingBean(BescheidRemoteService.class)
+class DummyBescheidRemoteService implements BescheidRemoteService {
+
+	private static final String DUMMY_BESCHEID_FILE_NAME = "dummy-bescheid.pdf";
+	private static final String DUMMY_BESCHEID_CONTENT_TYPE = MediaType.PDF.toString();
+
+	@Override
+	public Bescheid create(BescheidRequest request, Vorgang vorgang) {
+		var file = TempFileUtils.writeTmpFile(this.getClass().getClassLoader().getResourceAsStream(DUMMY_BESCHEID_FILE_NAME));
+
+		return Bescheid.builder()
+				.bescheidFile(file)
+				.bescheidFileName(DUMMY_BESCHEID_FILE_NAME)
+				.contentType(DUMMY_BESCHEID_CONTENT_TYPE)
+				.size(file.length())
+				.createdBy(request.getCreateFor().getId())
+				.build();
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/Nachricht.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/Nachricht.java
new file mode 100644
index 0000000000000000000000000000000000000000..730ad8c6fbfa16dde0b7c41ff20c4af5e7e70a4c
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/Nachricht.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import java.time.ZonedDateTime;
+
+import de.ozgcloud.bescheid.UserId;
+import de.ozgcloud.bescheid.vorgang.Vorgang;
+import de.ozgcloud.bescheid.vorgang.VorgangId;
+import de.ozgcloud.common.binaryfile.FileId;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NonNull;
+
+@Getter
+@Builder
+public class Nachricht {
+
+	private NachrichtId id;
+	private VorgangId vorgangId;
+
+	@NonNull
+	private String subject;
+	@NonNull
+	private String mailBody;
+
+	private FileId bescheidFileId;
+
+	@NonNull
+	private UserId createdBy;
+	@Builder.Default
+	private ZonedDateTime createdAt = ZonedDateTime.now();
+
+	private Vorgang.PostfachAddress postfachAddress;
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtId.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtId.java
new file mode 100644
index 0000000000000000000000000000000000000000..281704f2dc6c0088d07cce55c358533be85a84a2
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtId.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import de.ozgcloud.common.datatype.StringBasedValue;
+
+public class NachrichtId extends StringBasedValue {
+
+	NachrichtId(String nachrichtId) {
+		super(nachrichtId);
+	}
+
+	public static NachrichtId from(String nachrichtId) {
+		return new NachrichtId(nachrichtId);
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc03092f075ceaadd2f3f5c33af4a28e10b4e7de
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtMapper.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import org.mapstruct.CollectionMappingStrategy;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.NullValueCheckStrategy;
+import org.mapstruct.ReportingPolicy;
+
+import de.ozgcloud.bescheid.UserId;
+import de.ozgcloud.bescheid.vorgang.Vorgang;
+import de.ozgcloud.common.binaryfile.FileId;
+import de.ozgcloud.nachrichten.postfach.GrpcPostfachNachricht;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress;
+
+@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, //
+		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, unmappedTargetPolicy = ReportingPolicy.ERROR, uses = { GrpcObjectMapper.class })
+public interface NachrichtMapper {
+
+	@Mapping(target = "createdAtBytes", ignore = true)
+	@Mapping(target = "mergePostfachAddress", ignore = true)
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "idBytes", ignore = true)
+	@Mapping(target = "mailBodyBytes", ignore = true)
+	@Mapping(target = "replyOptionBytes", ignore = true)
+	@Mapping(target = "subjectBytes", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+
+	@Mapping(target = "id", ignore = true)
+	@Mapping(target = "attachmentList", source = "bescheidFileId")
+	@Mapping(target = "replyOption", constant = "FORBIDDEN")
+	GrpcPostfachNachricht mapToGrpc(Nachricht nachricht);
+
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "mergeIdentifier", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "versionBytes", ignore = true)
+	@Mapping(target = "allFields", ignore = true)
+	GrpcPostfachAddress mapAddress(Vorgang.PostfachAddress address);
+
+	default String mapToString(FileId fileId) {
+		return fileId.toString();
+	}
+
+	default String mapToString(UserId userId) {
+		return userId.toString();
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0578be2dd1283a65c55799b819ccafd4203e2537
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtRemoteService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.nachrichten.postfach.GrpcSaveNachrichtDraftRequest;
+import de.ozgcloud.nachrichten.postfach.PostfachServiceGrpc.PostfachServiceBlockingStub;
+import io.grpc.ClientInterceptor;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Service
+class NachrichtRemoteService {
+
+	@GrpcClient("nachrichten-manager")
+	private PostfachServiceBlockingStub serviceStub;
+
+	@Autowired
+	private NachrichtMapper mapper;
+
+	@Autowired
+	private ClientInterceptor bescheidCallContextInterceptor;
+
+	public void saveDraft(Nachricht nachricht) {
+		serviceStub.withInterceptors(bescheidCallContextInterceptor)
+				.saveNachrichtDraft(buildRequest(nachricht));
+	}
+
+	GrpcSaveNachrichtDraftRequest buildRequest(Nachricht nachricht) {
+		return GrpcSaveNachrichtDraftRequest.newBuilder()
+				.setVorgangId(nachricht.getVorgangId().toString())
+				.setNachricht(mapper.mapToGrpc(nachricht))
+				.build();
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtService.java
new file mode 100644
index 0000000000000000000000000000000000000000..74606a932ad3ec76ed118b6e15ec2796e85a5c05
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/nachricht/NachrichtService.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.bescheid.Bescheid;
+import de.ozgcloud.bescheid.vorgang.Vorgang.PostfachAddress;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import lombok.extern.log4j.Log4j2;
+
+@Service
+@Log4j2
+public class NachrichtService {
+
+	@Autowired
+	private NachrichtRemoteService remoteService;
+
+	@Autowired
+	private Configuration freemarkerCfg;
+
+	static final String SUBJECT = "Ihr Antrag";
+
+	private static final String TEMPLATE_FILE = "bescheid.nachrichtTemplate.txt.ftlh";
+
+	public void createNachrichtDraft(Bescheid bescheid) {
+		buildNachricht(bescheid).ifPresentOrElse(remoteService::saveDraft, () -> LOG.warn("No ServiceKonto given on Vorgang."));
+	}
+
+	Optional<Nachricht> buildNachricht(Bescheid bescheid) {
+		return getAddress(bescheid).map(address -> Nachricht.builder()
+				.vorgangId(bescheid.getVorgangId())
+				.postfachAddress(address)
+				.subject(SUBJECT)
+				.mailBody(buildMessage(bescheid))
+				.createdBy(bescheid.getCreatedBy())
+				.bescheidFileId(bescheid.getBescheidFileId())
+				.build());
+	}
+
+	Optional<PostfachAddress> getAddress(Bescheid bescheid) {
+		var serviceKonto = bescheid.getServiceKonto();
+		if (Objects.nonNull(serviceKonto)) {
+			return Optional.of(serviceKonto.getPostfachAddresses().get(0));
+		}
+		return Optional.empty();
+	}
+
+	String buildMessage(Bescheid bescheid) {
+		return bescheid.getNachrichtText()
+				.orElseGet(() -> fillTemplate(TEMPLATE_FILE, bescheid));
+	}
+
+	String fillTemplate(String templateName, Object dataModel) {
+		try {
+			Template template = getTemplate(templateName);
+			StringWriter stringWriter = new StringWriter();
+			template.process(dataModel, stringWriter);
+			return stringWriter.toString();
+
+		} catch (IOException | TemplateException e) {
+			throw new TechnicalException("Error filling template", e);
+		}
+	}
+
+	Template getTemplate(String templateName) {
+		try {
+			return freemarkerCfg.getTemplate(templateName);
+		} catch (IOException e) {
+			throw new TechnicalException("Error loading mail template", e);
+		}
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..2e6e0efe723f40feae30328b1bd1375514fe39f0
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteService.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.smartdocuments;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Optional;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.http.HttpStatusCode;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Service;
+import org.springframework.web.reactive.function.BodyExtractors;
+import org.springframework.web.reactive.function.client.ClientResponse;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.w3c.dom.Text;
+import org.xml.sax.SAXException;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+import de.ozgcloud.bescheid.Bescheid;
+import de.ozgcloud.bescheid.BescheidRemoteService;
+import de.ozgcloud.bescheid.BescheidRequest;
+import de.ozgcloud.bescheid.common.callcontext.UserProfile;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsBescheidRemoteService.SmartDocumentsResponse.SmartDocumentDocument;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsBescheidRemoteService.SmartDocumentsResponse.SmartDocumentFile;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.CustomerData;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.CustomerData.BescheidData;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.CustomerData.UserData;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.SmartDocument.Selection;
+import de.ozgcloud.bescheid.vorgang.Vorgang;
+import de.ozgcloud.common.binaryfile.FileDataDeserializer;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+import reactor.core.publisher.Mono;
+
+@Log4j2
+@Service
+@ConditionalOnProperty("ozgcloud.bescheid.smart-documents.url")
+class SmartDocumentsBescheidRemoteService implements BescheidRemoteService {
+
+	private static final String FILE_TYPE_PDF = "PDF";
+	private static final String FILE_TYPE_XML = "XML";
+
+	@SuppressWarnings("deprecation") // SD requires forced UTF-8 encoding
+	private static final MediaType JSON_MEDIA_TYPE_FOR_SD = MediaType.APPLICATION_JSON_UTF8;
+
+	@Autowired
+	@Qualifier("smartDocuments")
+	private WebClient smartDocumentsWebClient;
+
+	@Autowired
+	private SmartDocumentsProperties properties;
+
+	@Override
+	public Bescheid create(BescheidRequest request, Vorgang vorgang) {
+		var sdRequest = createRequest(request, vorgang);
+		LOG.debug(() -> buildLogRequest(sdRequest));
+
+		return smartDocumentsWebClient.post().accept(MediaType.APPLICATION_JSON)
+				.contentType(JSON_MEDIA_TYPE_FOR_SD)
+				.bodyValue(sdRequest)
+				.retrieve()
+				.onStatus(HttpStatusCode::is4xxClientError, this::handleClientError)
+				.bodyToMono(SmartDocumentsResponse.class)
+				.map(response -> buildBescheid(request, response))
+				.block();
+	}
+
+	Mono<Throwable> handleClientError(ClientResponse response) {
+		return response.body(BodyExtractors.toMono(String.class))
+				.map(content -> new TechnicalException("Client-Error: " + content));
+	}
+
+	private String buildLogRequest(SmartDocumentsRequest request) {
+		try {
+			ObjectMapper oj = new ObjectMapper();
+			return oj.writerWithDefaultPrettyPrinter().writeValueAsString(request);
+		} catch (Exception e) {
+			LOG.warn("Error writing request as json-string for logging.", e);
+			return "Error generating logging string";
+		}
+	}
+
+	Bescheid buildBescheid(BescheidRequest request, SmartDocumentsResponse smartDocumentsResponse) {
+		var smartDocumentsFile = getSmartDocumentsFile(smartDocumentsResponse);
+
+		return Bescheid.builder()
+				.bescheidFile(smartDocumentsFile.getDocument().getData())
+				.bescheidFileName(smartDocumentsFile.getFilename())
+				.size(smartDocumentsFile.getDocument().getData().length())
+				.contentType(MediaType.APPLICATION_PDF_VALUE)
+				.nachrichtText(getNachrichtText(smartDocumentsResponse))
+				.genehmigt(request.isGenehmigt())
+				.createdBy(request.getCreateFor().getId())
+				.vorgangId(request.getVorgangId())
+				.build();
+	}
+
+	private SmartDocumentFile getSmartDocumentsFile(SmartDocumentsResponse response) {
+		return getSmartDocumentsFile(response, FILE_TYPE_PDF)
+				.orElseThrow(() -> new IllegalStateException("No PDF File in SmartDocuments Response found."));
+	}
+
+	Optional<String> getNachrichtText(SmartDocumentsResponse response) {
+		return getXMLFile(response).flatMap(this::extractTextFormXmlFile);
+	}
+
+	Optional<String> extractTextFormXmlFile(File xmlFile) {
+		var xPath = XPathFactory.newInstance().newXPath();
+		try {
+			var document = DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder().parse(xmlFile);
+			var expr = xPath.compile("/root/SmartDocument/Fields/NachrichtenText/text()");
+			var text = (Text) expr.evaluate(document, XPathConstants.NODE);
+
+			return Optional.of(text.getTextContent());
+		} catch (XPathExpressionException | SAXException | IOException | ParserConfigurationException e) {
+			LOG.error("XML-Parsing error on extracting Nachricht-Text: {}", e.getMessage(), e);
+		} catch (ClassCastException e) {
+			LOG.error("Error on extraction Nachricht-Text. XPath return unexpected Type.", e);
+		} catch (RuntimeException e) {
+			LOG.error("Unexpected Error on extracting NachrichtText: {}", e.getMessage(), e);
+		}
+		return Optional.empty();
+	}
+
+	Optional<File> getXMLFile(SmartDocumentsResponse response) {
+		return getSmartDocumentsFile(response, FILE_TYPE_XML)
+				.map(SmartDocumentFile::getDocument)
+				.map(SmartDocumentDocument::getData);
+	}
+
+	Optional<SmartDocumentFile> getSmartDocumentsFile(SmartDocumentsResponse response, String fileType) {
+		return response.getFile().stream()
+				.filter(file -> file.getOutputFormat().equals(fileType))
+				.findFirst();
+	}
+
+	SmartDocumentsRequest createRequest(BescheidRequest request, Vorgang vorgang) {
+		return logRequest(SmartDocumentsRequest.builder()
+				.smartDocument(buildSDSection(vorgang))
+				.customerData(
+						CustomerData.builder()
+								.vorgang(vorgang)
+								.userData(buildUserData(request.getCreateFor()))
+								.bescheid(BescheidData.builder().bescheidVom(request.getBescheidVom()).genehmigt(request.isGenehmigt()).build())
+								.build())
+
+				.build());
+	}
+
+	private UserData buildUserData(UserProfile userProfile) {
+		return UserData.builder()
+				.firstName(userProfile.getFirstName())
+				.lastName(userProfile.getLastName())
+				.email(userProfile.getEmail())
+				.build();
+	}
+
+	private SmartDocumentsRequest.SmartDocument buildSDSection(Vorgang vorgang) {
+		return SmartDocumentsRequest.SmartDocument.builder().selection(Selection.builder()
+				.templateGroup(properties.getTemplateGroup())
+				.template(vorgang.getVorgangName())
+				.build())
+				.build();
+	}
+
+	private SmartDocumentsRequest logRequest(SmartDocumentsRequest request) {
+		LOG.debug(() -> {
+			var ojMapper = new ObjectMapper();
+			try {
+				return ojMapper.writeValueAsString(request);
+			} catch (JsonProcessingException e) {
+				LOG.warn("Json Processing Exception on logging request.", e);
+				return request.toString();
+			}
+		});
+
+		return request;
+	}
+
+	@Builder
+	@Getter
+	@NoArgsConstructor
+	@AllArgsConstructor
+	static class SmartDocumentsResponse {
+		Collection<SmartDocumentFile> file;
+
+		@Builder
+		@Getter
+		@NoArgsConstructor
+		@AllArgsConstructor
+		static class SmartDocumentFile {
+			private String filename;
+			private SmartDocumentDocument document;
+			private String outputFormat;
+		}
+
+		@Builder
+		@Getter
+		@NoArgsConstructor
+		@AllArgsConstructor
+		static class SmartDocumentDocument {
+			@JsonDeserialize(using = FileDataDeserializer.class)
+			private File data;
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsConfiguration.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..bec4a85cdbba36d966b92599e04b71449efb307a
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsConfiguration.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.smartdocuments;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.ExchangeFilterFunctions;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import reactor.netty.http.client.HttpClient;
+import reactor.netty.transport.ProxyProvider;
+
+@Configuration
+@ConditionalOnProperty("ozgcloud.bescheid.smart-documents.url")
+class SmartDocumentsConfiguration {
+
+	@Autowired
+	private SmartDocumentsProperties properties;
+
+	@Bean("smartDocuments")
+	WebClient smartDocumentsWebClient() {
+		ReactorClientHttpConnector connector = new ReactorClientHttpConnector(buildHttpClient());
+
+		return WebClient.builder()
+				.baseUrl(properties.getUrl())
+				.filter(ExchangeFilterFunctions.basicAuthentication(properties.getBasicAuth().getUsername(), properties.getBasicAuth().getPassword()))
+				.clientConnector(connector)
+				.build();
+	}
+
+	private HttpClient buildHttpClient() {
+		if (properties.getProxy() != null) {
+			return createProxyHttpClient();
+		} else {
+			return createNoProxyHttpClient();
+		}
+	}
+
+	private HttpClient createNoProxyHttpClient() {
+		return HttpClient.create();
+	}
+
+	private HttpClient createProxyHttpClient() {
+		return HttpClient.create()
+				.proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP)
+						.host(properties.getProxy().getHost())
+						.port(properties.getProxy().getPort())
+						.username(properties.getProxy().getUsername())
+						.password(username -> properties.getProxy().getPassword()));
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsProperties.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..213782ca18a351dc7e0b13bc055b1fd8a9fad1cb
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsProperties.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.smartdocuments;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+
+import org.apache.logging.log4j.core.config.plugins.validation.constraints.NotBlank;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@ConditionalOnProperty("ozgcloud.bescheid.smart-documents.url")
+@Validated
+@Getter
+@Setter
+@Configuration
+@ConfigurationProperties("ozgcloud.bescheid.smart-documents")
+public class SmartDocumentsProperties {
+
+	/**
+	 * Location of the Smart Documents Server
+	 */
+	@NotBlank
+	private String url;
+
+	/**
+	 * Credential for basic auth to the Smart Documents Server
+	 */
+	@NotNull
+	@Valid
+	private UsernamePassword basicAuth;
+
+	/**
+	 * Smart Documents Template Group
+	 */
+	@NotBlank
+	private String templateGroup;
+	/**
+	 * Smart Documents Template
+	 */
+	@NotBlank
+	private String template;
+
+	/**
+	 * Proxy Configuration if required.
+	 */
+	private ProxyConfiguration proxy;
+
+	@Getter
+	@Setter
+	static class UsernamePassword {
+		/**
+		 * Username for authentication
+		 */
+		@NotBlank
+		private String username;
+		/**
+		 * Password for authentication
+		 */
+		@NotBlank
+		private String password;
+	}
+
+	@Getter
+	@Setter
+	static class ProxyConfiguration {
+		/**
+		 * Host Address of the proxy server with protocol
+		 */
+		@NotBlank
+		private String host;
+		/**
+		 * Port Number of the proxy server
+		 */
+		private int port = 8080;
+		/**
+		 * Username for Authentication for the proxy server
+		 */
+		private String username;
+		/**
+		 * Username for Authentication for the proxy server
+		 */
+		private String password;
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsRequest.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..27f5364883a1695919ac5f46374ff1dfcbe3f89e
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsRequest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.smartdocuments;
+
+import java.time.LocalDate;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.PropertyNamingStrategies;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+
+import de.ozgcloud.bescheid.vorgang.Vorgang;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.ToString;
+
+@Builder
+@Getter
+@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
+@ToString
+class SmartDocumentsRequest {
+
+	@Builder.Default
+	private CustomerData customerData = CustomerData.builder().build();
+	@Builder.Default
+	private SmartDocument smartDocument = SmartDocument.builder().build();
+
+	@Builder
+	@Getter
+	static class CustomerData {
+		private Vorgang vorgang;
+		private BescheidData bescheid;
+		private UserData userData;
+
+		@Builder
+		@Getter
+		static class BescheidData {
+			private LocalDate bescheidVom;
+			private boolean genehmigt;
+		}
+
+		@Builder
+		@Getter
+		static class UserData {
+			private String firstName;
+			private String lastName;
+			private String email;
+		}
+	}
+
+	@Builder
+	@Getter
+	@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
+	static class SmartDocument {
+
+		@Builder.Default
+		@JsonProperty("Selection")
+		private Selection selection = Selection.builder().build();
+
+		@Builder
+		@Getter
+		@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class)
+		static class Selection {
+			@Builder.Default
+			private String templateGroup = "Kiel";
+			@Builder.Default
+			private String template = "Halteverbot";
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/BescheidVorgangMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/BescheidVorgangMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..2084c41af13e789546a99f5db8ee40b96839890e
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/BescheidVorgangMapper.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.ReportingPolicy;
+import org.mapstruct.factory.Mappers;
+
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.vorgang.GrpcEingang;
+import de.ozgcloud.vorgang.vorgang.GrpcFormData;
+import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress;
+import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangWithEingang;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR, //
+		uses = { FormDataEntryMapper.class, GrpcObjectMapper.class })
+interface BescheidVorgangMapper {
+
+	@Mapping(target = "serviceKonto", source = "header.serviceKonto")
+	@Mapping(target = "vorgangNummer", source = "nummer")
+	@Mapping(target = "vorgangName", source = "name")
+	Vorgang mapVorgang(GrpcVorgangWithEingang vorgang);
+
+	@Mapping(target = "postfachAddress", ignore = true)
+	@Mapping(target = "postfachAddresses", source = "postfachAddressesList")
+	Vorgang.ServiceKonto mapServiceKonto(GrpcServiceKonto serviceKonto);
+
+	Vorgang.PostfachAddress mapAddress(GrpcPostfachAddress address);
+
+	VorgangId mapVorgangId(String vorgangId);
+
+	Vorgang.Eingang mapEingang(GrpcEingang eingang);
+
+	default Collection<FormDataEntry> mapFormData(GrpcFormData value) {
+		var result = new ArrayList<FormDataEntry>();
+		var entryMapper = Mappers.getMapper(FormDataEntryMapper.class);
+
+		result.addAll(value.getFieldList().stream().map(entryMapper::fromGrpc).toList());
+		result.addAll(value.getFormList().stream().map(entryMapper::fromGrpc).toList());
+
+		return Collections.unmodifiableList(result);
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntry.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..16c04143f71dab853cff2ee82c53bdcbf6c51002
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntry.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Singular;
+
+@JsonSerialize(using = FormDataEntrySerializer.class)
+public interface FormDataEntry {
+
+	String getName();
+	@JsonIgnore
+	String getLabel();
+
+	@JsonIgnore
+	default boolean isSubForm() {
+		return false;
+	}
+
+	@JsonIgnore
+	default boolean isFormEntry() {
+		return false;
+	}
+
+	@Builder
+	@Getter
+	static class SubForm implements FormDataEntry {
+
+		private String name;
+		@JsonIgnore
+		private String label;
+
+		@Singular
+		private List<FormDataEntry> entries;
+
+		@JsonIgnore
+		@Override
+		public boolean isSubForm() {
+			return true;
+		}
+	}
+
+	@Builder
+	@Getter
+	static class FormField implements FormDataEntry {
+
+		private String name;
+		@JsonIgnore
+		private String label;
+
+		private Object value;
+
+		@JsonIgnore
+		@Override
+		public boolean isFormEntry() {
+			return true;
+		}
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntryMapper.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntryMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a36897ec4d57a05a4d0c2176b7138f806af4550
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntryMapper.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Named;
+import org.mapstruct.ReportingPolicy;
+
+import de.ozgcloud.bescheid.vorgang.FormDataEntry.FormField;
+import de.ozgcloud.bescheid.vorgang.FormDataEntry.SubForm;
+import de.ozgcloud.vorgang.vorgang.GrpcFormField;
+import de.ozgcloud.vorgang.vorgang.GrpcSubForm;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
+public interface FormDataEntryMapper {
+
+	@Mapping(target = "entries", source = ".", qualifiedByName = "mapEntrys")
+	@Mapping(target = "entry", ignore = true)
+	@Mapping(target = "name", source = "title")
+	SubForm fromGrpc(GrpcSubForm subForm);
+
+	FormField fromGrpc(GrpcFormField field);
+
+	@Named("mapEntrys")
+	default List<FormDataEntry> mapEntrys(GrpcSubForm subForm) {
+		var fieldStream = subForm.getFieldList().stream().map(this::fromGrpc);
+		var subFormsStream = subForm.getSubFormList().stream().map(this::fromGrpc);
+
+		return Stream.concat(fieldStream, subFormsStream).toList();
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntrySerializer.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntrySerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe3bd2ff129e8bb6d047a83e7c796c9d2fcee7ac
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/FormDataEntrySerializer.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+import de.ozgcloud.bescheid.vorgang.FormDataEntry.FormField;
+import de.ozgcloud.bescheid.vorgang.FormDataEntry.SubForm;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+
+public class FormDataEntrySerializer extends StdSerializer<FormDataEntry> {
+
+	public FormDataEntrySerializer() {
+		super(FormDataEntry.class);
+	}
+
+	@Override
+	public void serialize(FormDataEntry value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+
+		if (value.isFormEntry()) {
+			var formEntry = (FormField) value;
+			Optional.ofNullable(formEntry.getValue()).map(Object::toString).filter(StringUtils::isNoneBlank)
+					.ifPresent(val -> writeStringField(value.getName(), val, gen));
+		}
+		if (value.isSubForm()) {
+			gen.writeFieldName(value.getName());
+			gen.writeStartObject();
+			var subForm = (SubForm) value;
+
+			subForm.getEntries().forEach(entry -> writeObject(entry, gen));
+			gen.writeEndObject();
+		}
+	}
+
+	private void writeStringField(String name, String value, JsonGenerator gen) {
+		try {
+			gen.writeStringField(name, value);
+		} catch (IOException e) {
+			throw new TechnicalException("Error writing string field in json.", e);
+		}
+	}
+
+	static void writeObject(Object pojo, JsonGenerator jgen) {
+		try {
+			jgen.writeObject(pojo);
+		} catch (IOException e) {
+			throw new TechnicalException("Error on writing object to json.", e);
+		}
+	}
+}
+
+class FormDataEntryListSerializer extends StdSerializer<List<FormDataEntry>> {
+
+	public FormDataEntryListSerializer() {
+		super(List.class, true);
+	}
+
+	@Override
+	public void serialize(List<FormDataEntry> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+		gen.writeStartObject();
+
+		value.forEach(entry -> defaultSerializeValue(entry, gen, provider));
+		gen.writeEndObject();
+	}
+
+	private void defaultSerializeValue(Object value, JsonGenerator jgen, SerializerProvider provider) {
+		try {
+			var serializer = provider.findValueSerializer(FormDataEntry.class);
+			serializer.serialize(value, jgen, provider);
+		} catch (IOException e) {
+			throw new TechnicalException("Error serializing value.", e);
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/Vorgang.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/Vorgang.java
new file mode 100644
index 0000000000000000000000000000000000000000..d10b0b943d4492feade64acb84dfac49de920159
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/Vorgang.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import java.util.List;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Singular;
+import lombok.ToString;
+
+@Builder
+@Getter
+@ToString
+public class Vorgang {
+
+	@JsonIgnore
+	private VorgangId id;
+
+	private String vorgangName;
+
+	private String vorgangNummer;
+	private String aktenzeichen;
+
+	@JsonIgnore
+	@ToString.Exclude
+	private ServiceKonto serviceKonto;
+	@ToString.Exclude
+	private Eingang eingang;
+
+	@Builder
+	@Getter
+	public static class ServiceKonto {
+		private String type;
+		@Singular
+		private List<PostfachAddress> postfachAddresses;
+	}
+
+	@Builder
+	@Getter
+	public static class PostfachAddress {
+		private String version;
+		private int type;
+		private Map<String, Object> identifier;
+	}
+
+	@Builder
+	@Getter
+	static class Eingang {
+		private Antragsteller antragsteller;
+		private ZustaendigeStelle zustaendigeStelle;
+
+		@Singular("formData")
+		@JsonSerialize(using = FormDataEntryListSerializer.class)
+		private List<FormDataEntry> formData;
+	}
+
+	@Builder
+	@Getter
+	@JsonInclude(Include.NON_EMPTY)
+	static class Antragsteller {
+		private String anrede;
+		private String nachname;
+		private String vorname;
+		private String geburtsdatum;
+		private String geburtsort;
+		private String geburtsname;
+		private String email;
+		private String telefon;
+		private String strasse;
+		private String hausnummer;
+		private String plz;
+		private String ort;
+	}
+
+	@Builder
+	@Getter
+	static class ZustaendigeStelle {
+		private String organisationseinheitenId;
+		private String email;
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangId.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangId.java
new file mode 100644
index 0000000000000000000000000000000000000000..3603e7f02e95a6a7f9fad1438cb99da6b4fbffd7
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangId.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import de.ozgcloud.common.datatype.StringBasedValue;
+
+public class VorgangId extends StringBasedValue {
+
+	VorgangId(String vorgangId) {
+		super(vorgangId);
+	}
+
+	public static VorgangId from(String vorgangId) {
+		return new VorgangId(vorgangId);
+	}
+
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangRemoteService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..147de6d87627dedcdd0a7191e2acffb7f42c2566
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangRemoteService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
+import io.grpc.ClientInterceptor;
+import lombok.NonNull;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Service("bescheid_VorgangRemoteService")
+class VorgangRemoteService {
+
+	@GrpcClient("vorgang-manager")
+	private VorgangServiceBlockingStub vorgangServiceStub;
+	@Autowired
+	private BescheidVorgangMapper mapper;
+
+	@Autowired
+	private ClientInterceptor bescheidCallContextInterceptor;
+
+	public Vorgang getById(@NonNull VorgangId vorgangId) {
+		var request = GrpcFindVorgangWithEingangRequest.newBuilder().setId(vorgangId.toString()).build();
+		var response = vorgangServiceStub
+				.withInterceptors(bescheidCallContextInterceptor)
+				.findVorgangWithEingang(request);
+
+		return mapper.mapVorgang(response.getVorgangWithEingang());
+	}
+}
diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangService.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangService.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8d9c881c24d7d788fa9e0ac07c129a27a5253c5
--- /dev/null
+++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/vorgang/VorgangService.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import lombok.NonNull;
+
+@Service("bescheid_VorgangService")
+public class VorgangService {
+
+	@Autowired
+	public VorgangRemoteService remoteService;
+
+	public Vorgang getById(@NonNull VorgangId id) {
+		return remoteService.getById(id);
+	}
+}
diff --git a/bescheid-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/bescheid-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000000000000000000000000000000000..539db3df5fe335ab29e56648cc3f3ee374821b85
--- /dev/null
+++ b/bescheid-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,8 @@
+net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientMetricAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientHealthAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientSecurityAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientTraceAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcDiscoveryClientAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonTraceAutoConfiguration
diff --git a/bescheid-manager/src/main/resources/dummy-bescheid.pdf b/bescheid-manager/src/main/resources/dummy-bescheid.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..38e37a52ebeddf42ace077231b0a015ece6ef7ea
Binary files /dev/null and b/bescheid-manager/src/main/resources/dummy-bescheid.pdf differ
diff --git a/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh b/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh
new file mode 100644
index 0000000000000000000000000000000000000000..861bcc67d7f7cffdd9fc2608a6378b8baf23454b
--- /dev/null
+++ b/bescheid-manager/src/main/resources/templates/bescheid.nachrichtTemplate.txt.ftlh
@@ -0,0 +1,8 @@
+Sehr geehrte/r Antragstellende/r,
+
+ihr Antrag wurde <#if genehmigt>genehmigt<#else>abgelehnt</#if>.
+
+Sie können innerhalb von vier Wochen Einspruch einlegen.
+
+Mit freundlichen Grüßen,
+Ihre Verwaltung
\ No newline at end of file
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf35de70fd173a59e580c80b135cc76e0fc44bee
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.command.CommandTestFactory;
+
+@ITCase
+class BescheidEventListenerITCase {
+
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	@MockBean
+	private BescheidService service;
+
+	@Nested
+	class TestCreateBescheid {
+
+		private Command command = CommandTestFactory.createBuilder().order(BescheidEventListener.ORDER).build();
+
+		@Test
+		void shouldCallService() {
+			publisher.publishEvent(CommandCreatedEventTestFactory.withCommand(command));
+
+			verify(service).createBescheid(any());
+		}
+
+		@Test
+		void shouldNotReactOnOtherOrder() {
+			publisher.publishEvent(CommandCreatedEventTestFactory.withCommand(CommandTestFactory.createBuilder().order("OTHER").build()));
+
+			verifyNoInteractions(service);
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d745698eaadb7927bd83060aef8295064aee6c8
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import static de.ozgcloud.bescheid.BescheidEventListener.*;
+import static de.ozgcloud.bescheid.BescheidRequestTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.security.core.context.SecurityContext;
+
+import de.ozgcloud.bescheid.binaryfile.BinaryFileService;
+import de.ozgcloud.bescheid.common.callcontext.CurrentUserService;
+import de.ozgcloud.bescheid.common.callcontext.UserProfile;
+import de.ozgcloud.bescheid.common.callcontext.UserProfileTestFactory;
+import de.ozgcloud.bescheid.nachricht.NachrichtService;
+import de.ozgcloud.bescheid.vorgang.VorgangId;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandTestFactory;
+
+class BescheidEventListenerTest {
+
+	@Spy
+	@InjectMocks
+	private BescheidEventListener listener;
+
+	@Mock
+	private BescheidService service;
+	@Mock
+	private BinaryFileService fileService;
+	@Mock
+	private NachrichtService nachrichtService;
+
+	@Mock
+	private ApplicationEventPublisher eventPublisher;
+	@Mock
+	private CurrentUserService userService;
+
+	@Nested
+	class TestOnCreateBescheidCommand {
+
+		private Command command = CommandTestFactory.createBuilder()
+				.bodyObject(
+						Map.of(VORGANG_ID_BODYKEY, VORGANG_ID.toString(),
+								BESCHEID_VOM_BODYKEY, BESCHEID_VOM_STRING,
+								GENEHMIGT_BODYKEY, GENEHMIGT))
+				.build();
+
+		@Mock
+		private SecurityContext secContext;
+
+		@Test
+		void shouldCreateBescheid() {
+			listener.onCreateBescheidCommand(CommandCreatedEventTestFactory.withCommand(command));
+
+			verify(listener).doCreateBescheidBiz(command);
+		}
+
+		@Test
+		void shouldPublishErrorEventOnException() {
+			doThrow(new RuntimeException("ups")).when(listener).doCreateBescheidBiz(any());
+
+			listener.onCreateBescheidCommand(CommandCreatedEventTestFactory.withCommand(command));
+
+			verify(eventPublisher).publishEvent(any(CommandFailedEvent.class));
+		}
+
+		@Nested
+		class HandleSecurityContext {
+
+			@BeforeEach
+			void init() {
+				when(userService.startSecurityContext(any())).thenReturn(secContext);
+			}
+
+			@Test
+			void shouldStartSecurityContext() {
+				listener.onCreateBescheidCommand(CommandCreatedEventTestFactory.withCommand(command));
+
+				verify(userService).startSecurityContext(command);
+			}
+
+			@Test
+			void shouldResetSecurityContext() {
+				listener.onCreateBescheidCommand(CommandCreatedEventTestFactory.withCommand(command));
+
+				verify(userService).resetSecurityContext(secContext);
+			}
+
+			@Test
+			void shouldResetSecurityContextAfterException() {
+				doThrow(new RuntimeException("ups")).when(listener).doCreateBescheidBiz(any());
+
+				listener.onCreateBescheidCommand(CommandCreatedEventTestFactory.withCommand(command));
+
+				verify(userService).resetSecurityContext(secContext);
+			}
+		}
+
+		@Nested
+		class CreateBescheidRequest {
+			@Test
+			void shouldContainUserProfile() {
+				UserProfile user = UserProfileTestFactory.create();
+				when(userService.getUserProfile()).thenReturn(user);
+
+				var request = listener.createRequest(command);
+
+				assertThat(request.getCreateFor()).isSameAs(user);
+			}
+		}
+
+		@Nested
+		class CreateBescheid {
+
+			@Captor
+			private ArgumentCaptor<BescheidRequest> requestCaptor;
+
+			private Bescheid bescheid = BescheidTestFactory.create();
+			private Bescheid bescheidWithFileId = BescheidTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			when(service.createBescheid(any())).thenReturn(bescheid);
+			when(fileService.uploadBescheidFile(any())).thenReturn(bescheidWithFileId);
+			when(userService.getUserProfile()).thenReturn(UserProfileTestFactory.create());
+		}
+
+			@Test
+			void shouldCreateBescheid() {
+				listener.doCreateBescheidBiz(command);
+
+				verify(service).createBescheid(requestCaptor.capture());
+				assertThat(requestCaptor.getValue()).usingRecursiveComparison()
+						.isEqualTo(BescheidRequestTestFactory.createBuilder()
+								.vorgangId(VorgangId.from(CommandTestFactory.VORGANG_ID))
+								.build());
+			}
+
+			@Test
+			void shouldSaveFile() {
+				listener.doCreateBescheidBiz(command);
+
+				verify(fileService).uploadBescheidFile(bescheid);
+			}
+
+			@Test
+			void shouldSaveNachricht() {
+				listener.doCreateBescheidBiz(command);
+
+				verify(nachrichtService).createNachrichtDraft(bescheidWithFileId);
+			}
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidGrpcServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidGrpcServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4b769376700aad0438ecd670af3cd3bbd73b765
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidGrpcServiceTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import io.grpc.stub.StreamObserver;
+
+class BescheidGrpcServiceTest {
+
+	@Spy
+	@InjectMocks
+	private BescheidGrpcService service;
+
+	@Mock
+	private GrpcBescheidMapper mapper;
+
+	@BeforeEach
+	void initMapperMock() {
+		when(mapper.fromBescheid(any())).thenReturn(GrpcBescheidTestFactory.create());
+	}
+
+	@Nested
+	class TestGetBescheidDraft {
+
+		@Mock
+		private GrpcGetBescheidDraftRequest request;
+		@Mock
+		private StreamObserver<GrpcGetBescheidDraftResponse> responseObserver;
+
+		private static final GrpcGetBescheidDraftResponse response = GrpcGetBescheidDraftResponse.newBuilder().build();
+
+		@BeforeEach
+		void initMocks() {
+			when(service.buildResponse(any())).thenReturn(response);
+		}
+
+		@Test
+		void shouldBuildResponse() {
+			service.getBescheidDraft(request, responseObserver);
+
+			verify(service).buildResponse(any());
+		}
+
+		@Test
+		void shouldCallNext() {
+			service.getBescheidDraft(request, responseObserver);
+
+			verify(responseObserver).onNext(response);
+		}
+
+		@Test
+		void shouldCallCompleted() {
+			service.getBescheidDraft(request, responseObserver);
+
+			verify(responseObserver).onCompleted();
+		}
+
+	}
+
+	@Nested
+	class TestBuildResponse {
+
+		@Test
+		void shouldCallMapper() {
+			Bescheid bescheid = BescheidTestFactory.create();
+
+			service.buildResponse(bescheid);
+
+			verify(mapper).fromBescheid(bescheid);
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidRequestTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..02d08d4f2a35770e3287c35cfb88e94f2b06a1bb
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidRequestTestFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import java.time.LocalDate;
+
+import de.ozgcloud.bescheid.common.callcontext.UserProfileTestFactory;
+import de.ozgcloud.bescheid.vorgang.VorgangId;
+import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+
+public class BescheidRequestTestFactory {
+
+	static final VorgangId VORGANG_ID = VorgangTestFactory.ID;
+	static final String BESCHEID_VOM_STRING = "2023-01-04";
+	static final LocalDate BESCHEID_VOM = LocalDate.parse(BESCHEID_VOM_STRING);
+	static final boolean GENEHMIGT = true;
+
+	public static BescheidRequest create() {
+		return createBuilder().build();
+	}
+
+	public static BescheidRequest.BescheidRequestBuilder createBuilder() {
+		return BescheidRequest.builder()
+				.vorgangId(VORGANG_ID)
+				.bescheidVom(BESCHEID_VOM)
+				.genehmigt(GENEHMIGT)
+				.createFor(UserProfileTestFactory.create());
+
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c7505f3e889ea8010f257db86fe0aeae2e937ce
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidServiceTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.bescheid.vorgang.Vorgang;
+import de.ozgcloud.bescheid.vorgang.VorgangService;
+import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+
+class BescheidServiceTest {
+
+	@InjectMocks
+	private BescheidService service;
+
+	@Mock
+	private VorgangService vorgangService;
+	@Mock
+	private BescheidRemoteService remoteService;
+
+	@Nested
+	class TestCreateBescheid {
+
+		private Vorgang vorgang = VorgangTestFactory.create();
+		private Bescheid bescheid = BescheidTestFactory.createBuilder().vorgangId(null).build();
+
+		@BeforeEach
+		void initMocks() {
+			when(vorgangService.getById(any())).thenReturn(vorgang);
+			when(remoteService.create(any(), any())).thenReturn(bescheid);
+		}
+
+		@Test
+		void shouldLoadVorgang() {
+			service.createBescheid(BescheidRequestTestFactory.create());
+
+			verify(vorgangService).getById(VorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldCreateBescheid() {
+			BescheidRequest request = BescheidRequestTestFactory.create();
+
+			service.createBescheid(request);
+
+			verify(remoteService).create(request, vorgang);
+		}
+
+		@Test
+		void shouldReturnCreatedBescheid() {
+			var result = service.createBescheid(BescheidRequestTestFactory.create());
+
+			assertThat(result).usingRecursiveComparison().isEqualTo(BescheidTestFactory.create());
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ecd853df278ca53e275066e06f1666cac2b8fc7
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestApplication.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.security.authentication.AuthenticationTrustResolver;
+import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
+
+@SpringBootApplication
+@ComponentScan({ "de.ozgcloud.*" })
+public class BescheidTestApplication {
+
+	@Bean
+	AuthenticationTrustResolver trustResolver() {
+		return new AuthenticationTrustResolverImpl();
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..f89f4ca68e7c3b0de7b5069d4ce1acfdb1e0e557
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/BescheidTestFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+import java.io.File;
+import java.util.Optional;
+
+import org.springframework.http.MediaType;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.bescheid.common.callcontext.UserProfileTestFactory;
+import de.ozgcloud.bescheid.vorgang.ServiceKontoTestFactory;
+import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.binaryfile.TempFileUtils;
+
+public class BescheidTestFactory {
+
+	public static final UserId CREATED_BY = UserProfileTestFactory.ID;
+	public static final String FILE_NAME = "bescheid.pdf";
+
+	public static final byte[] TEST_BESCHEID = "testbescheid".getBytes();
+	public static final File BESCHEID_FILE = TempFileUtils.writeTmpFile(TEST_BESCHEID);
+
+	public static final String CONTENT_TYPE = MediaType.APPLICATION_PDF_VALUE;
+	public static final String NACHRICHT_TEXT = LoremIpsum.getInstance().getWords(5);
+
+	public static Bescheid create() {
+		return createBuilder().build();
+	}
+
+	public static Bescheid.BescheidBuilder createBuilder() {
+		return Bescheid.builder()
+				.createdBy(CREATED_BY)
+				.vorgangId(VorgangTestFactory.ID)
+				.contentType(CONTENT_TYPE)
+				.bescheidFileName(FILE_NAME)
+				.bescheidFile(BESCHEID_FILE)
+				.nachrichtText(Optional.of(NACHRICHT_TEXT))
+				.genehmigt(true)
+				.size(TEST_BESCHEID.length)
+				.serviceKonto(ServiceKontoTestFactory.create());
+	}
+}
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/GrpcBescheidMapperTest.java
similarity index 72%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangMapperTest.java
rename to bescheid-manager/src/test/java/de/ozgcloud/bescheid/GrpcBescheidMapperTest.java
index 467519bcc98e942fe767459fec34990f112e0caa..d167ae129c5324bce39db71d7f61c0784a133363 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangMapperTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/GrpcBescheidMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.bescheid;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -29,18 +29,18 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 
-class VorgangMapperTest {
+class GrpcBescheidMapperTest {
 
-	private VorgangMapper mapper = Mappers.getMapper(VorgangMapper.class);
+	private GrpcBescheidMapper mapper = Mappers.getMapper(GrpcBescheidMapper.class);
 
 	@Nested
-	class TestFromGrpc {
+	class TestFromBescheid {
 
 		@Test
-		void shouldMapVorgang() {
-			var mapped = mapper.fromGrpc(GrpcVorgangTestFactory.create());
+		void shouldMapAllFields() {
+			var result = mapper.fromBescheid(BescheidTestFactory.create());
 
-			assertThat(mapped).usingRecursiveComparison().isEqualTo(VorgangTestFactory.create());
+			assertThat(result).usingRecursiveComparison().isEqualTo(GrpcBescheidTestFactory.create());
 		}
 	}
 
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/GrpcBescheidTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/GrpcBescheidTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab0aba3c1f5a720adb0be00015a60e17a0033dda
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/GrpcBescheidTestFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid;
+
+class GrpcBescheidTestFactory {
+
+	public static GrpcBescheid create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcBescheid.Builder createBuilder() {
+		return GrpcBescheid.newBuilder()
+				.setBewilligt(true)
+				.setNachrichtText(BescheidTestFactory.NACHRICHT_TEXT);
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFsTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/callcontext/CurrentUserServiceTest.java
similarity index 59%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFsTest.java
rename to bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/callcontext/CurrentUserServiceTest.java
index cf88c10a9210f02ae62d7477fbb26e198f757ae1..745f6cd6b3794f36cdafbf30de1adcc5bfb567a1 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFsTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/callcontext/CurrentUserServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,31 +21,36 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.migration;
+package de.ozgcloud.bescheid.common.callcontext;
 
 import static org.assertj.core.api.Assertions.*;
 
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
-import org.mockito.Spy;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.gridfs.GridFsTemplate;
+import org.springframework.security.authentication.AuthenticationTrustResolver;
 
-class M001_MigrateMailServiceAttachmentsToGridFsTest {// NOSONAR
+import de.ozgcloud.command.CommandTestFactory;
+
+class CurrentUserServiceTest {
 
-	@Spy
 	@InjectMocks
-	private M001_MigrateMailServiceAttachmentsToGridFs migrator = new M001_MigrateMailServiceAttachmentsToGridFs();
-	@Mock
-	private MongoTemplate template;
+	private CurrentUserService service;
 	@Mock
-	private GridFsTemplate gridFsTemplate;
+	private AuthenticationTrustResolver trustResolver;
+
+	@DisplayName("Create user")
+	@Nested
+	class TestCreateUser {
 
-	@Test
-	void shouldConvertBytes() {
-		byte[] content = migrator.convertContent(MigrationBinaryFileTestFactory.createFile());
+		// FIXME read client name from command
+		@Test
+		void shouldContainsClientName() {
+			var user = service.createUser(CommandTestFactory.create());
 
-		assertThat(content).isEqualTo(MigrationIncomingFileTestFactory.CONTENT);
+			assertThat(user.getClientName()).isEqualTo("Alfa");
+		}
 	}
-}
\ No newline at end of file
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/GrpcPostfachNachrichtTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/GrpcPostfachNachrichtTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..9807e737c57d61abf33c251e89174bdf9d74205b
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/GrpcPostfachNachrichtTestFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import de.ozgcloud.nachrichten.postfach.GrpcPostfachNachricht;
+
+public class GrpcPostfachNachrichtTestFactory {
+
+	public static final GrpcPostfachNachricht create() {
+		return createBuilder().build();
+	}
+
+	public static final GrpcPostfachNachricht.Builder createBuilder() {
+		return GrpcPostfachNachricht.newBuilder()
+				.setCreatedAt(NachrichtTestFactory.CREATED_AT.toString())
+				.setMailBody(NachrichtTestFactory.MAIL_BODY)
+				.setSubject(NachrichtTestFactory.SUBJECT);
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..01cb5f98a260a2e716a8d3e466db98715edd3146
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtMapperTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+
+class NachrichtMapperTest {
+
+	@InjectMocks
+	private NachrichtMapper mapper = Mappers.getMapper(NachrichtMapper.class);;
+
+	@Nested
+	class TestMapToGrpc {
+		@Test
+		void shouldMapNachricht() {
+			var mapped = mapper.mapToGrpc(NachrichtTestFactory.create());
+
+			assertThat(mapped).usingRecursiveComparison()
+					.ignoringFields("replyOption_", "memoizedHashCode")
+					.isEqualTo(GrpcPostfachNachrichtTestFactory.create());
+		}
+
+		@Test
+		void shouldIgnoreMissingFileId() {
+			var mapped = mapper.mapToGrpc(NachrichtTestFactory.createBuilder().bescheidFileId(null).build());
+
+			assertThat(mapped.getAttachmentList()).isEmpty();
+		}
+
+		@Test
+		void shouldSetReplyOption() {
+			var mapped = mapper.mapToGrpc(NachrichtTestFactory.create());
+
+			assertThat(mapped.getReplyOption()).isEqualTo("FORBIDDEN");
+		}
+
+		@Test
+		void shouldNotMapId() {
+			var mapped = mapper.mapToGrpc(NachrichtTestFactory.create());
+
+			assertThat(mapped.getId()).isEmpty();
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtRemoteServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c447e1a3202d0274e0474ee5e570ebb10236fe85
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtRemoteServiceTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+import de.ozgcloud.nachrichten.postfach.GrpcPostfachNachricht;
+
+class NachrichtRemoteServiceTest {
+
+	@InjectMocks
+	private NachrichtRemoteService remoteService;
+
+	@Mock
+	private NachrichtMapper mapper;
+
+	@Nested
+	class TestSaveDarft {
+		@Nested
+		class BuildRequest {
+			private Nachricht nachricht = NachrichtTestFactory.create();
+			private GrpcPostfachNachricht grpcNachricht = GrpcPostfachNachrichtTestFactory.create();
+
+			@BeforeEach
+			void initMocks() {
+				when(mapper.mapToGrpc(any())).thenReturn(grpcNachricht);
+			}
+
+			@Test
+			void shouldCallMapper() {
+				remoteService.buildRequest(nachricht);
+
+				verify(mapper).mapToGrpc(nachricht);
+			}
+
+			@Test
+			void shouldSetNachricht() {
+				var request = remoteService.buildRequest(nachricht);
+
+				assertThat(request.getNachricht()).isSameAs(grpcNachricht);
+			}
+
+			@Test
+			void shouldSetVorgangId() {
+				var request = remoteService.buildRequest(nachricht);
+
+				assertThat(request.getVorgangId()).isEqualTo(VorgangTestFactory.ID.toString());
+			}
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtServiceITCase.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..29afe88412c17d9a99488bb3c2a78de92b7b0851
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtServiceITCase.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.bescheid.BescheidTestFactory;
+
+@ITCase
+class NachrichtServiceITCase {
+
+	@Autowired
+	private NachrichtService service;
+
+	@Nested
+	class TestBuildMessage {
+		@Test
+		void shouldBuildMessage() {
+			var message = service.buildMessage(BescheidTestFactory.create());
+
+			assertThat(message).isNotBlank();
+		}
+
+		@Test
+		void shouldBeGenehmigt() {
+			var message = service.buildMessage(BescheidTestFactory.createBuilder().genehmigt(true).build());
+
+			assertThat(message).contains("genehmigt").doesNotContain("abgelehnt");
+		}
+
+		@Test
+		void shouldBeAbgelehnt() {
+			var message = service.buildMessage(BescheidTestFactory.createBuilder().genehmigt(false).build());
+
+			assertThat(message).contains("abgelehnt").doesNotContain("genehmigt");
+		}
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae7a41757d649facf7f52f8db22b02d1c40bb17e
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtServiceTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.bescheid.BescheidTestFactory;
+import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+
+class NachrichtServiceTest {
+
+	@Spy
+	@InjectMocks
+	private NachrichtService service;
+
+	@Mock
+	private NachrichtRemoteService remoteService;
+
+	@Nested
+	class TestCreateNachrichtDraft {
+
+		private Nachricht nachricht = NachrichtTestFactory.create();
+
+		@Test
+		void shouldCallRemoteService() {
+			doReturn(Optional.of(nachricht)).when(service).buildNachricht(any());
+
+			service.createNachrichtDraft(BescheidTestFactory.create());
+
+			verify(remoteService).saveDraft(nachricht);
+		}
+
+		@Nested
+		class BuildNachricht {
+
+			@BeforeEach
+			void init() {
+				doReturn(NachrichtTestFactory.MAIL_BODY).when(service).buildMessage(any());
+			}
+
+			@Test
+			void shouldFillMailBody() {
+				var nachricht = service.buildNachricht(BescheidTestFactory.create()).get();
+
+				assertThat(nachricht.getMailBody()).isEqualTo(NachrichtTestFactory.MAIL_BODY);
+			}
+
+			@Test
+			void shouldSetSubject() {
+				var nachricht = service.buildNachricht(BescheidTestFactory.create()).get();
+
+				assertThat(nachricht.getSubject()).isEqualTo(NachrichtService.SUBJECT);
+			}
+
+			@Test
+			void shouldSetUser() {
+				var nachricht = service.buildNachricht(BescheidTestFactory.create()).get();
+
+				assertThat(nachricht.getCreatedBy()).isEqualTo(BescheidTestFactory.CREATED_BY);
+			}
+
+			@Test
+			void shouldSetVorgangId() {
+				var nachricht = service.buildNachricht(BescheidTestFactory.create()).get();
+
+				assertThat(nachricht.getVorgangId()).isEqualTo(VorgangTestFactory.ID);
+			}
+		}
+	}
+
+	@Nested
+	class TestBuildMessage {
+		@Test
+		void shouldUseTextFromBescheid() {
+			var message = service.buildMessage(BescheidTestFactory.create());
+
+			assertThat(message).isEqualTo(BescheidTestFactory.NACHRICHT_TEXT);
+		}
+
+		@Test
+		void shouldUseDefaultTemplate() {
+			doReturn("FROM_TEMPLATE").when(service).fillTemplate(any(), any());
+
+			var message = service.buildMessage(BescheidTestFactory.createBuilder().nachrichtText(Optional.empty()).build());
+
+			assertThat(message).isEqualTo("FROM_TEMPLATE");
+		}
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..21dd7fdde722fbba4150e4cd23fe867f5780ffe3
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/nachricht/NachrichtTestFactory.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.nachricht;
+
+import java.time.ZonedDateTime;
+import java.util.UUID;
+
+import de.ozgcloud.bescheid.UserId;
+import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+
+public class NachrichtTestFactory {
+
+	public static final NachrichtId ID = NachrichtId.from(UUID.randomUUID().toString());
+
+	public static final String SUBJECT = "subject of message";
+	public static final String MAIL_BODY = "Lorem ipsum";
+
+	public static final UserId CREATED_BY = UserId.from(UUID.randomUUID().toString());
+	public static final ZonedDateTime CREATED_AT = ZonedDateTime.now().withNano(0);
+
+	public static Nachricht create() {
+		return createBuilder().build();
+	}
+
+	public static Nachricht.NachrichtBuilder createBuilder() {
+		return Nachricht.builder()
+				.id(ID)
+				.vorgangId(VorgangTestFactory.ID)
+				.subject(SUBJECT)
+				.mailBody(MAIL_BODY)
+				.createdBy(CREATED_BY)
+				.createdAt(CREATED_AT);
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteServiceITCase.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..452dd07294e67ee59f39a5e6f619dc72baeaa748
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteServiceITCase.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.smartdocuments;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ActiveProfiles;
+
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.bescheid.BescheidRequestTestFactory;
+import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+
+@Disabled
+@ITCase
+@ActiveProfiles({ "itcase", "local" })
+class SmartDocumentsBescheidRemoteServiceITCase {
+
+	@Autowired
+	private SmartDocumentsBescheidRemoteService remoteService;
+
+	@Test
+	void createBescheid() {
+		var bescheid = remoteService.create(BescheidRequestTestFactory.create(), VorgangTestFactory.create());
+
+		System.out.println(bescheid.getBescheidFileName());
+		System.out.println(bescheid.getBescheidFile().getAbsolutePath());
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ec9d4be5fadde6f224ca778d54053db9c982104
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsBescheidRemoteServiceTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.smartdocuments;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.File;
+import java.util.Optional;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.bescheid.BescheidRequestTestFactory;
+import de.ozgcloud.bescheid.BescheidTestFactory;
+import de.ozgcloud.bescheid.common.callcontext.UserProfileTestFactory;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsRequest.CustomerData.UserData;
+import de.ozgcloud.bescheid.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.binaryfile.TempFileUtils;
+import de.ozgcloud.common.test.TestUtils;
+
+class SmartDocumentsBescheidRemoteServiceTest {
+
+	@Spy
+	@InjectMocks
+	private SmartDocumentsBescheidRemoteService service;
+
+	@Mock
+	private SmartDocumentsProperties properties;
+
+	@Nested
+	class TestBuildBescheid {
+
+		@Test
+		void shouldFillBescheid() {
+			var bescheid = service.buildBescheid(BescheidRequestTestFactory.create(), SmartDocumentsResponseTestFactory.create());
+
+			assertThat(bescheid).usingRecursiveComparison().ignoringFields("serviceKonto")
+					.isEqualTo(BescheidTestFactory.createBuilder().nachrichtText(Optional.empty()).build());
+		}
+	}
+
+	@Nested
+	class TestCreateRequest {
+
+		@Test
+		void shouldFillUserData() {
+			var request = service.createRequest(BescheidRequestTestFactory.create(), VorgangTestFactory.create());
+
+			assertThat(request.getCustomerData().getUserData()).isNotNull()
+					.extracting(UserData::getEmail).isEqualTo(UserProfileTestFactory.EMAIL);
+		}
+	}
+
+	@Nested
+	class TestGetNachrichtText {
+		private File xmlFile = TempFileUtils.writeTmpFile(TestUtils.loadFile("SD_answer.xml"));
+
+		@Test
+		void shouldCallExtractText() {
+			doReturn(Optional.of(xmlFile)).when(service).getXMLFile(any());
+
+			service.getNachrichtText(SmartDocumentsResponseTestFactory.create());
+
+			verify(service).extractTextFormXmlFile(notNull());
+		}
+
+		@Nested
+		class ExtractingText {
+
+			@Test
+			void shouldReturnText() {
+				var text = service.extractTextFormXmlFile(xmlFile);
+
+				assertThat(text).isPresent().get().isNotNull();
+			}
+
+			@Test
+			void shouldHandleError() {
+				var text = service.extractTextFormXmlFile(null);
+
+				assertThat(text).isEmpty();
+			}
+
+		}
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsResponseTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0b9010e0e023c03d94413113c5d5c30f1553d86
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/smartdocuments/SmartDocumentsResponseTestFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.smartdocuments;
+
+import java.util.List;
+
+import de.ozgcloud.bescheid.BescheidTestFactory;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsBescheidRemoteService.SmartDocumentsResponse;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsBescheidRemoteService.SmartDocumentsResponse.SmartDocumentDocument;
+import de.ozgcloud.bescheid.smartdocuments.SmartDocumentsBescheidRemoteService.SmartDocumentsResponse.SmartDocumentFile;
+
+public class SmartDocumentsResponseTestFactory {
+
+	static final String OUTPUT_FORMAT = "PDF";
+
+	static SmartDocumentsResponse create() {
+		return createBuilder().build();
+	}
+
+	static SmartDocumentsResponse.SmartDocumentsResponseBuilder createBuilder() {
+		return SmartDocumentsResponse.builder()
+				.file(List.of(SmartDocumentFile.builder()
+						.filename(BescheidTestFactory.FILE_NAME)
+						.outputFormat(OUTPUT_FORMAT)
+						.document(SmartDocumentDocument.builder()
+								.data(BescheidTestFactory.BESCHEID_FILE)
+								.build())
+						.build()));
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/BescheidVorgangMapperTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/BescheidVorgangMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..15315ae9c70d3209a2949b8d98269004579546a5
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/BescheidVorgangMapperTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+
+class BescheidVorgangMapperTest {
+
+	@InjectMocks
+	private BescheidVorgangMapperImpl mapper;
+
+	@Nested
+	class TestMapVorgang {
+
+		@Test
+		void shouldMapEingang() {
+			var result = mapper.mapVorgang(GrpcVorgangWithEingangTestFactory.create());
+
+			assertThat(result.getEingang()).isNotNull();
+		}
+
+		@Test
+		void shouldMapVorgangId() {
+			var result = mapper.mapVorgang(GrpcVorgangWithEingangTestFactory.create());
+
+			assertThat(result.getId()).isEqualTo(VorgangTestFactory.ID);
+		}
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/FormDataEntrySerializerTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/FormDataEntrySerializerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2edf705117f4b9825836066b86a5c45424e8ba60
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/FormDataEntrySerializerTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import de.ozgcloud.bescheid.vorgang.FormDataEntry.FormField;
+import de.ozgcloud.bescheid.vorgang.FormDataEntry.SubForm;
+import de.ozgcloud.bescheid.vorgang.Vorgang.Eingang;
+import lombok.SneakyThrows;
+
+class FormDataEntrySerializerTest {
+
+	private ObjectMapper mapper = new ObjectMapper();
+
+	@Test
+	void schouldSerializeFormDataWithSingleField() throws JsonProcessingException {
+		var eingang = Eingang.builder()
+				.formData(FormField.builder().name("name").value("Thea").build())
+				.build();
+
+		var json = mapper.writeValueAsString(eingang);
+
+		assertThat(json).contains("\"formData\":{\"name\":\"Thea\"}");
+	}
+
+	@Test
+	@SneakyThrows
+	void sohludSerializeFormDataWithSubForm() {
+		var eingang = Eingang.builder()
+				.formData(SubForm.builder().name("address")
+						.entry(FormField.builder().name("name").value("Thea").build())
+						.build())
+				.build();
+
+		var json = mapper.writeValueAsString(eingang);
+
+		assertThat(json).contains("\"formData\":{\"address\":{\"name\":\"Thea\"}}");
+	}
+
+	@Test
+	@SneakyThrows
+	void shouldSerializeFormDataWithSubSubForm() {
+		var eingang = Eingang.builder()
+				.formData(SubForm.builder().name("address")
+						.entry(SubForm.builder().name("person")
+								.entry(FormField.builder().name("name").value("Thea").build())
+								.build())
+						.build())
+				.build();
+
+		var json = mapper.writeValueAsString(eingang);
+
+		assertThat(json).contains("\"formData\":{\"address\":{\"person\":{\"name\":\"Thea\"}}}");
+	}
+
+	@Test
+	@SneakyThrows
+	void shouldSerializeFormWithTwoFields() {
+		var eingang = Eingang.builder()
+				.formData(FormField.builder().name("firstname").value("Thea").build())
+				.formData(FormField.builder().name("lastname").value("Test").build())
+				.build();
+
+		var json = mapper.writeValueAsString(eingang);
+
+		assertThat(json).contains("\"formData\":{\"firstname\":\"Thea\",\"lastname\":\"Test\"}");
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/GrpcEingangTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/GrpcEingangTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..c21e9c5ad5510b9b9ff7d35308443f11de877b5f
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/GrpcEingangTestFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import de.ozgcloud.vorgang.vorgang.GrpcEingang;
+
+public class GrpcEingangTestFactory {
+
+	static GrpcEingang create() {
+		return createBuilder().build();
+	}
+
+	static GrpcEingang.Builder createBuilder() {
+		return GrpcEingang.newBuilder();
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/GrpcVorgangWithEingangTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/GrpcVorgangWithEingangTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a19fee57da7538ebb632081475988e74e6cb73b3
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/GrpcVorgangWithEingangTestFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import static de.ozgcloud.bescheid.vorgang.VorgangTestFactory.*;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangResponse;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangWithEingang;
+
+class GrpcVorgangWithEingangTestFactory {
+
+	static GrpcVorgangWithEingang create() {
+		return createBuilder().build();
+	}
+
+	static GrpcVorgangWithEingang.Builder createBuilder() {
+		return GrpcVorgangWithEingang.newBuilder()
+				.setId(ID.toString())
+				.setEingang(GrpcEingangTestFactory.create());
+	}
+
+	static GrpcFindVorgangWithEingangResponse createResponse() {
+		return GrpcFindVorgangWithEingangResponse.newBuilder()
+				.setVorgangWithEingang(create())
+				.build();
+	}
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/ServiceKontoTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/ServiceKontoTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea978d85cc46d426403defae97dda9fdae31e7e2
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/ServiceKontoTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import de.ozgcloud.bescheid.vorgang.Vorgang.PostfachAddress;
+import de.ozgcloud.bescheid.vorgang.Vorgang.ServiceKonto;
+
+public class ServiceKontoTestFactory {
+
+	public static ServiceKonto create() {
+		return createBuilder().build();
+	}
+
+	public static ServiceKonto.ServiceKontoBuilder createBuilder() {
+		return ServiceKonto.builder()
+				.postfachAddress(PostfachAddress.builder().build());
+	}
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangRemoteServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..94a445215f3e1c17be8d50f47dd6b0f264cd63e8
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangRemoteServiceTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
+
+class VorgangRemoteServiceTest {
+
+	@Spy
+	@InjectMocks
+	private VorgangRemoteService service;
+
+	@Mock
+	private VorgangServiceBlockingStub serviceStub;
+	@Mock
+	private BescheidVorgangMapper mapper;
+
+	@Nested
+	class TestGetById {
+		@Captor
+		private ArgumentCaptor<GrpcFindVorgangWithEingangRequest> requestCaptor;
+
+		@BeforeEach
+		void prepareGrpc() {
+			when(serviceStub.withInterceptors(any())).thenReturn(serviceStub);
+			when(serviceStub.findVorgangWithEingang(any())).thenReturn(GrpcVorgangWithEingangTestFactory.createResponse());
+			
+		}
+
+		@BeforeEach
+		void init() {
+			when(mapper.mapVorgang(any())).thenReturn(VorgangTestFactory.create());
+		}
+
+		@Test
+		void shouldCallStubWithId() {
+			service.getById(VorgangTestFactory.ID);
+
+			verify(serviceStub).findVorgangWithEingang(requestCaptor.capture());
+			assertThat(requestCaptor.getValue()).extracting(GrpcFindVorgangWithEingangRequest::getId).isEqualTo(VorgangTestFactory.ID.toString());
+		}
+
+		@Test
+		void shouldCallMapper() {
+			service.getById(VorgangTestFactory.ID);
+
+			verify(mapper).mapVorgang(any());
+		}
+
+		@Test
+		void shouldReturnVorgang() {
+			var vorgang = service.getById(VorgangTestFactory.ID);
+
+			assertThat(vorgang).usingRecursiveComparison().isEqualTo(VorgangTestFactory.create());
+		}
+
+	}
+
+}
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/user/UserRemoteServiceTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangServiceTest.java
similarity index 60%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/user/UserRemoteServiceTest.java
rename to bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangServiceTest.java
index 372ad9f23e16d7e3600d808156e27ed12f102bcc..2dde114c3bc0a1c4d3f98d27869e2573ebaa88c2 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/user/UserRemoteServiceTest.java
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,39 +21,49 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.bescheid.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
-import de.itvsh.kop.user.grpc.recipient.RecipientServiceGrpc.RecipientServiceBlockingStub;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-class UserRemoteServiceTest {
+class VorgangServiceTest {
 
 	@InjectMocks
-	private UserRemoteService remoteService;
+	private VorgangService service;
 
 	@Mock
-	private RecipientServiceBlockingStub recipientService;
-	@Mock
-	private UserRecipientMapper mapper;
+	private VorgangRemoteService remoteService;
 
 	@Nested
-	class TestRequestRecipients {
+	class TestGetById {
+
+		private Vorgang vorgang = VorgangTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			when(remoteService.getById(any())).thenReturn(vorgang);
+		}
 
 		@Test
-		void shouldConvertCorrectly() {
-			when(recipientService.findRecipientByOrganisationsEinheitId(any())).thenReturn(GrpcFindRecipientRequestTestFactory.create());
-			when(mapper.fromGrpc(any())).thenReturn(RecipientTestFactory.create());
+		void shouldCallRemoteService() {
+			service.getById(VorgangTestFactory.ID);
 
-			var recipients = remoteService.getRecipients("id");
+			verify(remoteService).getById(VorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldReturnResult() {
+			var result = service.getById(VorgangTestFactory.ID);
 
-			assertThat(recipients.get(0)).usingRecursiveComparison().isEqualTo(RecipientTestFactory.create());
+			assertThat(result).isEqualTo(vorgang);
 		}
 	}
-}
\ No newline at end of file
+
+}
diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangTestFactory.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..333576eb699f820447eed1a8e5283de531165e23
--- /dev/null
+++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/vorgang/VorgangTestFactory.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.bescheid.vorgang;
+
+import java.util.UUID;
+
+public class VorgangTestFactory {
+
+	public static final VorgangId ID = VorgangId.from(UUID.randomUUID().toString());
+
+	public static Vorgang create() {
+		return createBuilder().build();
+	}
+
+	public static Vorgang.VorgangBuilder createBuilder() {
+		return Vorgang.builder()
+				.id(ID)
+				.serviceKonto(ServiceKontoTestFactory.create())
+				.vorgangName("KFAS_LIVE_KI_10_Haltverbot_befristet")
+				.vorgangNummer("ABC-123-XY")
+				.aktenzeichen("DE-HÖÄ-003");
+	}
+
+}
diff --git a/mail-service/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/bescheid-manager/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
similarity index 100%
rename from mail-service/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
rename to bescheid-manager/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
diff --git a/bescheid-manager/src/test/resources/SD_answer.xml b/bescheid-manager/src/test/resources/SD_answer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..df9d905e472c9b0a077421064ad61a990389ede5
--- /dev/null
+++ b/bescheid-manager/src/test/resources/SD_answer.xml
@@ -0,0 +1,399 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+   <SmartDocument Version="2.0">
+      <Selection>
+         <TypistID>E53F295BC2794A6697155664D0F30880</TypistID>
+         <UserGroupID>88FC6F29D71C4BB096B71BC9B3C860F8</UserGroupID>
+         <AuthorID>E53F295BC2794A6697155664D0F30880</AuthorID>
+         <TemplateGroupID>94A1C1208DF0479CB58E3CFB0A6057BC</TemplateGroupID>
+         <Template>KFAS_LIVE_KI_10_Haltverbot_befristet</Template>
+         <TemplateID Timestamp="1704722931920">7ACEA5AE7C3642978ACCC48182EBCD6E</TemplateID>
+         <Blocks>
+            <Block VersionID="15DCCB4DFE1A414796EBA44352C7AAFF">CC2A9C0E14164B9A967CEE8DCD41B3B5</Block>
+            <Placeholders>
+               <Placeholder ID="125E766AF0424D4992F8F04C806F75EB">CC2A9C0E14164B9A967CEE8DCD41B3B5</Placeholder>
+            </Placeholders>
+         </Blocks>
+      </Selection>
+      <Variables/>
+      <QuestionAnswers>
+         <Question ID="07BE1279C0504852AEFBB264D165E139"
+                   Description="Tagesdatum"
+                   OriginalValue="2024-01-08"><![CDATA[08.01.2024]]></Question>
+         <Question ID="23BB945F7BA44321B09A0A984D541DD1"
+                   Description="Tage Halteverbot"
+                   ContentId="23BB945F7BA44321B09A0A984D541DD1"
+                   IsFormatted="true"
+                   ContentType="XML">
+            <Records>
+               <Record>
+                  <Field Name="71F5F35C4FD94982A1F8321A73E9B593">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="58F6E456AE1F4E13907D78E158BF4847" Description="Freitag">
+                           <Answer ID="313DC774D89E45D8864FC33983C95923"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="313DC774D89E45D8864FC33983C95923"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="B66C9D21D31A4293852EEDCAB57C593B">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="EF33891FF01A42B0BEFB1E78E3FC023D" Description="Samstag">
+                           <Answer ID="24CD7BEAB973475A998C7EAB9C4D1AE3"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="24CD7BEAB973475A998C7EAB9C4D1AE3"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="67082AAB675E457180A7014531C46CB3">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="60C6CD1F29084A26BEC493A862583AAB" Description="Montag">
+                           <Answer ID="13A1D81A4DB74AAEB2A6E684C575B768"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="13A1D81A4DB74AAEB2A6E684C575B768"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="3FD23F8F98EF459A95B50448DEDFF20E">
+                     <Value><![CDATA[ja]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="C8BC6BFFE8BE4E6BBDC4CBCD34377DB2" Description="Mittwoch">
+                           <Answer ID="97B676CAC9B74D00B574F319B2D20BB5"
+                                   Description="Ja"
+                                   IsFormatted="true"
+                                   ContentId="97B676CAC9B74D00B574F319B2D20BB5"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="09658B4DA4BB4295822A42C0AA8FC2EC">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="39BF39565D4043078ABEEC9601A091E7" Description="Donnerstag">
+                           <Answer ID="8D4A19B4D3AF448FB720E9160E7A40D2"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="8D4A19B4D3AF448FB720E9160E7A40D2"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="975867EBE97547ACA6B8D85F1D8D39C8">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="03906ABB93494C6EB087D87C4C70217C" Description="Dienstag">
+                           <Answer ID="B9ACD0E74C6B41BEA700C9EB8FCFFC25"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="B9ACD0E74C6B41BEA700C9EB8FCFFC25"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="AF89873144744EDC9A1B78776F3D25F5">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="06349259221C4DEFBB4FE9FD33D76403" Description="Sonntag">
+                           <Answer ID="853ED74B536C4BD8AF95193450F18201"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="853ED74B536C4BD8AF95193450F18201"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+               </Record>
+            </Records>
+         </Question>
+         <Question ID="28CB094DAD1A4604B08CE7C5D2177C03" Description="Beschilderung">
+            <Answer ID="D2CA0BC90987429DA8CCF855C496DBAB"
+                    Description="Ja"
+                    IsFormatted="true"
+                    ContentId="D2CA0BC90987429DA8CCF855C496DBAB"/>
+         </Question>
+         <Question ID="736372FDB0A2407CBBFB15DE71FD1450"
+                   Description="Geschlecht Antragssteller">
+            <Answer ID="4E80D616EB364F2EA9C567C1D7F8AED8"
+                    Description="männlich"
+                    IsFormatted="true"
+                    ContentId="4E80D616EB364F2EA9C567C1D7F8AED8"/>
+         </Question>
+         <Question ID="97E309BDBDB548F48D162D289056B313" Description="Uhrzeit Halteverbot">
+            <Answer ID="E45BE1342D5F43D59E21986C377DA1B0"
+                    Description="ganztägig"
+                    IsFormatted="true"
+                    ContentId="E45BE1342D5F43D59E21986C377DA1B0"/>
+         </Question>
+         <Question ID="992F241A1DF4497A8B4568E69B9C567C"
+                   Description="Vor Ort geltende Parkregelung">
+            <Answer ID="7437DBBAAA6F468DBFAC138607C123FA"
+                    Description="Parken am Seitenstreifen"
+                    IsFormatted="true"
+                    ContentId="7437DBBAAA6F468DBFAC138607C123FA"/>
+         </Question>
+         <Question ID="9BD81FB0E5FF4235A094BE3D21544615"
+                   Description="Name Ansprechperson / Firma"
+                   AlternativeParentID="736372FDB0A2407CBBFB15DE71FD1450">
+            <Answer ID="CCD833A8C8C34E5D9564676CAFCF4DD8"
+                    Description="männlich"
+                    IsFormatted="true"
+                    ContentId="CCD833A8C8C34E5D9564676CAFCF4DD8"/>
+         </Question>
+         <Question ID="9CE081D9122E43B1B778863AE32AB29F" Description="Protokoll">
+            <Answer ID="C2E7328389584B33A0D4DB82D8FA2671"
+                    Description="Ja"
+                    IsFormatted="true"
+                    ContentId="C2E7328389584B33A0D4DB82D8FA2671"/>
+         </Question>
+         <Question ID="B651AC699A4F4B768DC34DE87BBD578C"
+                   Description="Gründe für Halteverbot"
+                   ContentId="B651AC699A4F4B768DC34DE87BBD578C"
+                   IsFormatted="true"
+                   ContentType="XML">
+            <Records>
+               <Record>
+                  <Field Name="DE3D244EB8754929955FF571D374C635">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="35AECC80B19C426CAB60195F0839E968" Description="Container">
+                           <Answer ID="9034F5BDB3CE48429C95D7E8C5144E35"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="9034F5BDB3CE48429C95D7E8C5144E35"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="4EE22B7DF177414796C4458EDA2BDAAD">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="A167DD3CA6B14A459F350FFD725FD121" Description="Baufahrzeug">
+                           <Answer ID="D4D84D211E5640F4921BB280026B786C"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="D4D84D211E5640F4921BB280026B786C"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="D406E7038AD64786AC0E54C8033BAAB0">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="CB595FC6EC054D408FFCA67ACA1E33D6" Description="Materiallagerung">
+                           <Answer ID="A74A7B407B5B4681BF254948837912AC"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="A74A7B407B5B4681BF254948837912AC"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="2BBBB7D558014C4297747D4E841CBB93">
+                     <Value><![CDATA[ja]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="38B11C2200034615B41F7DB88136B2C6" Description="Umzug">
+                           <Answer ID="D7B3F786760D48DBAEE9DC3A8F555EA8"
+                                   Description="Ja"
+                                   IsFormatted="true"
+                                   ContentId="D7B3F786760D48DBAEE9DC3A8F555EA8"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="6B173C517C4F48C7A8E212E6CF2ACF23">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="C67E6013B0554AEC9EDF897DD29794C3" Description="Hubsteiger / Kran">
+                           <Answer ID="FF2D2B532E3343228C59C072DCE783C1"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="FF2D2B532E3343228C59C072DCE783C1"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+                  <Field Name="AB9698E6B2EA4DAAB0A0F51E2B127F32">
+                     <Value><![CDATA[nein]]></Value>
+                     <QuestionAnswers>
+                        <Question ID="8356F526632542AEA6D30E41B4FF4872" Description="sonstiges">
+                           <Answer ID="A2776865599D44C28213EACCC0861BE5"
+                                   Description="Nein"
+                                   IsFormatted="true"
+                                   ContentId="A2776865599D44C28213EACCC0861BE5"/>
+                        </Question>
+                     </QuestionAnswers>
+                  </Field>
+               </Record>
+            </Records>
+         </Question>
+         <Question ID="C7C9CCBF9633499EAB08D1BBB84BFD98" Description="Richtigkeit">
+            <Answer ID="386B6CDC94D2498F9576ED949322491C"
+                    Description="Ja"
+                    IsFormatted="true"
+                    ContentId="386B6CDC94D2498F9576ED949322491C"/>
+         </Question>
+         <Question ID="C7D1A20B17CD4C96BF55A2738B8A4631" Description="Kenntnisnahme">
+            <Answer ID="27B4C15818DD4F3087EF6D4822EE1215"
+                    Description="Ja"
+                    IsFormatted="true"
+                    ContentId="27B4C15818DD4F3087EF6D4822EE1215"/>
+         </Question>
+      </QuestionAnswers>
+      <Fields>
+         <Field ID="3C5C7920FB444A9DB2F5239339599BD7"/>
+         <Field ID="41237CC02584421A8D65990E7F78F833"><![CDATA[24]]></Field>
+         <Field ID="423CB6F4AEB54A44BC67F97626ADC06C"><![CDATA[christoph.steuber@kiel.de]]></Field>
+         <Field ID="442D48B946C64853B78DB99D9341AAC8"/>
+         <Field ID="4D4178B6F808409391990233D33BF54C"><![CDATA[21727]]></Field>
+         <Field ID="5AE5217E97F845B48D4274894BC2F043"/>
+         <Field ID="635CEB0B41DE44EFB2207122CCB8EE1D"><![CDATA[0431789456]]></Field>
+         <Field ID="6B06CD242FC64865BFC5B770BB03EAA4"><![CDATA[ESTORF]]></Field>
+         <Field ID="769E3AC926154741AABE870EB802E2AD"/>
+         <Field ID="7AF097E4E741455685CD543ABB7CE337"><![CDATA[OSTERBERG]]></Field>
+         <Field ID="8CA72E11F95F4352AE6FB8001BE79508"><![CDATA[06.12.2023]]></Field>
+         <Field ID="8D38662ADBF2408B8C8DDB5294A5A5A9"><![CDATA[Fleet]]></Field>
+         <Field ID="CA36A227CFEC4B89A40CA8B0CF4460C0"><![CDATA[9]]></Field>
+         <Field ID="CC330D642D7D465FA611D029F6A06344"/>
+         <Field ID="D316B8AE41A3496495C058CCB3766F3A"><![CDATA[CHRISTOPH ALÄXANDER]]></Field>
+         <Field ID="DB270EC247D5476A9D8BFA008E872D7D"><![CDATA[Kiel]]></Field>
+         <Field ID="DE7F7E00C8C246AEA9FFDF7F89E2FB03"><![CDATA[06.12.2023]]></Field>
+         <Field ID="F1826BE2F3D04E508F6401E8AA1D08C1"><![CDATA[10]]></Field>
+         <Field ID="FEC37A441C9D46189533DBD9CFD0E0E8"><![CDATA[STEUBER]]></Field>
+         <Field ID="FECCC52ABB614390BAE2577AD8C44262"><![CDATA[24103]]></Field>
+         <Field ID="root/CustomerData/Dateiname"><![CDATA[Fleet_9-Verk-AO_01-08_06.12.2023-06.12.2023]]></Field>
+         <NachrichtenText>Sehr geehrte/r Antragstellende,
+
+anliegend erhalten Sie die verkehrsrechtliche Anordnung für die Aufstellung der von Ihnen beantragten Beschilderung. Die Prüfung der Straßenverkehrsbehörde bezieht sich nur auf die Vollständigkeit des Antrages und die Plausibilität der Angaben. Die richtige Auswahl der aufzustellenden Verkehrszeichen oder Überschneidung mit anderen Anträgen wurde dabei nicht geprüft.
+
+BITTE DRINGEND BEACHTEN
+Der Antrag einer mobilen Haltverbotszone ist MINDESTENS 1 Woche vor Aufstellung der Beschilderung zu stellen. Des Weiteren gilt die Beschilderung erst als angeordnet, wenn die Antragstellenden das von der Straßenverkehrsbehörde unterschriebene Anmeldeformular zurückerhalten haben (Fax, E-Mail, Post). Vorab sind keine Schilder aufzustellen!!!
+</NachrichtenText>
+      </Fields>
+      <DocumentProperties>
+         <Guid>7ACEA5AE7C3642978ACCC48182EBCD6E</Guid>
+         <BuiltIn>
+            <creator>Pascal Sauermann</creator>
+         </BuiltIn>
+         <Extended/>
+         <Custom>
+            <Author name="Author"
+                    type="lpwstr"
+                    property="true"
+                    variable="false"
+                    xml="false">psa</Author>
+            <Typist name="Typist"
+                    type="lpwstr"
+                    property="true"
+                    variable="false"
+                    xml="false">psa</Typist>
+            <TemplateId name="TemplateId"
+                        type="lpwstr"
+                        property="true"
+                        variable="false"
+                        xml="false">7ACEA5AE7C3642978ACCC48182EBCD6E</TemplateId>
+            <Template name="Template"
+                      type="lpwstr"
+                      property="true"
+                      variable="false"
+                      xml="false">KFAS_LIVE_KI_10_Haltverbot_befristet</Template>
+         </Custom>
+      </DocumentProperties>
+   </SmartDocument>
+   <CustomerData>
+      <bescheid>
+         <bescheidVom/>
+         <genehmigt>true</genehmigt>
+      </bescheid>
+      <userData>
+         <firstName>Tobias</firstName>
+         <lastName>Bruns</lastName>
+         <email>tobias.bruns@external.mgm-tp.com</email>
+      </userData>
+      <vorgang>
+         <vorgangName>KFAS_LIVE_KI_10_Haltverbot_befristet</vorgangName>
+         <serviceKonto>
+            <type>OSI</type>
+            <postfachAddresses>
+               <item>
+                  <identifier>
+                     <postfachId>76f1ae54-1cf1-4ae1-c0b4-08d950d6cfc0</postfachId>
+                  </identifier>
+                  <type>1</type>
+                  <version>1.0</version>
+               </item>
+            </postfachAddresses>
+         </serviceKonto>
+         <eingang>
+            <zustaendigeStelle>
+               <organisationseinheitenId>268084622</organisationseinheitenId>
+               <email/>
+            </zustaendigeStelle>
+            <antragsteller>
+               <vorname>CHRISTOPH ALÄXANDER</vorname>
+               <nachname>STEUBER</nachname>
+            </antragsteller>
+            <formData>
+               <Stammdaten__Antragstellende_Person_>
+                  <Adresse_Kiel_vorbefüllt_mit_Kontaktdaten>
+                     <AS_E-Mail>christoph.steuber@kiel.de</AS_E-Mail>
+                     <Postleitzahl>21727</Postleitzahl>
+                     <AS_Telefon>0431789456</AS_Telefon>
+                     <Wohnort>ESTORF</Wohnort>
+                     <Straße>OSTERBERG</Straße>
+                     <Hausnummer>24</Hausnummer>
+                  </Adresse_Kiel_vorbefüllt_mit_Kontaktdaten>
+                  <Angabe_zur_Person__Firma>männlich</Angabe_zur_Person__Firma>
+                  <Verantwortliche_Person_für_die_Aufstellung_der_Beschilderung/>
+                  <AS_Name1>
+                     <AS_Name1>
+                        <AS_Vorname>CHRISTOPH ALÄXANDER</AS_Vorname>
+                        <AS_Name>STEUBER</AS_Name>
+                     </AS_Name1>
+                  </AS_Name1>
+               </Stammdaten__Antragstellende_Person_>
+               <Antrag_abschließen>
+                  <Ich_bestätige__dass_die_Beschilderung_entsprechend_den_wichtigen_Hinweisen_durchgeführt_wird>ja</Ich_bestätige__dass_die_Beschilderung_entsprechend_den_wichtigen_Hinweisen_durchgeführt_wird>
+                  <Hiermit_bestätige_ich_die_Kenntnisnahme_des_Vorgehens_bei_parkenden_KFZ>ja</Hiermit_bestätige_ich_die_Kenntnisnahme_des_Vorgehens_bei_parkenden_KFZ>
+                  <Ich_bestätige_hiermit__dass_ein_Protokoll_entsprechend_den_wichtigen_Hinweisen_erstellt_wird>ja</Ich_bestätige_hiermit__dass_ein_Protokoll_entsprechend_den_wichtigen_Hinweisen_erstellt_wird>
+                  <Hiermit_bestätige_ich_die_Richtigkeit_der_gemachten_Angaben>ja</Hiermit_bestätige_ich_die_Richtigkeit_der_gemachten_Angaben>
+               </Antrag_abschließen>
+               <Angaben_zur_Parkregelung_und_zur_Beschilderung>
+                  <Länge_der_Fläche_in_Metern>10</Länge_der_Fläche_in_Metern>
+                  <Ort_des_Haltverbotes>
+                     <Postleitzahl>24103</Postleitzahl>
+                     <Wohnort>Kiel</Wohnort>
+                     <Straße>Fleet</Straße>
+                     <Hausnummer>9</Hausnummer>
+                  </Ort_des_Haltverbotes>
+                  <Beginn_des_Haltverbotes>06.12.2023</Beginn_des_Haltverbotes>
+                  <Gründe>
+                     <Container>nein</Container>
+                     <Baufahrzeug>nein</Baufahrzeug>
+                     <Materiallagerung>nein</Materiallagerung>
+                     <Umzug>ja</Umzug>
+                     <Hubsteiger__Kran>nein</Hubsteiger__Kran>
+                     <Sonstiges>nein</Sonstiges>
+                  </Gründe>
+                  <Uhrzeit>
+                     <ganztägig>ja</ganztägig>
+                  </Uhrzeit>
+                  <Vor_Ort_geltende_Parkregelung>Parken am Seitenstreifen</Vor_Ort_geltende_Parkregelung>
+                  <Objektgruppe_Hinweis_kein_Abschleppen_möglich/>
+                  <Tage_Haltverbot>
+                     <Freitag>nein</Freitag>
+                     <Samstag>nein</Samstag>
+                     <Montag>nein</Montag>
+                     <Mittwoch>ja</Mittwoch>
+                     <Donnerstag>nein</Donnerstag>
+                     <Dienstag>nein</Dienstag>
+                     <Sonntag>nein</Sonntag>
+                  </Tage_Haltverbot>
+                  <Ende_des_Haltverbotes>06.12.2023</Ende_des_Haltverbotes>
+               </Angaben_zur_Parkregelung_und_zur_Beschilderung>
+               <Informationen_und_Hinweise_zu_erforderlichen_Unterlagen/>
+            </formData>
+         </eingang>
+         <vorgangNummer>KFAS_LIVE_KI_10_Haltverbot_befristet-GZpJckhu</vorgangNummer>
+         <aktenzeichen/>
+      </vorgang>
+      <Dateiname>Fleet_9-Verk-AO_01-08_06.12.2023-06.12.2023</Dateiname>
+      <Dateiname>Fleet_9-Verk-AO_01-08_06.12.2023-06.12.2023</Dateiname>
+   </CustomerData>
+</root>
\ No newline at end of file
diff --git a/bescheid-manager/src/test/resources/application-itcase.yml b/bescheid-manager/src/test/resources/application-itcase.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c1a93efc5a28691d088b6b641637ca0a61e11936
--- /dev/null
+++ b/bescheid-manager/src/test/resources/application-itcase.yml
@@ -0,0 +1,16 @@
+logging:
+  level:
+    ROOT: WARN,
+    '[org.springframework]': ERROR
+    '[de.ozgcloud]': WARN
+  config: classpath:log4j2-local.xml
+  
+ozgcloud:
+  bescheid:
+    smart-documents:
+      url: https://demo-de.smartdocuments.com/wsxmldeposit/deposit/unattended
+      basicAuth:
+        username: 
+        password: 
+      templateGroup: Kiel
+      template: Halteverbot
diff --git a/mail-service/src/test/resources/junit-platform.properties b/bescheid-manager/src/test/resources/junit-platform.properties
similarity index 100%
rename from mail-service/src/test/resources/junit-platform.properties
rename to bescheid-manager/src/test/resources/junit-platform.properties
diff --git a/mail-service/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/bescheid-manager/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
similarity index 100%
rename from mail-service/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
rename to bescheid-manager/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
diff --git a/dependency-check-supressions.xml b/dependency-check-supressions.xml
new file mode 100644
index 0000000000000000000000000000000000000000..db1350f8a83ff8c231b055286a017cd62152964f
--- /dev/null
+++ b/dependency-check-supressions.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
+   <suppress>
+      <vulnerabilityName>CVE-DUMMY</vulnerabilityName>
+   </suppress>
+</suppressions>
\ No newline at end of file
diff --git a/pluto-server/lombok.config b/lombok.config
similarity index 94%
rename from pluto-server/lombok.config
rename to lombok.config
index d07dd9b0e2b0281fbf514a968b9451cb6af62f93..81661f0fd9c5f6e2f40f39aa9ee13f7017fc2726 100644
--- a/pluto-server/lombok.config
+++ b/lombok.config
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
 # Ministerpräsidenten des Landes Schleswig-Holstein
 # Staatskanzlei
 # Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
diff --git a/mail-service/lombok.config b/mail-service/lombok.config
deleted file mode 100644
index e2cecc9355b20d3ec85afca7daa6c78e6b2082ee..0000000000000000000000000000000000000000
--- a/mail-service/lombok.config
+++ /dev/null
@@ -1,28 +0,0 @@
-#   Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
-#   Ministerpräsidenten des Landes Schleswig-Holstein
-#   Staatskanzlei
-#   Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-#
-#   Lizenziert unter der EUPL, Version 1.2 oder - sobald
-#   diese von der Europäischen Kommission genehmigt wurden -
-#   Folgeversionen der EUPL ("Lizenz");
-#   Sie dürfen dieses Werk ausschließlich gemäß
-#   dieser Lizenz nutzen.
-#   Eine Kopie der Lizenz finden Sie hier:
-#
-#   https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-#
-#   Sofern nicht durch anwendbare Rechtsvorschriften
-#   gefordert oder in schriftlicher Form vereinbart, wird
-#   die unter der Lizenz verbreitete Software "so wie sie
-#   ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-#   ausdrücklich oder stillschweigend - verbreitet.
-#   Die sprachspezifischen Genehmigungen und Beschränkungen
-#   unter der Lizenz sind dem Lizenztext zu entnehmen.
-
-lombok.log.fieldName=LOG
-lombok.log.slf4j.flagUsage = ERROR
-lombok.log.log4j.flagUsage = ERROR
-lombok.data.flagUsage = ERROR
-lombok.nonNull.exceptionType = IllegalArgumentException
-lombok.addLombokGeneratedAnnotation = true
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachEventListener.java b/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachEventListener.java
deleted file mode 100644
index b0350dc17fd7481e682f44b0e28405956cb512d9..0000000000000000000000000000000000000000
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachEventListener.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.mail.postfach;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.function.Predicate;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Component;
-
-import de.itvsh.ozg.mail.postfach.Message.ReplyOption;
-import de.itvsh.ozg.mail.postfach.PostfachMail.Direction;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEvent;
-import lombok.extern.log4j.Log4j2;
-
-@Component
-@Log4j2
-public class PostfachEventListener {
-
-	private static final String IS_SEND_POSTFACH_NACHRICHT_COMMAND = "{T(de.itvsh.ozg.mail.postfach.PostfachEventListener).IS_SEND_POSTFACH_NACHRICHT.test(event.getSource())}";
-
-	public static final Predicate<Command> IS_SEND_POSTFACH_NACHRICHT = command -> command.getOrder().equals("SEND_POSTFACH_NACHRICHT");
-
-	@Autowired
-	private PostfachService service;
-
-	@EventListener(condition = IS_SEND_POSTFACH_NACHRICHT_COMMAND)
-	public void sendPostfachNachricht(CommandCreatedEvent event) {
-		var command = event.getSource();
-		try {
-			service.sendMail(command.getId(), command.getCreatedBy(), buildNachricht(command, command.getBodyObject()));
-		} catch (RuntimeException e) {
-			service.publishMailSentFailedEvent(command.getId(), "Error on sending Postfach Nachricht: " + e.getMessage());
-			LOG.error("Error on sending Postfach Nachricht.", e);
-		}
-
-	}
-
-	private PostfachMail buildNachricht(Command command, Map<String, Object> commandBody) {
-		return PostfachMail.builder()
-				.vorgangId(command.getRelationId())
-				.postfachId(getStringValue(commandBody, PostfachMail.FIELD_POSTFACH_ID))
-				.replyOption(ReplyOption.valueOf(getStringValue(commandBody, PostfachMail.FIELD_REPLY_OPTION)))
-				.createdBy(command.getCreatedBy())
-				.direction(Direction.OUT)
-				.subject(getStringValue(commandBody, PostfachMail.FIELD_SUBJECT))
-				.mailBody(getStringValue(commandBody, PostfachMail.FIELD_MAIL_BODY))
-				.attachments(getStringListValue(commandBody, PostfachMail.FIELD_ATTACHMENTS))
-				.build();
-	}
-
-	private String getStringValue(Map<String, Object> commandBody, String fieldName) {
-		return Optional.ofNullable(
-				commandBody.get(fieldName)).map(Object::toString).orElse(null);
-	}
-
-	List<String> getStringListValue(Map<String, Object> commandBody, String fieldName) {
-		return Optional.ofNullable(commandBody.get(fieldName))
-				.filter(Objects::nonNull)
-				.map(this::mapObjectToList)
-				.orElse(Collections.emptyList());
-	}
-
-	private List<String> mapObjectToList(Object object) {
-		if (object instanceof Collection<?> objects) {
-			return objects.stream().map(Objects::toString).toList();
-		} else {
-			return List.of(object.toString());
-		}
-	}
-}
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailMapper.java b/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailMapper.java
deleted file mode 100644
index cc8232ec653f343e41e28e54fb7089f5a537b246..0000000000000000000000000000000000000000
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailMapper.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.mail.postfach;
-
-import java.time.ZonedDateTime;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.lang3.StringUtils;
-import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
-import org.mapstruct.MappingConstants;
-import org.mapstruct.ReportingPolicy;
-import org.mapstruct.ValueMapping;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import de.itvsh.ozg.mail.postfach.Message.ReplyOption;
-import de.itvsh.ozg.mail.postfach.PostfachMail.Direction;
-
-@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN)
-public abstract class PostfachMailMapper {
-
-	@Autowired
-	private AttachmentService attachmentService;
-
-	@Mapping(target = "attachment", ignore = true)
-	@Mapping(target = "messageId", ignore = true)
-
-	@Mapping(target = "isHtml", constant = "false")
-	@Mapping(target = "rechtsverbindlich", constant = "false")
-	@Mapping(target = "eidasLevel", constant = "MEDIUM")
-	public abstract Message toOsiMessage(PostfachMail mail);
-
-	List<MessageAttachment> map(List<String> attachedFileIds) {
-		return attachedFileIds.stream().map(FileId::from).map(fileId -> attachmentService.getMessageAttachment(fileId)).toList();
-	}
-
-	@Mapping(target = "attachments", source = "attachmentList")
-	@Mapping(target = "createdAt", ignore = true)
-	@Mapping(target = "createdBy", ignore = true)
-	@Mapping(target = "direction", ignore = true)
-	@Mapping(target = "messageId", ignore = true)
-	@Mapping(target = "sentAt", ignore = true)
-	@Mapping(target = "sentSuccessful", ignore = true)
-
-	@ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL)
-	@ValueMapping(source = "UNDEFINED", target = MappingConstants.NULL)
-	public abstract PostfachMail fromGrpcMail(GrpcPostfachMail grpcMail);
-
-	@SuppressWarnings("unchecked")
-	public GrpcPostfachMail fromMap(Map<String, Object> mailMap) {
-		return GrpcPostfachMail.newBuilder()
-				.setId((String) mailMap.get(PostfachMail.FIELD_ID))
-				.setVorgangId((String) mailMap.get(PostfachMail.FIELD_VORGANG_ID))
-				.setPostfachId((String) mailMap.get(PostfachMail.FIELD_POSTFACH_ID))
-				.setCreatedAt((String) mailMap.get(PostfachMail.FIELD_CREATED_AT))
-				.setCreatedBy((String) mailMap.getOrDefault(PostfachMail.FIELD_CREATED_BY, StringUtils.EMPTY))
-				.setSentAt((String) mailMap.getOrDefault(PostfachMail.FIELD_SENT_AT, StringUtils.EMPTY))
-				.setSentSuccessful((Boolean) mailMap.getOrDefault(PostfachMail.FIELD_SENT_SUCCESSFUL, false))
-				.setMessageCode((String) mailMap.getOrDefault(PostfachMail.FIELD_MESSAGE_CODE, StringUtils.EMPTY))
-				.setDirection(GrpcDirection.valueOf(((String) mailMap.get(PostfachMail.FIELD_DIRECTION))))
-				.setSubject((String) mailMap.get(PostfachMail.FIELD_SUBJECT))
-				.setMailBody((String) mailMap.get(PostfachMail.FIELD_MAIL_BODY))
-				.setReplyOption(((String) mailMap.get(PostfachMail.FIELD_REPLY_OPTION)))
-				.addAllAttachment((Iterable<String>) mailMap.getOrDefault(PostfachMail.FIELD_ATTACHMENTS, Collections.emptyList()))
-				.build();
-	}
-
-	@Mapping(target = "createdBy", ignore = true)
-	@Mapping(target = "id", ignore = true)
-	@Mapping(target = "messageCode", ignore = true)
-	@Mapping(target = "sentAt", ignore = true)
-	@Mapping(target = "sentSuccessful", ignore = true)
-	@Mapping(target = "createdAt", expression = "java(java.time.ZonedDateTime.now())")
-	@Mapping(target = "direction", constant = "IN")
-	@Mapping(target = "attachments", expression = "java(persistAttachements(message.getVorgangId() ,message.getAttachments()))")
-	public abstract PostfachMail toMail(Message message);
-
-	List<String> persistAttachements(String vorgangId, List<MessageAttachment> attachments) {
-		return attachments.stream().map(attachment -> attachmentService.persistAttachment(vorgangId, attachment)).toList();
-	}
-
-	@SuppressWarnings("unchecked")
-	PostfachMail fromMapToPostfachMail(Map<String, Object> mailMap) {
-		return PostfachMail.builder()
-				.id((String) mailMap.get(PostfachMail.FIELD_ID))
-				.vorgangId((String) mailMap.get(PostfachMail.FIELD_VORGANG_ID))
-				.postfachId((String) mailMap.get(PostfachMail.FIELD_POSTFACH_ID))
-				.messageId((String) mailMap.get(PostfachMail.FIELD_MESSAGE_ID))
-				.createdAt(ZonedDateTime.parse((String) mailMap.get(PostfachMail.FIELD_CREATED_AT)))
-				.createdBy((String) mailMap.get(PostfachMail.FIELD_CREATED_BY))
-				.sentAt(ZonedDateTime.parse((String) mailMap.get(PostfachMail.FIELD_SENT_AT)))
-				.sentSuccessful((Boolean) mailMap.get(PostfachMail.FIELD_SENT_SUCCESSFUL))
-				.messageCode((String) mailMap.get(PostfachMail.FIELD_MESSAGE_CODE))
-				.direction(Direction.valueOf((String) mailMap.get(PostfachMail.FIELD_DIRECTION)))
-				.subject((String) mailMap.get(PostfachMail.FIELD_SUBJECT))
-				.mailBody((String) mailMap.get(PostfachMail.FIELD_MAIL_BODY))
-				.replyOption(ReplyOption.valueOf((String) mailMap.get(PostfachMail.FIELD_REPLY_OPTION)))
-				.attachments((List<String>) mailMap.getOrDefault(PostfachMail.FIELD_ATTACHMENTS, Collections.emptyList()))
-				.build();
-	}
-}
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachService.java b/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachService.java
deleted file mode 100644
index 40c54dd203e7f193a3498ec3d26066b1b23881e2..0000000000000000000000000000000000000000
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachService.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.mail.postfach;
-
-import java.time.ZonedDateTime;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Stream;
-
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import de.itvsh.ozg.mail.attributes.ClientAttributeService;
-import de.itvsh.ozg.mail.postfach.PostfachMail.Direction;
-import lombok.NonNull;
-import lombok.extern.log4j.Log4j2;
-
-@Log4j2
-@Service
-@Validated
-class PostfachService {
-
-	@Autowired
-	private OsiPostfachService osiPostfachService;
-	@Autowired
-	private PostfachMailMapper mapper;
-
-	@Autowired
-	private PersistPostfachMailService persistingService;
-	@Autowired
-	private ClientAttributeService clientAttributeService;
-
-	@Autowired
-	private ApplicationEventPublisher publisher;
-
-	public void sendMail(String commandId, String userId, @Valid PostfachMail mail) {
-		var sendResponse = handleSendMail(commandId, mail);
-		persistSentMail(userId, addMailSentInformation(mail, sendResponse));
-	}
-
-	PostfachMail addMailSentInformation(PostfachMail mail, SendPostfachNachrichtResponse sendResponse) {
-		return mail.toBuilder().sentAt(ZonedDateTime.now()).sentSuccessful(sendResponse.isSentSuccessful())
-				.messageCode(sendResponse.getMessageCode().getMessageCode())
-				.build();
-	}
-
-	void persistSentMail(@NonNull String userId, PostfachMail mail) {
-		persistingService.persistMail(Optional.of(userId), mail.toBuilder()
-				.direction(Direction.OUT)
-				.createdAt(ZonedDateTime.now().withNano(0)).createdBy(userId)
-				.build());
-
-		clientAttributeService.setHasPostfachNachricht(mail.getVorgangId());
-	}
-
-	public Optional<Map<String, Object>> findById(String nachrichtId) {
-		return persistingService.findById(nachrichtId);
-	}
-
-	public Stream<Map<String, Object>> findByVorgang(String vorgangId) {
-		return persistingService.findByVorgangAsMap(vorgangId);
-	}
-
-	public void fetchAndPersistReplies() {
-		osiPostfachService.getAllMessages().map(mapper::toMail).forEach(this::persistMail);
-	}
-
-	private void persistMail(PostfachMail mail) {
-		persistingService.persistMail(Optional.empty(), mail);
-
-		clientAttributeService.setHasNewPostfachNachricht(mail.getVorgangId());
-
-		osiPostfachService.deleteMessage(mail.getMessageId());
-	}
-
-	public void resendMail(String commandId, String postfachMailId) {
-		PostfachMail mail = mapper.fromMapToPostfachMail(persistingService.getById(postfachMailId));
-
-		var sendResponse = handleSendMail(commandId, mail);
-		patchMail(mail.getId(), createResendPatchMap(sendResponse));
-	}
-
-	SendPostfachNachrichtResponse handleSendMail(String commandId, PostfachMail mail) {
-		try {
-			doSendMail(mail);
-
-			publishMailSentEvent(commandId);
-			return buildSendNachrichtResponse(true, OsiPostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE);
-		} catch (OsiPostfachServerProcessException e) {
-			return proceedwithWarnException(commandId, e);
-
-		} catch (OsiPostfachException e) {
-			return proceedWithErrorException(commandId, e);
-		}
-	}
-
-	SendPostfachNachrichtResponse proceedwithWarnException(String commandId, OsiPostfachServerProcessException e) {
-		LOG.warn(e.getMessage(), e);
-		return proceedWithException(commandId, e);
-	}
-
-	SendPostfachNachrichtResponse proceedWithErrorException(String commandId, OsiPostfachException e) {
-		LOG.error(e.getMessage(), e);
-		return proceedWithException(commandId, e);
-	}
-
-	private SendPostfachNachrichtResponse proceedWithException(String commandId, OsiPostfachException e) {
-		publishMailSentFailedEvent(commandId, e.getMessage());
-		return buildSendNachrichtResponse(false, e.getMessageCode());
-
-	}
-
-	void doSendMail(PostfachMail mail) {
-		osiPostfachService.sendMessage(mapper.toOsiMessage(mail));
-	}
-
-	private void publishMailSentEvent(String commandId) {
-		publisher.publishEvent(new PostfachMailSentEvent(commandId));
-	}
-
-	public void publishMailSentFailedEvent(String commandId, String message) {
-		publisher.publishEvent(new PostfachMailSentFailedEvent(commandId, message));
-	}
-
-	private SendPostfachNachrichtResponse buildSendNachrichtResponse(boolean sentSuccesful, OsiPostfachMessageCode messageCode) {
-		return SendPostfachNachrichtResponse.builder().sentSuccessful(sentSuccesful).messageCode(messageCode).build();
-	}
-
-	Map<String, Object> createResendPatchMap(SendPostfachNachrichtResponse sendResponse) {
-		return Map.of(PostfachMail.FIELD_SENT_AT, ZonedDateTime.now().withNano(0).toString(),
-				PostfachMail.FIELD_SENT_SUCCESSFUL, sendResponse.isSentSuccessful(),
-				PostfachMail.FIELD_MESSAGE_CODE, sendResponse.getMessageCode().getMessageCode());
-	}
-
-	private void patchMail(String postfachMailId, Map<String, Object> propertyMap) {
-		persistingService.patch(postfachMailId, propertyMap);
-	}
-
-	public boolean isPostfachConfigured() {
-		return osiPostfachService.isConfigured();
-	}
-
-}
\ No newline at end of file
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachEventListenerTest.java b/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachEventListenerTest.java
deleted file mode 100644
index 126e9a572310a5c6d1653883c87a3060920e26cf..0000000000000000000000000000000000000000
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachEventListenerTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.mail.postfach;
-
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import static org.assertj.core.api.Assertions.*;
-
-import de.itvsh.ozg.mail.postfach.PostfachMail.Direction;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEvent;
-
-class PostfachEventListenerTest {
-
-	@InjectMocks
-	private PostfachEventListener listener;
-
-	@Mock
-	private PostfachService service;
-	@Mock
-	private Command command;
-
-	@Captor
-	private ArgumentCaptor<PostfachMail> nachrichtCaptor;
-
-	@DisplayName("Send postfach nachricht")
-	@Nested
-	class TestSendPostfachNachricht {
-
-		private static final String COMMAND_ID = UUID.randomUUID().toString();
-		private static final String USER_ID = PostfachMailTestFactory.CREATED_BY;
-
-		@BeforeEach
-		void mockCommand() {
-			when(command.getId()).thenReturn(COMMAND_ID);
-			when(command.getCreatedBy()).thenReturn(USER_ID);
-			when(command.getRelationId()).thenReturn(MessageTestFactory.VORGANG_ID);
-			when(command.getBodyObject()).thenReturn(buildCommandBody());
-		}
-
-		@Test
-		void shouldCallService() {
-			listener.sendPostfachNachricht(new CommandCreatedEvent(command));
-
-			verify(service).sendMail(eq(COMMAND_ID), eq(USER_ID), nachrichtCaptor.capture());
-
-			assertThat(nachrichtCaptor.getValue())
-					.usingRecursiveComparison().ignoringFields("id", "createdAt", "messageCode", "messageId", "sentAt", "sentSuccessful")
-					.isEqualTo(PostfachMailTestFactory.createBuilder().direction(Direction.OUT)
-							.build());
-		}
-
-		private Map<String, Object> buildCommandBody() {
-			return Map.of(
-					PostfachMail.FIELD_VORGANG_ID, "fake",
-					PostfachMail.FIELD_POSTFACH_ID, MessageTestFactory.POSTFACH_ID,
-					PostfachMail.FIELD_SUBJECT, MessageTestFactory.SUBJECT,
-					PostfachMail.FIELD_MAIL_BODY, MessageTestFactory.MAIL_BODY,
-					PostfachMail.FIELD_REPLY_OPTION, MessageTestFactory.REPLY_OPTION.name(),
-					PostfachMail.FIELD_ATTACHMENTS, PostfachMailTestFactory.ATTACHMENTS);
-		}
-	}
-
-	@DisplayName("Get string list value")
-	@Nested
-	class TestGetStringListValue {
-
-		@Test
-		void shouldReturnMultipleValuesFieldAsStringList() {
-			var commandBodyMap = new HashMap<String, Object>();
-			commandBodyMap.put(PostfachMail.FIELD_ATTACHMENTS, List.of("1", "2"));
-
-			var list = listener.getStringListValue(commandBodyMap, PostfachMail.FIELD_ATTACHMENTS);
-
-			assertThat(list).contains("1").contains("2");
-		}
-
-		@Test
-		void shouldReturnSingleValueFieldAsStringList() {
-			var commandBodyMap = new HashMap<String, Object>();
-			commandBodyMap.put(PostfachMail.FIELD_ATTACHMENTS, List.of("1", "2"));
-
-			var list = listener.getStringListValue(commandBodyMap, PostfachMail.FIELD_ATTACHMENTS);
-
-			assertThat(list).contains("1").contains("2");
-		}
-
-		@Test
-		void shouldReturnEmptyFieldValueAsEmptyCollection() {
-			var commandBodyMap = new HashMap<String, Object>();
-			commandBodyMap.put(PostfachMail.FIELD_ATTACHMENTS, Collections.emptyList());
-
-			var list = listener.getStringListValue(commandBodyMap, PostfachMail.FIELD_ATTACHMENTS);
-
-			assertThat(list).isEmpty();
-		}
-
-		@Test
-		void shouldReturnEmptyFieldAsEmptyCollection() {
-			var commandBodyMap = new HashMap<String, Object>();
-
-			var list = listener.getStringListValue(commandBodyMap, PostfachMail.FIELD_ATTACHMENTS);
-
-			assertThat(list).isEmpty();
-		}
-	}
-}
\ No newline at end of file
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailMapperTest.java b/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailMapperTest.java
deleted file mode 100644
index 32485d0d0f13fe7d5a55f7cfbc0b3fee10418fc2..0000000000000000000000000000000000000000
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailMapperTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.mail.postfach;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import java.time.ZonedDateTime;
-import java.time.temporal.ChronoUnit;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mapstruct.factory.Mappers;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import de.itvsh.ozg.mail.postfach.PostfachMail.Direction;
-
-class PostfachMailMapperTest {
-
-	@InjectMocks
-	private PostfachMailMapper mapper = Mappers.getMapper(PostfachMailMapper.class);
-	@Mock
-	private AttachmentService attachmentService;
-
-	@Nested
-	class TestFromMap {
-		@Test
-		void shouldFillGrpcMail() {
-			var grpcMail = mapper.fromMap(PostfachMailTestFactory.asMap());
-
-			assertThat(grpcMail).usingRecursiveComparison().isEqualTo(GrpcPostfachMailTestFactory.create());
-		}
-
-		@Test
-		void shouldIgnoreSentSuccessful() {
-			var grpcMail = mapper.fromMap(getMapWithoutProperty(PostfachMail.FIELD_SENT_SUCCESSFUL));
-
-			assertThat(grpcMail.getSentSuccessful()).isFalse();
-		}
-
-		@Test
-		void shouldIgnoreSentAt() {
-			var grpcMail = mapper.fromMap(getMapWithoutProperty(PostfachMail.FIELD_SENT_AT));
-
-			assertThat(grpcMail.getSentAt()).isEmpty();
-		}
-
-		private Map<String, Object> getMapWithoutProperty(String entryKey) {
-			Map<String, Object> map = PostfachMailTestFactory.asMap();
-			map.remove(entryKey);
-			return map;
-		}
-	}
-
-	@Nested
-	class TestToMail {
-		@Test
-		void shouldSetDirection() {
-			var mail = mapper.toMail(MessageTestFactory.create());
-
-			assertThat(mail.getDirection()).isEqualTo(Direction.IN);
-		}
-
-		@Test
-		void shouldSetCreatedAt() {
-			var mail = mapper.toMail(MessageTestFactory.create());
-
-			assertThat(mail.getCreatedAt()).isNotNull().isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS));
-		}
-
-		@Test
-		void shouldIgnoreSentInformation() {
-			var mail = mapper.toMail(MessageTestFactory.create());
-
-			assertThat(mail.getSentAt()).isNull();
-			assertThat(mail.getSentSuccessful()).isNull();
-		}
-
-		@Test
-		void shouldPersistAttachment() {
-			mapper.toMail(MessageTestFactory.create());
-
-			verify(attachmentService).persistAttachment(MessageTestFactory.VORGANG_ID, MessageTestFactory.ATTACHMENTS.get(0));
-		}
-	}
-
-	@Nested
-	class TestFromMapToPostfachMail {
-
-		@Test
-		void shouldMap() {
-			var mail = mapper.fromMapToPostfachMail(PostfachMailTestFactory.asMap());
-
-			assertThat(mail).usingRecursiveComparison().isEqualTo(PostfachMailTestFactory.create());
-		}
-	}
-
-	@Nested
-	class TestToOsiMessage {
-
-		@Test
-		void shouldCallAttachmentService() {
-			var fileId = FileId.from("42");
-
-			mapper.toOsiMessage(PostfachMailTestFactory.createBuilder().attachments(List.of(fileId.toString())).build());
-
-			verify(attachmentService).getMessageAttachment(fileId);
-		}
-
-		@Test
-		void shouldMap() {
-			var message = mapper.toOsiMessage(PostfachMailTestFactory.create());
-
-			assertThat(message.getSubject()).isEqualTo(MessageTestFactory.SUBJECT);
-			assertThat(message.getAttachments()).hasSize(1);
-		}
-	}
-}
\ No newline at end of file
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailTestFactory.java b/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailTestFactory.java
deleted file mode 100644
index 4ec37e0cf62295c9e92d6ed14d3bf1b229704f22..0000000000000000000000000000000000000000
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailTestFactory.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.mail.postfach;
-
-import static de.itvsh.ozg.mail.postfach.MessageTestFactory.*;
-
-import java.time.ZonedDateTime;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import de.itvsh.ozg.mail.postfach.PostfachMail.Direction;
-
-public class PostfachMailTestFactory {
-
-	public static final String ID = UUID.randomUUID().toString();
-	public static final String CREATED_AT_STR = "2020-04-01T10:30:10Z";
-	public static final ZonedDateTime CREATED_AT = ZonedDateTime.parse(CREATED_AT_STR);
-	public static final String CREATED_BY = UUID.randomUUID().toString();
-
-	public static final String SENT_AT_STR = "2020-04-01T11:30:10Z";
-	public static final ZonedDateTime SENT_AT = ZonedDateTime.parse(SENT_AT_STR);
-	public static final boolean SENT_SUCCESSFUL = true;
-	public static final String MESSAGE_CODE = OsiPostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE.getMessageCode();
-
-	public static PostfachMail.Direction DIRECTION = Direction.IN;
-	public static final List<String> ATTACHMENTS = List.of("21");
-
-	public static PostfachMail create() {
-		return createBuilder().build();
-	}
-
-	public static PostfachMail.PostfachMailBuilder createBuilder() {
-		return PostfachMail.builder()
-				.id(ID)
-				.postfachId(POSTFACH_ID)
-				.messageId(MESSAGE_ID)
-				.vorgangId(VORGANG_ID)
-				.direction(DIRECTION)
-				.createdAt(CREATED_AT)
-				.createdBy(CREATED_BY)
-				.sentAt(SENT_AT)
-				.sentSuccessful(SENT_SUCCESSFUL)
-				.messageCode(MESSAGE_CODE)
-				.replyOption(REPLY_OPTION)
-				.subject(SUBJECT)
-				.mailBody(MAIL_BODY)
-				.attachments(ATTACHMENTS);
-	}
-
-	public static Map<String, Object> asMap() {
-		HashMap<String, Object> map = new HashMap<>();
-		map.put(PostfachMail.FIELD_ID, ID);
-		map.put(PostfachMail.FIELD_POSTFACH_ID, POSTFACH_ID);
-		map.put(PostfachMail.FIELD_MESSAGE_ID, MESSAGE_ID);
-		map.put(PostfachMail.FIELD_VORGANG_ID, VORGANG_ID);
-		map.put(PostfachMail.FIELD_DIRECTION, DIRECTION.name());
-		map.put(PostfachMail.FIELD_CREATED_AT, CREATED_AT_STR);
-		map.put(PostfachMail.FIELD_CREATED_BY, CREATED_BY);
-		map.put(PostfachMail.FIELD_SENT_AT, SENT_AT_STR);
-		map.put(PostfachMail.FIELD_SENT_SUCCESSFUL, SENT_SUCCESSFUL);
-		map.put(PostfachMail.FIELD_MESSAGE_CODE, MESSAGE_CODE);
-		map.put(PostfachMail.FIELD_REPLY_OPTION, REPLY_OPTION.name());
-		map.put(PostfachMail.FIELD_SUBJECT, SUBJECT);
-		map.put(PostfachMail.FIELD_MAIL_BODY, MAIL_BODY);
-		map.put(PostfachMail.FIELD_ATTACHMENTS, ATTACHMENTS);
-		return map;
-	}
-}
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachServiceTest.java b/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachServiceTest.java
deleted file mode 100644
index e9a48d528534af05f9c3cd649d6a7dda7cfe626e..0000000000000000000000000000000000000000
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachServiceTest.java
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.mail.postfach;
-
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.time.ZonedDateTime;
-import java.time.temporal.ChronoUnit;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.stream.Stream;
-
-import org.apache.logging.log4j.Logger;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mapstruct.factory.Mappers;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Spy;
-import org.springframework.boot.logging.LogLevel;
-import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.test.util.ReflectionTestUtils;
-
-import static org.assertj.core.api.Assertions.*;
-
-import de.itvsh.ozg.mail.attributes.ClientAttributeService;
-import de.itvsh.ozg.mail.postfach.PostfachMail.Direction;
-import nl.altindag.log.LogCaptor;
-
-class PostfachServiceTest {
-
-	@Spy
-	@InjectMocks
-	private PostfachService service;
-	@Mock
-	private OsiPostfachService osiPostfachService;
-
-	@Mock
-	private PersistPostfachMailService persistingService;
-	@Spy
-	private PostfachMailMapper mapper = Mappers.getMapper(PostfachMailMapper.class);
-
-	@Mock
-	private ClientAttributeService clientAttributeService;
-
-	@Mock
-	private AttachmentService attachmentService;
-
-	@Mock
-	private ApplicationEventPublisher publisher;
-
-	@Nested
-	class TestSendMail {
-
-		static final String COMMAND_ID = UUID.randomUUID().toString();
-		static final String USER_ID = UUID.randomUUID().toString();
-
-		@BeforeEach
-		void init() {
-			ReflectionTestUtils.setField(mapper, "attachmentService", attachmentService);
-		}
-
-		@Test
-		void shouldCallDoSendMail() {
-			var mail = PostfachMailTestFactory.create();
-
-			service.sendMail(COMMAND_ID, USER_ID, mail);
-
-			verify(service).doSendMail(mail);
-		}
-
-		@Test
-		void shouldCallPersistSentMail() {
-			var mail = PostfachMailTestFactory.create();
-			doReturn(mail).when(service).addMailSentInformation(any(PostfachMail.class), any(SendPostfachNachrichtResponse.class));
-
-			service.sendMail(COMMAND_ID, USER_ID, PostfachMailTestFactory.create());
-
-			verify(service).persistSentMail(USER_ID, mail);
-		}
-
-		@Test
-		void shouldAddMailSentInformation() {
-			var postfachMail = service.addMailSentInformation(PostfachMailTestFactory.createBuilder().sentAt(null).sentSuccessful(null).build(),
-					SendPostfachNachrichtResponseTestFactory.create());
-
-			assertThat(postfachMail.getSentAt()).isNotNull();
-			assertThat(postfachMail.getSentSuccessful()).isEqualTo(SendPostfachNachrichtResponseTestFactory.SENT_SUCCESSFUL);
-			assertThat(postfachMail.getMessageCode()).isEqualTo(SendPostfachNachrichtResponseTestFactory.MESSAGE_CODE.getMessageCode());
-		}
-
-		@Test
-		void shouldHandleSendMail() {
-			var mail = PostfachMailTestFactory.create();
-			service.sendMail(COMMAND_ID, USER_ID, mail);
-
-			verify(service).handleSendMail(COMMAND_ID, mail);
-		}
-
-		@Nested
-		class TestPersistSentMail {
-
-			@Captor
-			private ArgumentCaptor<PostfachMail> mailCaptor;
-
-			@Test
-			void shouldCallPersistingService() {
-				var mail = PostfachMailTestFactory.create();
-
-				service.persistSentMail(USER_ID, mail);
-
-				verify(persistingService).persistMail(any(), notNull());
-			}
-
-			@Test
-			void shouldSetDirectionToIN() {
-				service.persistSentMail(USER_ID, PostfachMailTestFactory.createBuilder().direction(null).build());
-
-				verify(persistingService).persistMail(any(), mailCaptor.capture());
-				assertThat(mailCaptor.getValue().getDirection()).isEqualTo(Direction.OUT);
-			}
-
-			@Test
-			void shouldSetCreatedAt() {
-				service.persistSentMail(USER_ID, PostfachMailTestFactory.createBuilder().createdAt(null).build());
-
-				verify(persistingService).persistMail(any(), mailCaptor.capture());
-				assertThat(mailCaptor.getValue().getCreatedAt()).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS));
-			}
-
-			@Test
-			void shouldSetCreatedBy() {
-				service.persistSentMail(USER_ID, PostfachMailTestFactory.createBuilder().createdBy(null).build());
-
-				verify(persistingService).persistMail(any(), mailCaptor.capture());
-				assertThat(mailCaptor.getValue().getCreatedBy()).isEqualTo(USER_ID);
-			}
-
-			@Test
-			void shouldSetUserId() {
-				var mail = PostfachMailTestFactory.create();
-
-				service.persistSentMail(USER_ID, mail);
-
-				verify(persistingService).persistMail(eq(Optional.of(USER_ID)), any());
-			}
-
-			@Test
-			void shouldSetClientAttribute() {
-				service.persistSentMail(USER_ID, PostfachMailTestFactory.create());
-
-				verify(clientAttributeService).setHasPostfachNachricht(MessageTestFactory.VORGANG_ID);
-			}
-		}
-	}
-
-	@Nested
-	class TestFindById {
-		@Test
-		void shouldCallPersistingService() {
-			service.findById(PostfachMailTestFactory.ID);
-
-			verify(persistingService).findById(PostfachMailTestFactory.ID);
-		}
-	}
-
-	@Nested
-	class TestFindByVorgang {
-
-		private static final String VORGANG_ID = UUID.randomUUID().toString();
-
-		@Test
-		void shouldCallPersistingService() {
-			service.findByVorgang(VORGANG_ID);
-
-			verify(persistingService).findByVorgangAsMap(VORGANG_ID);
-		}
-	}
-
-	@Nested
-	class TestFetchAndPersistReplies {
-
-		private static final Message message = MessageTestFactory.create();
-
-		@BeforeEach
-		void initTest() {
-			when(osiPostfachService.getAllMessages()).thenReturn(Stream.of(message));
-			ReflectionTestUtils.setField(mapper, "attachmentService", attachmentService);
-		}
-
-		@Test
-		void shouldCallGetAllMessages() {
-			service.fetchAndPersistReplies();
-
-			verify(osiPostfachService).getAllMessages();
-		}
-
-		@Test
-		void shouldCallMapper() {
-			service.fetchAndPersistReplies();
-
-			verify(mapper).toMail(message);
-		}
-
-		@Test
-		void shouldCallPersistingService() {
-			service.fetchAndPersistReplies();
-
-			verify(persistingService).persistMail(eq(Optional.empty()), any());
-		}
-
-		@Test
-		void shouldCallDelete() {
-			service.fetchAndPersistReplies();
-
-			verify(osiPostfachService).deleteMessage(MessageTestFactory.MESSAGE_ID);
-		}
-
-		@Test
-		void shouldCallClientAttributeService() {
-			service.fetchAndPersistReplies();
-
-			verify(clientAttributeService).setHasNewPostfachNachricht(MessageTestFactory.VORGANG_ID);
-		}
-	}
-
-	@Nested
-	class TestResendPostfachMail {
-
-		static final String COMMAND_ID = UUID.randomUUID().toString();
-		static final PostfachMail mail = PostfachMailTestFactory.create();
-
-		@BeforeEach
-		void mockService() {
-			when(persistingService.getById(anyString())).thenReturn(PostfachMailTestFactory.asMap());
-			doReturn(mail).when(mapper).fromMapToPostfachMail(anyMap());
-			ReflectionTestUtils.setField(mapper, "attachmentService", attachmentService);
-		}
-
-		@Test
-		void shouldCallPersistingServiceGetById() {
-			service.resendMail(COMMAND_ID, PostfachMailTestFactory.ID);
-
-			verify(persistingService).getById(PostfachMailTestFactory.ID);
-		}
-
-		@Test
-		void shouldMapFromMapToPostfachMail() {
-			service.resendMail(COMMAND_ID, PostfachMailTestFactory.ID);
-
-			verify(mapper).fromMapToPostfachMail(PostfachMailTestFactory.asMap());
-		}
-
-		@Test
-		void shouldSendMail() {
-			service.resendMail(COMMAND_ID, PostfachMailTestFactory.ID);
-
-			verify(osiPostfachService).sendMessage(any(Message.class));
-		}
-
-		@Test
-		void shouldCallMapper() {
-			service.resendMail(COMMAND_ID, PostfachMailTestFactory.ID);
-
-			verify(mapper).toOsiMessage(mail);
-		}
-
-		@Test
-		void shouldPatchMail() {
-			service.resendMail(COMMAND_ID, PostfachMailTestFactory.ID);
-
-			verify(persistingService).patch(anyString(), anyMap());
-		}
-
-		@Test
-		void shouldHandleSentMail() {
-			service.resendMail(COMMAND_ID, PostfachMailTestFactory.ID);
-
-			verify(service).handleSendMail(COMMAND_ID, mail);
-		}
-	}
-
-	@Nested
-	class TestCreateResendPatchMap {
-
-		@Test
-		void shouldContainsSentAt() {
-			var map = service.createResendPatchMap(SendPostfachNachrichtResponseTestFactory.create());
-
-			assertThat(map).containsKey(PostfachMail.FIELD_SENT_AT);
-			assertThat(ZonedDateTime.parse(map.get(PostfachMail.FIELD_SENT_AT).toString())).isCloseTo(ZonedDateTime.now(),
-					within(2, ChronoUnit.SECONDS));
-		}
-
-		@Test
-		void shouldContainsSentSuccessful() {
-			var map = service.createResendPatchMap(SendPostfachNachrichtResponseTestFactory.create());
-
-			assertThat(map).containsEntry(PostfachMail.FIELD_SENT_SUCCESSFUL, true);
-		}
-
-		@Test
-		void shouldContainsMessageCode() {
-			var map = service.createResendPatchMap(SendPostfachNachrichtResponseTestFactory.create());
-
-			assertThat(map).containsEntry(PostfachMail.FIELD_MESSAGE_CODE, SendPostfachNachrichtResponseTestFactory.MESSAGE_CODE.getMessageCode());
-		}
-	}
-
-	@DisplayName("Handle send mail")
-	@Nested
-	class TestHandleSendMail {
-
-		final String COMMAND_ID = UUID.randomUUID().toString();
-		final PostfachMail mail = PostfachMailTestFactory.create();
-
-		@BeforeEach
-		void initTest() {
-			ReflectionTestUtils.setField(mapper, "attachmentService", attachmentService);
-		}
-
-		@Test
-		void shouldDoSendMail() {
-			service.handleSendMail(COMMAND_ID, mail);
-
-			verify(service).doSendMail(mail);
-		}
-
-		@Nested
-		class TestSentSuccess {
-
-			@Captor
-			private ArgumentCaptor<PostfachMailSentEvent> eventCaptor;
-
-			@Test
-			void shouldDoSendMail() {
-				service.handleSendMail(COMMAND_ID, mail);
-
-				verify(service).doSendMail(mail);
-			}
-
-			@Test
-			void shouldPublishEvent() {
-				service.handleSendMail(COMMAND_ID, mail);
-
-				verify(publisher).publishEvent(eventCaptor.capture());
-				assertThat(eventCaptor.getValue().getSource()).isEqualTo(COMMAND_ID);
-			}
-
-			@Test
-			void shouldReturnResponse() {
-				var response = service.handleSendMail(COMMAND_ID, mail);
-
-				assertThat(response.isSentSuccessful()).isTrue();
-				assertThat(response.getMessageCode()).isEqualTo(OsiPostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE);
-			}
-		}
-
-		@DisplayName("receive")
-		@Nested
-		class TestSentFailed {
-
-			@Captor
-			private ArgumentCaptor<PostfachMailSentFailedEvent> eventFailedCaptor;
-
-			@DisplayName("OsiPostfachException")
-			@Nested
-			class TestOnOsiPostfachException {
-
-				private final static String MESSAGE = "Osi Postfach throws an exception.";
-
-				@BeforeEach
-				void mockService() {
-					doThrow(new OsiPostfachException(MESSAGE, OsiPostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE)).when(osiPostfachService)
-							.sendMessage(any());
-				}
-
-				@Test
-				void shouldPublishEvent() {
-					service.handleSendMail(COMMAND_ID, mail);
-
-					verify(publisher).publishEvent(eventFailedCaptor.capture());
-					assertThat(eventFailedCaptor.getValue().getSource()).isEqualTo(COMMAND_ID);
-					assertThat(eventFailedCaptor.getValue().getErrorMessage()).isEqualTo(MESSAGE);
-				}
-
-				@Test
-				void shouldLogError() {
-					var logCaptor = LogCaptor.forClass(PostfachService.class);
-
-					service.handleSendMail(COMMAND_ID, mail);
-
-					verify(service).proceedWithErrorException(eq(COMMAND_ID), any(OsiPostfachException.class));
-					assertThat(logCaptor.getLogEvents().get(0).getLevel()).isEqualTo(LogLevel.ERROR.name());
-					assertThat(logCaptor.getLogEvents().get(0).getMessage()).isEqualTo(MESSAGE);
-				}
-
-				@Test
-				void shouldReturnResponse() {
-					var response = service.handleSendMail(COMMAND_ID, mail);
-
-					assertThat(response.isSentSuccessful()).isFalse();
-					assertThat(response.getMessageCode()).isEqualTo(OsiPostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE);
-				}
-			}
-
-			@DisplayName("OsiPostfachServerProcessException")
-			@Nested
-			class TestOsiPostfachServerProcessException {
-
-				private final static String MESSAGE = "Osi-Postfach server returned false";
-
-				@Mock
-				private Logger logger;
-
-				@BeforeEach
-				void mockService() {
-					doThrow(new OsiPostfachServerProcessException()).when(osiPostfachService).sendMessage(any());
-				}
-
-				@Test
-				void shouldPublishEvent() {
-					service.handleSendMail(COMMAND_ID, mail);
-
-					verify(publisher).publishEvent(eventFailedCaptor.capture());
-					assertThat(eventFailedCaptor.getValue().getSource()).isEqualTo(COMMAND_ID);
-					assertThat(eventFailedCaptor.getValue().getErrorMessage()).isEqualTo(MESSAGE);
-				}
-
-				@Test
-				void shouldLogWarning() {
-					var logCaptor = LogCaptor.forClass(PostfachService.class);
-
-					service.handleSendMail(COMMAND_ID, mail);
-
-					verify(service).proceedwithWarnException(eq(COMMAND_ID), any(OsiPostfachServerProcessException.class));
-					assertThat(logCaptor.getLogEvents().get(0).getLevel()).isEqualTo(LogLevel.WARN.name());
-					assertThat(logCaptor.getLogEvents().get(0).getMessage()).isEqualTo(MESSAGE);
-				}
-
-				@Test
-				void shouldReturnResponse() {
-					var response = service.handleSendMail(COMMAND_ID, mail);
-
-					assertThat(response.isSentSuccessful()).isFalse();
-					assertThat(response.getMessageCode()).isEqualTo(OsiPostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE);
-				}
-			}
-		}
-
-	}
-
-	@Nested
-	class TestDoSendMail {
-		@Captor
-		private ArgumentCaptor<Message> messageCaptor;
-
-		@BeforeEach
-		void initTest() {
-			ReflectionTestUtils.setField(mapper, "attachmentService", attachmentService);
-			when(attachmentService.getMessageAttachment(any())).thenReturn(MessageAttachmentTestFactory.create());
-		}
-
-		@Test
-		void shouldCallOsiPostfachService() {
-			service.doSendMail(PostfachMailTestFactory.create());
-
-			verify(osiPostfachService).sendMessage(any());
-		}
-
-		@Test
-		void shouldSendFilledMessage() {
-			var expected = MessageTestFactory.createBuilder()
-					.messageId(null)
-					.vorgangId(MessageTestFactory.VORGANG_ID)
-					.rechtsverbindlich(false)
-					.build();
-
-			service.doSendMail(PostfachMailTestFactory.create());
-
-			verify(osiPostfachService).sendMessage(messageCaptor.capture());
-			assertThat(messageCaptor.getValue()).usingRecursiveComparison().isEqualTo(expected);
-
-		}
-	}
-
-	@Nested
-	class TestIsPostfachConfigured {
-
-		@Test
-		void shouldCallOsiPostfachService() {
-			service.isPostfachConfigured();
-
-			verify(osiPostfachService).isConfigured();
-		}
-	}
-}
\ No newline at end of file
diff --git a/mongodb/docker-compose.yml b/mongodb/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1c8da77f84e590e1195a9030abafef65c06eec50
--- /dev/null
+++ b/mongodb/docker-compose.yml
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+version: "2.1"
+services:
+  mongo:
+    image: mongo:4
+    ports:
+     - 27017:27017
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/pom.xml b/nachrichten-bayernid-proxy/bayernid-proxy-impl/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3ca593d77704362af2ae2a4b1be48ec7f25b7e05
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/pom.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>de.ozgcloud.nachrichten</groupId>
+		<artifactId>nachrichten-bayernid-proxy</artifactId>
+		<version>0.1.0</version>
+		<relativePath>../</relativePath>
+	</parent>
+
+	<artifactId>bayernid-proxy-impl</artifactId>
+	<name>OZG Cloud BayernID Proxy Implementation</name>
+
+	<properties>
+		<jaxb-maven-plugin.version>4.0.0</jaxb-maven-plugin.version>
+
+		<spring-boot.build-image.imageName>docker.ozg-sh.de/bayernid-proxy:build-latest</spring-boot.build-image.imageName>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>de.ozgcloud.nachrichten</groupId>
+			<artifactId>bayernid-proxy-interface</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
+		<!-- Spring -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter</artifactId>
+		</dependency>
+		<dependency>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-actuator</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-validation</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.ws</groupId>
+			<artifactId>spring-ws-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-oxm</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.ws</groupId>
+			<artifactId>spring-xml</artifactId>
+		</dependency>
+
+		<!-- commons -->
+		<dependency>
+			<groupId>org.apache.httpcomponents.client5</groupId>
+			<artifactId>httpclient5</artifactId>
+		</dependency>
+
+		<!-- grpc -->
+		<dependency>
+			<groupId>net.devh</groupId>
+			<artifactId>grpc-server-spring-boot-starter</artifactId>
+		</dependency>
+
+		<!-- aspectJ -->
+		<dependency>
+			<groupId>org.aspectj</groupId>
+			<artifactId>aspectjweaver</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.aspectj</groupId>
+			<artifactId>aspectjrt</artifactId>
+		</dependency>
+
+		<!-- Tools -->
+		<dependency>
+			<groupId>org.mapstruct</groupId>
+			<artifactId>mapstruct</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.glassfish.jaxb</groupId>
+			<artifactId>jaxb-runtime</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.dataformat</groupId>
+			<artifactId>jackson-dataformat-xml</artifactId>
+		</dependency>
+
+		<!-- Dev -->
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<optional>true</optional>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- Test -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+			<exclusions>
+				<exclusion>
+					<groupId>org.junit.vintage</groupId>
+					<artifactId>junit-vintage-engine</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>org.junit.jupiter</groupId>
+			<artifactId>junit-jupiter-engine</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.junit.jupiter</groupId>
+			<artifactId>junit-jupiter-params</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.wiremock</groupId>
+			<artifactId>wiremock</artifactId>
+			<version>${wiremock.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>net.devh</groupId>
+			<artifactId>grpc-client-spring-boot-starter</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+	</dependencies>
+
+	<build>
+		<finalName>${project.artifactId}</finalName>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-failsafe-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.jacoco</groupId>
+				<artifactId>jacoco-maven-plugin</artifactId>
+			</plugin>
+			<plugin>
+				<groupId>org.jvnet.jaxb</groupId>
+				<artifactId>jaxb-maven-plugin</artifactId>
+				<version>${jaxb-maven-plugin.version}</version>
+				<configuration>
+					<schemas>
+						<schema>
+							<fileset>
+								<directory>${basedir}/src/main/resources/bayernid</directory>
+								<includes>
+									<include>*.wsdl</include>
+								</includes>
+							</fileset>
+						</schema>
+						<schema>
+							<fileset>
+								<directory>${basedir}/src/main/resources/bayernid</directory>
+								<includes>
+									<include>*.xsd</include>
+								</includes>
+							</fileset>
+						</schema>
+					</schemas>
+					<episode>false</episode>
+				</configuration>
+				<executions>
+					<execution>
+						<goals>
+							<goal>generate</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProperties.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..4fe6e1a75367636864088b1d13b506f7fb393b25
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProperties.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import jakarta.validation.constraints.NotBlank;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Validated
+@Configuration
+@ConfigurationProperties(prefix = "ozgcloud.bayernid")
+public class BayernIdProperties {
+
+	@NotBlank
+	private String server;
+
+	private boolean useSsl = true;
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyApplication.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b47fed8a9a59718b29fab5ac6006b03d81f7294
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyApplication.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import java.util.TimeZone;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@SpringBootApplication
+@EnableAsync(proxyTargetClass = true)
+@EnableAspectJAutoProxy(proxyTargetClass = true)
+public class BayernIdProxyApplication {
+
+	public static void main(String[] args) {
+		TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+		SpringApplication.run(BayernIdProxyApplication.class, args);
+	}
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyConfiguration.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..1705b377cb69f6fea167d7c54dd681289bf0fec8
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyConfiguration.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
+import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
+import org.apache.hc.client5.http.io.HttpClientConnectionManager;
+import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
+import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
+import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
+import org.apache.hc.core5.http.config.RegistryBuilder;
+import org.springframework.boot.ssl.SslBundles;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+import org.springframework.ws.transport.http.HttpComponents5MessageSender;
+
+import akdb.bsp.postkorb.komm.webservice.ObjectFactory;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.akdb.BayernIdRemoteService;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessageMapper;
+import lombok.RequiredArgsConstructor;
+
+@Configuration
+@RequiredArgsConstructor
+class BayernIdProxyConfiguration {
+
+	private final SslBundles sslBundles;
+	private final BayernIdProperties properties;
+
+	@Bean
+	Jaxb2Marshaller createJaxb2Marshaller() {
+		var marshaller = new Jaxb2Marshaller();
+		marshaller.setContextPaths("akdb.bsp.postkorb.komm.webservice", "de.akdb.egov.bsp.nachrichten");
+		return marshaller;
+	}
+
+	@Bean
+	BayernIdRemoteService soapHttpClient(BayernIdMessageMapper messageMapper, Jaxb2Marshaller marshaller) {
+		var bayernIdRemoteService = new BayernIdRemoteService(messageMapper, new ObjectFactory());
+		bayernIdRemoteService.setMarshaller(marshaller);
+		bayernIdRemoteService.setUnmarshaller(marshaller);
+		bayernIdRemoteService.setDefaultUri(properties.getServer());
+		bayernIdRemoteService.setMessageSender(createMessageSender());
+		return bayernIdRemoteService;
+	}
+
+	HttpComponents5MessageSender createMessageSender() {
+		var httpClient = HttpClientBuilder.create()
+				.setConnectionManager(createConnectionManager())
+				.addRequestInterceptorFirst(new HttpComponents5MessageSender.RemoveSoapHeadersInterceptor())
+				.build();
+		return new HttpComponents5MessageSender(httpClient);
+	}
+
+	private HttpClientConnectionManager createConnectionManager() {
+		var socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", new PlainConnectionSocketFactory());
+		if (properties.isUseSsl()) {
+			socketFactoryRegistry.register("https", createSslConnectionSocketFactory());
+		}
+		return new BasicHttpClientConnectionManager(socketFactoryRegistry.build());
+	}
+
+	private SSLConnectionSocketFactory createSslConnectionSocketFactory() {
+		return new SSLConnectionSocketFactory(sslBundles.getBundle("bayern-id-ca").createSslContext());
+	}
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyGrpcService.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyGrpcService.java
new file mode 100644
index 0000000000000000000000000000000000000000..b92528052e8b3685c7d9804dd24e1685b3db5560
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyGrpcService.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.BayernIdProxyServiceGrpc.BayernIdProxyServiceImplBase;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessageMapper;
+import io.grpc.stub.StreamObserver;
+import lombok.RequiredArgsConstructor;
+import net.devh.boot.grpc.server.service.GrpcService;
+
+@GrpcService
+@RequiredArgsConstructor
+public class BayernIdProxyGrpcService extends BayernIdProxyServiceImplBase {
+
+	private final BayernIdProxyService proxyService;
+	private final BayernIdMessageMapper messageMapper;
+
+	@Override
+	public StreamObserver<GrpcSendBayernIdMessageRequest> sendMessageAsStream(StreamObserver<GrpcSendBayernIdMessageResponse> responseObserver) {
+		return new UploadStreamObserver(responseObserver, proxyService, messageMapper);
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyService.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a760fd479ba85227a3a17f0473ad94abaf27109
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyService.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.akdb.BayernIdRemoteService;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessage;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdResponse;
+import lombok.RequiredArgsConstructor;
+
+@Service
+@RequiredArgsConstructor
+public class BayernIdProxyService {
+
+	private final BayernIdRemoteService bayernIdRemoteService;
+
+	public BayernIdResponse sendPostfachNachricht(BayernIdMessage message) {
+		return bayernIdRemoteService.sendPostfachNachricht(message);
+	}
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/DeleteOnCloseInputStream.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/DeleteOnCloseInputStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa543be86676ba3dc96c8ec6c50bfe1aff266f67
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/DeleteOnCloseInputStream.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Files;
+
+public class DeleteOnCloseInputStream extends FileInputStream {
+
+	private final File file;
+
+	public DeleteOnCloseInputStream(File file) throws FileNotFoundException {
+		super(file);
+		this.file = file;
+	}
+
+	@Override
+	public void close() throws IOException {
+		super.close();
+		Files.deleteIfExists(file.toPath());
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/UploadStreamObserver.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/UploadStreamObserver.java
new file mode 100644
index 0000000000000000000000000000000000000000..e223ae4e59c7483418cc295d8c018902f4fa0fd1
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/UploadStreamObserver.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import static java.util.Objects.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.atomic.AtomicReference;
+
+import com.google.protobuf.ByteString;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.Attachment;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessage.BayernIdMessageBuilder;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessageMapper;
+import io.grpc.stub.StreamObserver;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@RequiredArgsConstructor
+public class UploadStreamObserver implements StreamObserver<GrpcSendBayernIdMessageRequest> {
+
+	static final String ATTACHMENT_FILE_SUFFIX = ".ozg-cloud.tmp";
+
+	private final StreamObserver<GrpcSendBayernIdMessageResponse> responseObserver;
+	private final BayernIdProxyService proxyService;
+	private final BayernIdMessageMapper messageMapper;
+
+	private final AtomicReference<BayernIdMessageBuilder> messageBuilder = new AtomicReference<>();
+	private OutputStream attachmentWriter;
+
+	@Override
+	public synchronized void onNext(GrpcSendBayernIdMessageRequest sendRequest) {
+		if (sendRequest.hasMessageMetadata()) {
+			readMessageMetadata(sendRequest.getMessageMetadata());
+			return;
+		}
+		readAttachments(sendRequest.getAttachments());
+	}
+
+	void readMessageMetadata(GrpcBayernIdMessageMetadata sendRequest) {
+		messageBuilder.set(messageMapper.toBayernIdMessage(sendRequest));
+	}
+
+	void readAttachments(GrpcAttachments attachments) {
+		if (attachments.hasAttachmentMetadata()) {
+			addDataContainer(attachments.getAttachmentMetadata());
+			return;
+		}
+		writeAttachment(attachments.getContent());
+	}
+
+	void addDataContainer(GrpcAttachmentMetadata attachmentMetadata) {
+		messageBuilder.get().attachment(buildAttachment(attachmentMetadata));
+	}
+
+	Attachment buildAttachment(GrpcAttachmentMetadata attachmentMetadata) {
+		var attachmentFile = createTemporallyFile(attachmentMetadata.getFileName());
+		return Attachment.builder()
+				.name(attachmentMetadata.getFileName())
+				.type(attachmentMetadata.getFileType())
+				.content(attachmentFile)
+				.build();
+	}
+
+	InputStream createTemporallyFile(String fileName) {
+		try {
+			closeTemporallyWriter();
+			var tempFilePath = createFile(fileName);
+			attachmentWriter = newOutputStream(tempFilePath);
+			return newInputStream(tempFilePath);
+		} catch (IOException e) {
+			throw new TechnicalException("Can not create temporary file for attachment " + fileName, e);
+		}
+	}
+
+	Path createFile(String fileName) throws IOException {
+		var tmpFile = Files.createTempFile(fileName, ATTACHMENT_FILE_SUFFIX);
+		tmpFile.toFile().deleteOnExit();
+		return tmpFile;
+	}
+
+	OutputStream newOutputStream(Path filePath) throws IOException {
+		return Files.newOutputStream(filePath);
+	}
+
+	InputStream newInputStream(Path filePath) throws IOException {
+		return new DeleteOnCloseInputStream(filePath.toFile());
+	}
+
+	void closeTemporallyWriter() {
+		try {
+			if (nonNull(attachmentWriter)) {
+				attachmentWriter.close();
+			}
+		} catch (IOException e) {
+			throw new TechnicalException("Can not close attachment file", e);
+		}
+	}
+
+	void writeAttachment(ByteString content) {
+		try {
+			attachmentWriter.write(content.toByteArray());
+			attachmentWriter.flush();
+		} catch (IOException e) {
+			throw new TechnicalException("Can not save attachment content", e);
+		}
+	}
+
+	@Override
+	public void onError(Throwable t) {
+		closeTemporallyWriter();
+		throw new TechnicalException("Error while sending postfach message", t);
+	}
+
+	@Override
+	public void onCompleted() {
+		closeTemporallyWriter();
+		try {
+			var bayernIdResponse = proxyService.sendPostfachNachricht(messageBuilder.get().build());
+			responseObserver.onNext(messageMapper.fromBayernIdResponse(bayernIdResponse));
+			responseObserver.onCompleted();
+		} catch (Exception e) {
+			throw new TechnicalException("Error while sending postfach message", e);
+		}
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/akdb/BayernIdRemoteService.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/akdb/BayernIdRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..9446a6a57b9fa105e237b6542b2bfeb6cecab4b0
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/akdb/BayernIdRemoteService.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.akdb;
+
+import java.io.IOException;
+
+import jakarta.xml.bind.JAXBElement;
+
+import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
+import org.springframework.xml.transform.StringResult;
+import org.springframework.xml.transform.StringSource;
+
+import akdb.bsp.postkorb.komm.webservice.ObjectFactory;
+import akdb.bsp.postkorb.komm.webservice.SendBspNachrichtNative;
+import akdb.bsp.postkorb.komm.webservice.SendBspNachrichtNativeOutput;
+import de.akdb.egov.bsp.nachrichten.BspNachricht;
+import de.akdb.egov.bsp.nachrichten.BspQuittung;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessage;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessageMapper;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdResponse;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class BayernIdRemoteService extends WebServiceGatewaySupport {
+
+	private final BayernIdMessageMapper messageMapper;
+	private final ObjectFactory objectFactory;
+
+	public BayernIdResponse sendPostfachNachricht(BayernIdMessage message) {
+		var sendNachricht = createSendNachricht(message);
+		var sendBspNachrichtResponse = sendBspNachricht(sendNachricht);
+		var bspQuittung = createBspQuitung(sendBspNachrichtResponse);
+		return messageMapper.toBayernIdResponse(bspQuittung);
+	}
+
+	SendBspNachrichtNative createSendNachricht(BayernIdMessage message) {
+		var bspNachricht = messageMapper.toBspNachricht(message);
+		var sendBspNachricht = new SendBspNachrichtNative();
+		sendBspNachricht.setBspNachricht(buildBspNachrichtXml(bspNachricht));
+		return sendBspNachricht;
+	}
+
+	String buildBspNachrichtXml(BspNachricht message) {
+		try {
+			var result = new StringResult();
+			getMarshaller().marshal(message, result);
+			return result.toString();
+		} catch (IOException e) {
+			throw new TechnicalException("Error while marshalling BspNachricht", e);
+		}
+	}
+
+	SendBspNachrichtNativeOutput sendBspNachricht(SendBspNachrichtNative request) {
+		return send(objectFactory.createSendBspNachrichtNative(request)).getValue();
+	}
+
+	@SuppressWarnings("unchecked")
+	JAXBElement<SendBspNachrichtNativeOutput> send(JAXBElement<SendBspNachrichtNative> jaxbSendBspNachrichtNative) {
+		return (JAXBElement<SendBspNachrichtNativeOutput>) getWebServiceTemplate().marshalSendAndReceive(jaxbSendBspNachrichtNative);
+	}
+	BspQuittung createBspQuitung(SendBspNachrichtNativeOutput bspNachrichtResponse) {
+		try {
+			return (BspQuittung) getUnmarshaller().unmarshal(new StringSource(bspNachrichtResponse.getBspQuittung()));
+		} catch (IOException e) {
+			throw new TechnicalException("Error while unmarshalling BspQuittung", e);
+		}
+	}
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/errorhandling/ExceptionHandler.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/errorhandling/ExceptionHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..fba0b8d8e0b7e1d5068e9f7a2bdf2d91519c0030
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/errorhandling/ExceptionHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.errorhandling;
+
+import java.util.UUID;
+
+import de.ozgcloud.common.errorhandling.ExceptionUtil;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.common.grpc.GrpcUtil;
+import io.grpc.Metadata;
+import io.grpc.Status;
+import io.grpc.StatusException;
+import lombok.extern.log4j.Log4j2;
+import net.devh.boot.grpc.server.advice.GrpcAdvice;
+import net.devh.boot.grpc.server.advice.GrpcExceptionHandler;
+
+@GrpcAdvice
+@Log4j2
+public class ExceptionHandler {
+
+	static final String KEY_EXCEPTION_ID = "EXCEPTION_ID";
+
+	@GrpcExceptionHandler
+	public StatusException handleTechnicalException(TechnicalException e) {
+		LOG.error("Technical exception occurred", e);
+		return createStatusException(buildInternalStatus(e), buildMetadata(e.getExceptionId()));
+	}
+
+	@GrpcExceptionHandler
+	public StatusException handleRuntimeException(RuntimeException e) {
+		var exceptionId = createExceptionId();
+		LOG.error(ExceptionUtil.formatMessageWithExceptionId("gRPC internal exception.",exceptionId), e);
+		return createStatusException(buildInternalStatus(e), buildMetadata(exceptionId));
+	}
+
+	Status buildInternalStatus(RuntimeException e) {
+		return Status.INTERNAL.withDescription(e.getMessage()).withCause(e.getCause());
+	}
+
+	String createExceptionId() {
+		return UUID.randomUUID().toString();
+	}
+
+	Metadata buildMetadata(String exceptionId) {
+		var metadata = new Metadata();
+		metadata.put(GrpcUtil.keyOfString(KEY_EXCEPTION_ID), exceptionId);
+		return metadata;
+	}
+
+	StatusException createStatusException(Status status, Metadata metadata) {
+		return new StatusException(status, metadata);
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Absender.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Absender.java
new file mode 100644
index 0000000000000000000000000000000000000000..e5cbd91cffbcaab77b6f96e86d391476def7694f
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Absender.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class Absender {
+
+	private String postkorbId;
+	private String name;
+	private String anschrift;
+	private String email;
+	private String telefon;
+	private String hyperlink;
+	private String dienst;
+	private String mandant;
+	private String gemeindeschluessel;
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Attachment.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Attachment.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c144a4f25b95a12b32ba22f21bfa228ed1f6aef
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Attachment.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import java.io.InputStream;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class Attachment {
+
+	private String name;
+	private String type;
+	private InputStream content;
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessage.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..71328dde692f42a4eb197722c9a21b03d9c87b1b
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessage.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import java.util.List;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Singular;
+
+@Builder
+@Getter
+public class BayernIdMessage {
+
+	private String messageId;
+	private String createdAt;
+	private String vorgangId;
+	private Absender absender;
+	private Empfaenger empfaenger;
+	private String subject;
+	private String storkQaaLevel;
+	private String text;
+	@Singular
+	private List<Attachment> attachments;
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageMapper.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e7a7488191a84c17593abbcb887dfc7d3293469
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageMapper.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import java.io.IOException;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.NullValueCheckStrategy;
+import org.mapstruct.NullValuePropertyMappingStrategy;
+
+import de.akdb.egov.bsp.nachrichten.AbsenderType;
+import de.akdb.egov.bsp.nachrichten.BspNachricht;
+import de.akdb.egov.bsp.nachrichten.BspQuittung;
+import de.akdb.egov.bsp.nachrichten.DataContainerType;
+import de.akdb.egov.bsp.nachrichten.SchluesseltabelleType;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAbsender;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcBayernIdMessageMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessage.BayernIdMessageBuilder;
+
+@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
+public interface BayernIdMessageMapper {
+
+	String TABELLE_NUMMER_TEXT_ENCODING = "9004";
+	String TABELLE_NUMMER_MIME_TYPE = "9005";
+	String TABELLE_NUMMER_GEMEINDE_SCHLUESSEL = "36";
+	String TEXT_ENCODING_PLAIN_TEXT = "text/plain";
+
+	@Mapping(target = "attachments", ignore = true)
+	BayernIdMessageBuilder toBayernIdMessage(GrpcBayernIdMessageMetadata grpcMessage);
+
+	@Mapping(target = "gemeindeschluessel.tabelle", constant = TABELLE_NUMMER_GEMEINDE_SCHLUESSEL)
+	@Mapping(target = "gemeindeschluessel.schluessel", source = "gemeindeschluessel")
+	AbsenderType toAbsenderType(GrpcAbsender absender);
+
+	@Mapping(target = "unknownFields", ignore = true)
+	@Mapping(target = "statusBytes", ignore = true)
+	@Mapping(target = "messageBytes", ignore = true)
+	@Mapping(target = "mergeUnknownFields", ignore = true)
+	@Mapping(target = "mergeFrom", ignore = true)
+	@Mapping(target = "clearOneof", ignore = true)
+	@Mapping(target = "clearField", ignore = true)
+	GrpcSendBayernIdMessageResponse fromBayernIdResponse(BayernIdResponse message);
+
+	@Mapping(target = "nachrichtenKopf.identifikationNachricht.nachrichtenId", source = "messageId")
+	@Mapping(target = "nachrichtenKopf.identifikationNachricht.erstellungszeitpunkt", source = "createdAt")
+	@Mapping(target = "nachrichtenKopf.empfaenger.postkorbId", source = "empfaenger.postkorbId")
+	@Mapping(target = "nachrichtenKopf.empfaenger.name", source = "empfaenger.name")
+	@Mapping(target = "nachrichtenKopf.empfaenger.anschrift", source = "empfaenger.anschrift")
+	@Mapping(target = "nachrichtenKopf.absender", source = "absender")
+	@Mapping(target = "nachrichtenInhalt.betreff", source = "subject")
+	@Mapping(target = "nachrichtenInhalt.storkQaaLevel", source = "storkQaaLevel")
+	@Mapping(target = "nachrichtenInhalt.zuVorgang.vorgangsId", source = "vorgangId")
+	@Mapping(target = "nachrichtenInhalt.freiText.encoding.schluessel", constant = TEXT_ENCODING_PLAIN_TEXT)
+	@Mapping(target = "nachrichtenInhalt.freiText.encoding.tabelle", constant = TABELLE_NUMMER_TEXT_ENCODING)
+	@Mapping(target = "nachrichtenInhalt.freiText.text", source = "text")
+	@Mapping(target = "nachrichtenInhalt.dataContainer", source = "attachments")
+	BspNachricht toBspNachricht(BayernIdMessage message);
+
+	@Mapping(target = "gemeindeschluessel.tabelle", constant = TABELLE_NUMMER_GEMEINDE_SCHLUESSEL)
+	@Mapping(target = "gemeindeschluessel.schluessel", source = "gemeindeschluessel")
+	AbsenderType toAbsenderType(Absender absender);
+
+	default DataContainerType toDataContainerType(Attachment attachment) {
+		var dataContainer = new DataContainerType();
+		dataContainer.setFileType(toSchluesseltabelleType(attachment));
+		dataContainer.setFileName(attachment.getName());
+		try {
+			var content = attachment.getContent();
+			try {
+				dataContainer.setInhalt(content.readAllBytes());
+			} finally {
+				content.close();
+			}
+		} catch (IOException e) {
+			throw new TechnicalException("Error reading attachment content", e);
+		}
+		return dataContainer;
+	}
+
+	default SchluesseltabelleType toSchluesseltabelleType(Attachment attachment) {
+		var schluesseltabelle = new SchluesseltabelleType();
+		schluesseltabelle.setSchluessel(attachment.getType());
+		schluesseltabelle.setTabelle(TABELLE_NUMMER_MIME_TYPE);
+		return schluesseltabelle;
+	}
+
+	@Mapping(target = "status", source = "ergebnisStatus.schluessel")
+	@Mapping(target = "message", source = "ergaenzendeHinweise")
+	@Mapping(target = "success", source = "annahmeErfolgreich")
+	BayernIdResponse toBayernIdResponse(BspQuittung quittung);
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdResponse.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..f7b17f2da4ae66fbc4078d1e9be11b124164293b
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdResponse.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class BayernIdResponse {
+
+	private boolean success;
+	private String status;
+	private String message;
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Empfaenger.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Empfaenger.java
new file mode 100644
index 0000000000000000000000000000000000000000..6cfd6fb4ef00f9ab4e2c315203c4f41b093b34fc
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/Empfaenger.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class Empfaenger {
+
+	private String postkorbId;
+	private String name;
+	private String anschrift;
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000000000000000000000000000000000..31f436d781244c879e37eb6d97662f3c5102e6b7
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,14 @@
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonTraceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcAdviceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcHealthServiceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataConsulConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataEurekaConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataNacosConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataZookeeperConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcReflectionServiceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerMetricAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerSecurityAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerTraceAutoConfiguration
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application-dev.yml b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application-dev.yml
new file mode 100644
index 0000000000000000000000000000000000000000..df2f1cca69b93f18902100a3a93997030beb2000
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application-dev.yml
@@ -0,0 +1,5 @@
+ozgcloud:
+  bayernid:
+    proxy:
+      server: "https://infra-pre-id.bayernportal.de/bspx-postkorb-okkomm-ws/bspservices/postkorbkomm"
+      postkorbId: "28721c6f-b78f-4d5c-a048-19fd2fc429d2"
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application-local.yml b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application-local.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f048bc1e34b576c9d95d558300db721823dc58f5
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application-local.yml
@@ -0,0 +1,11 @@
+logging:
+  config: classpath:log4j2-local.xml
+
+server:
+  port: 9097
+management:
+  server.port: 9098
+
+grpc:
+  server:
+    port: 9099
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application.yml b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..69790c2b42e751213e739cf8ca6a87df6fd74068
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/application.yml
@@ -0,0 +1,29 @@
+logging:
+  level:
+    ROOT: WARN
+    '[de.ozgcloud]': INFO
+  config: classpath:log4j2-local.xml
+
+
+management:
+  server:
+    port: 8081
+  health:
+    livenessState:
+      enabled: true
+    readinessState:
+      enabled: true
+  endpoint:
+    health:
+      group:
+        exploratory:
+          include: livenessState,readinessState,ping
+          show-details: always
+      probes:
+        enabled: true
+    prometheus:
+      enabled: true
+  endpoints:
+    web:
+      exposure:
+        include: "*"
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/bayernid/PostfachnachrichtenServiceBy.wsdl b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/bayernid/PostfachnachrichtenServiceBy.wsdl
new file mode 100644
index 0000000000000000000000000000000000000000..a2df76060c0568ed74ed70e6cc71fdc6a9005c98
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/bayernid/PostfachnachrichtenServiceBy.wsdl
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions name="PostkorbKommService"
+	xmlns="http://schemas.xmlsoap.org/wsdl/"
+	xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+	xmlns:bsp="http://akdb.de/portal/gehaltsabrechnungen-bspnachricht"
+	xmlns:tns="urn:akdb:bsp:postkorb:komm:webservice"
+	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+	targetNamespace="urn:akdb:bsp:postkorb:komm:webservice">
+	<types>
+		<xs:schema
+			targetNamespace='urn:akdb:bsp:postkorb:komm:webservice' version='1.1'
+			xmlns:tns='urn:akdb:bsp:postkorb:komm:webservice'
+			xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+			<xs:element name='sendBspNachricht'
+				type='tns:sendBspNachricht' />
+			<xs:complexType name='sendBspNachricht'>
+				<xs:sequence>
+					<xs:element minOccurs='1' name='okKommBspNachrichtInput'
+						type='xs:base64Binary' />
+				</xs:sequence>
+			</xs:complexType>
+			<xs:element name='sendBspNachrichtOutput'
+				type='tns:sendBspNachrichtOutput' />
+			<xs:complexType name='sendBspNachrichtOutput'>
+				<xs:sequence>
+					<xs:element minOccurs='1'
+						name='okKommBspNachrichtOutput' type='xs:base64Binary' />
+				</xs:sequence>
+			</xs:complexType>
+			<xs:element name='sendBspNachrichtNative'
+				type='tns:sendBspNachrichtNative' />
+			<xs:complexType name='sendBspNachrichtNative'>
+				<xs:sequence>
+					<xs:element minOccurs='1' name='bspNachricht'
+						type='xs:string' />
+				</xs:sequence>
+			</xs:complexType>
+			<xs:element name='sendBspNachrichtNativeOutput'
+				type='tns:sendBspNachrichtNativeOutput' />
+			<xs:complexType name='sendBspNachrichtNativeOutput'>
+				<xs:sequence>
+					<xs:element minOccurs='1' name='bspQuittung'
+						type='xs:string' />
+				</xs:sequence>
+			</xs:complexType>
+		</xs:schema>
+	</types>
+	<message name='PostkorbKommService_sendBspNachrichtInput'>
+		<part element='tns:sendBspNachricht'
+			name='okKommBspNachrichtInput'></part>
+	</message>
+	<message name='PostkorbKommService_sendBspNachrichtOutput'>
+		<part element='tns:sendBspNachrichtOutput'
+			name='sendBspNachrichtOutput'></part>
+	</message>
+	<message name='PostkorbKommService_sendBspNachrichtNativeInput'>
+		<part element='tns:sendBspNachrichtNative'
+			name='sendBspNachrichtNative'></part>
+	</message>
+	<message
+		name='PostkorbKommService_sendBspNachrichtNativeOutput'>
+		<part element='tns:sendBspNachrichtNativeOutput'
+			name='bspQuittung'></part>
+	</message>
+	<portType name='PostkorbKommPortType'>
+		<operation name='sendBspNachricht'>
+			<input message='tns:PostkorbKommService_sendBspNachrichtInput'></input>
+			<output
+				message='tns:PostkorbKommService_sendBspNachrichtOutput'></output>
+		</operation>
+		<operation name='sendBspNachrichtNative'>
+			<input
+				message='tns:PostkorbKommService_sendBspNachrichtNativeInput'></input>
+			<output
+				message='tns:PostkorbKommService_sendBspNachrichtNativeOutput'></output>
+		</operation>
+	</portType>
+	<binding name="PostkorbKommBinding"
+		type="tns:PostkorbKommPortType">
+		<soap:binding style="document"
+			transport="http://schemas.xmlsoap.org/soap/http" />
+		<operation name='sendBspNachricht'>
+			<soap:operation soapAction='' />
+			<input>
+				<soap:body use='literal' />
+			</input>
+			<output>
+				<soap:body use="literal" />
+			</output>
+		</operation>
+		<operation name='sendBspNachrichtNative'>
+			<soap:operation soapAction='' />
+			<input>
+				<soap:body use='literal' />
+			</input>
+			<output>
+				<soap:body use="literal" />
+			</output>
+		</operation>
+	</binding>
+	<service name="PostkorbKommService">
+		<port name="PostkorbKommPort" binding="tns:PostkorbKommBinding">
+			<!-- <soap:address location="${web-services-base- url}/bspservices/postkorbkomm" 
+				/> -->
+			<soap:address location="http://localhost:8080/bspx-postkorb-okkomm-ws/bspservices/postkorbkomm" />
+		</port>
+	</service>
+</definitions>
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/bayernid/bspnachrichten-2.13.xsd b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/bayernid/bspnachrichten-2.13.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..23b0e247d2bd9d2ab3f2206e4354d0c497844f28
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/bayernid/bspnachrichten-2.13.xsd
@@ -0,0 +1,343 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Service- und Portalplattform
+    AKDB München, Geschäftsfeld eGovernment
+
+    Copyright (c) AKDB
+
+-->
+<xsd:schema targetNamespace="http://www.akdb.de/egov/bsp/nachrichten"
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  xmlns:bsp="http://www.akdb.de/egov/bsp/nachrichten"
+  elementFormDefault="qualified">
+
+  <xsd:element name="BspNachricht">
+    <xsd:annotation>
+      <xsd:appinfo>
+        <title>Nachricht für die Kommunikation zwischen Bürgerservice-Portal
+          und externen Fachverfahren</title>
+      </xsd:appinfo>
+      <xsd:documentation>Einheitliches Nachrichtenschema für die
+        Kommunikation zwischen Bürgerservice-Portal und externem Verfahren.
+        Nachrichten vom Bürgerservice-Portal an den Postkorb eines
+        Verfahrens
+        oder Nachrichten von den Verfahren an das Bürgerservice-Portal müssen
+        gemäß diesem Schema aufgebaut sein.
+      </xsd:documentation>
+    </xsd:annotation>
+    <xsd:complexType>
+      <xsd:sequence>
+        <xsd:element name="NachrichtenKopf" type="bsp:NachrichtenKopfType"/>
+        <xsd:element name="NachrichtenInhalt" type="bsp:NachrichtenInhaltType"/>
+      </xsd:sequence>
+      <xsd:attribute name="version" use="required">
+        <xsd:annotation>
+          <xsd:documentation>Dieses Attribut kennzeichnet die
+            Nachrichten-Version, z. B. "1.0", "1.1".</xsd:documentation>
+        </xsd:annotation>
+        <xsd:simpleType>
+           <xsd:restriction base="xsd:string">
+             <xsd:enumeration value="1.1"/>
+             <xsd:enumeration value="1.2"/>
+             <xsd:enumeration value="1.3"/>
+             <xsd:enumeration value="1.4"/>
+             <xsd:enumeration value="1.5"/>
+           </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
+      <xsd:attribute name="fassung" use="required" >
+        <xsd:annotation>
+          <xsd:documentation>Dieses Attribut kennzeichnet das Datum, an dem
+            die diesen Schemata im Status final produziert wurde. Format:
+            YYYY-MM-DD.</xsd:documentation>
+        </xsd:annotation>
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="2017-03-15"/>
+            <xsd:enumeration value="2018-04-01"/>
+            <xsd:enumeration value="2018-11-01"/>
+            <xsd:enumeration value="2019-06-28"/>
+            <xsd:enumeration value="2020-03-15"/>
+          </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
+      <xsd:attribute name="produkt" type="xsd:string" use="optional">
+        <xsd:annotation>
+          <xsd:documentation>In diesem Attribut ist der Name des Produktes
+            (der Software) einzutragen, mit dem diese Nachricht erstellt
+            worden ist. z.B. BSP, PWS</xsd:documentation>
+        </xsd:annotation>
+      </xsd:attribute>
+      <xsd:attribute name="produkthersteller" type="xsd:string" use="optional"/>
+      <xsd:attribute name="produktversion" type="xsd:string" use="optional"/>
+    </xsd:complexType>
+  </xsd:element>
+
+  <xsd:element name="BspQuittung">
+    <xsd:annotation>
+      <xsd:appinfo>
+        <title>Quittung über den Empfang einer BSO-Nachricht</title>
+      </xsd:appinfo>
+      <xsd:documentation>Zu einer empfangenen BSP-Nachricht wird eine
+                Quittung geliefert, die bestätigt, dass die Nachricht übernommen wurde
+                oder aufgrund eines technischen oder fachlichen Fehlers abgewiesen wurde.
+      </xsd:documentation>
+    </xsd:annotation>
+    <xsd:complexType>
+      <xsd:sequence>
+        <xsd:element name="AnnahmeErfolgreich" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
+          <xsd:element name="ErgebnisStatus" type="bsp:SchluesseltabelleType" minOccurs="1" maxOccurs="1">
+            <xsd:annotation>
+              <xsd:documentation>Schluesseltabelle 9006 (0 (erfolgreich angenommen), 99 (sonstiger technischer Fehler), ...)</xsd:documentation>
+            </xsd:annotation>
+          </xsd:element>
+        <xsd:element name="ErgaenzendeHinweise" type="xsd:string" minOccurs="0" maxOccurs="1"/>
+      </xsd:sequence>
+      <xsd:attribute name="version" use="required">
+        <xsd:annotation>
+          <xsd:documentation>Dieses Attribut kennzeichnet die
+            Nachrichten-Version, z. B. "1.0", "1.1".</xsd:documentation>
+        </xsd:annotation>
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="1.1"/>
+			<xsd:enumeration value="1.2"/>
+            <xsd:enumeration value="1.3"/>
+            <xsd:enumeration value="1.4"/>
+            <xsd:enumeration value="1.5"/>
+           </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
+      <xsd:attribute name="fassung" use="required">
+        <xsd:annotation>
+          <xsd:documentation>Dieses Attribut kennzeichnet das Datum, an dem
+            die diesen Schemata im Status final produziert wurde. Format:
+            YYYY-MM-DD.</xsd:documentation>
+        </xsd:annotation>
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="2017-03-15"/>
+            <xsd:enumeration value="2018-04-01"/>
+            <xsd:enumeration value="2018-11-01"/>
+            <xsd:enumeration value="2019-06-28"/>
+            <xsd:enumeration value="2020-03-15"/>			
+          </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
+      <xsd:attribute name="produkt" type="xsd:string" use="optional">
+        <xsd:annotation>
+          <xsd:documentation>In diesem Attribut ist der Name des Produktes
+            (der Software) einzutragen, mit dem diese Nachricht erstellt
+            worden ist. z.B. BSP, PWS</xsd:documentation>
+        </xsd:annotation>
+      </xsd:attribute>
+      <xsd:attribute name="produkthersteller" type="xsd:string" use="optional"/>
+      <xsd:attribute name="produktversion" type="xsd:string" use="optional"/>
+    </xsd:complexType>
+  </xsd:element>
+
+  <xsd:complexType name="NachrichtenKopfType">
+    <xsd:sequence>
+      <xsd:element name="Identifikation.Nachricht" type="bsp:Identifikation.NachrichtType" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="Anwenderkennung" type="xsd:string" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation> Die Anwenderkennung stellt Informationen über die absendende Person
+          zur Verfügung und dient der Protokollierung.
+          Anhand dieser Kennung kann die absendende Person identifiziert werden.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Absender" type="bsp:AbsenderType" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="Empfaenger" type="bsp:EmpfaengerType"  maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="AntwortAuf" type="xsd:string" maxOccurs="1" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation>Eine Nachricht kann mit einer exisiterenden
+            Nachricht in Beziehung gebracht werden als Antwortnachricht oder
+            weitergeleitete Nachricht. Der Bezug erfolgt hierbei über die
+            NachrichtenId.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="WeiterleitungZu" type="xsd:string" minOccurs="0"/>
+      <xsd:element name="lesebestaetigungAntwortAdresse" type="xsd:string" minOccurs="0"/>
+    </xsd:sequence>
+  </xsd:complexType>
+  <xsd:complexType name="Identifikation.NachrichtType">
+    <xsd:sequence>
+      <xsd:element name="Ereignis" type="bsp:SchluesseltabelleType">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9001, Schluessel: BspNachricht
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Erstellungszeitpunkt" type="xsd:dateTime" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="NachrichtenId" type="xsd:string" maxOccurs="1" minOccurs="1">
+        <xsd:annotation>
+          <xsd:documentation>eine beliebige, eindeutige ID, die durch den
+            erstellenden Client generiert wird. Zusammen mit
+            Erstellungszeitpunkt und Absender kann eine Nachricht bsp-global
+            eindeutig identifiziert werden.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="AbsenderType">
+    <xsd:sequence>
+      <xsd:element name="PostkorbId" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Verfahren" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Dienst" type="bsp:NonEmptyString" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Mandant" type="bsp:NonEmptyString" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Gemeindeschluessel" type="bsp:SchluesseltabelleType" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation>Der amtliche Gemeindeschlüssel (AGS).
+            Als Tabellennummer ist hier die 36 (OSCI-XMeld-Schlüsseltabelle "Amtlicher Gemeindeschluessel") zu verwenden.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Name" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Anschrift" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Email" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Telefon" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Hyperlink" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+   </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="EmpfaengerType">
+    <xsd:sequence>
+      <xsd:element name="PostkorbId" type="xsd:string" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="Verfahren" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Dienst" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Mandant" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Gemeindeschluessel" type="bsp:SchluesseltabelleType" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation>Der amtliche Gemeindeschlüssel (AGS).
+            Als Tabellennummer ist hier die 36 (OSCI-XMeld-Schlüsseltabelle "Amtlicher Gemeindeschluessel") zu verwenden.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Name" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Anschrift" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="NachrichtenInhaltType">
+    <xsd:sequence>
+      <xsd:element name="Betreff" type="bsp:NonEmptyString" maxOccurs="1"   minOccurs="1"/>
+      <xsd:element name="Kategorie" type="bsp:SchluesseltabelleType" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9002 (KAT_STATUS, KAT_INFOBSP, ...)
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:choice minOccurs="0">
+        <xsd:element name="StorkQaaLevel" type="bsp:StorkQaaLevel"/>
+        <xsd:element name="NpaGescheutzt" type="xsd:boolean" >
+          <!-- deprecated, wird durch StorkQaaLevel="STORK-QAA-Level-1" ersetzt -->
+          <xsd:annotation>
+            <xsd:documentation>
+              Diese Nachricht kann im BüsP-Postkorb nur nach
+              vorheriger Anmeldung mit dem nPA gelesen werden.
+            </xsd:documentation>
+          </xsd:annotation>
+        </xsd:element>
+      </xsd:choice>
+      <xsd:element name="ZuVorgang" type="bsp:ZuVorgangType" minOccurs="0"/>
+      <xsd:element name="FreiText" type="bsp:FreiTextType"/>
+      <xsd:element name="DataContainer" type="bsp:DataContainerType" minOccurs="0" maxOccurs="unbounded"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="ZuVorgangType">
+    <xsd:annotation>
+      <xsd:documentation>VorgangsName oder VorgangsId müssen angegeben
+        werden. Es können auch beide angegeben werden.</xsd:documentation>
+    </xsd:annotation>
+    <xsd:sequence minOccurs="0">
+      <xsd:element name="VorgangsName" type="xsd:string"/>
+      <xsd:element name="VorgangsId" type="xsd:string"/>
+      <xsd:element name="VorgangStatus" type="bsp:SchluesseltabelleType">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9003 (ST_ERHALTEN, ST_GELESEN,...)
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="FreiTextType">
+    <xsd:sequence>
+      <xsd:element name="Encoding" type="bsp:SchluesseltabelleType" maxOccurs="1" minOccurs="1">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9004 (text/plain, text/html, ...)
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Text" type="bsp:NonEmptyString" maxOccurs="1" minOccurs="1">
+        <xsd:annotation>
+          <xsd:documentation>
+            Wenn als Encoding text/plain festgelegt ist, so wird die Zeichensequenz "\n" als ein Zeilenvorschub interpretiert.
+            Das Backslash-Zeichen (\) wird mit einem weiteren Backslash-Zeichen entwertet.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="DataContainerType">
+    <xsd:sequence minOccurs="0">
+      <xsd:element name="Inhalt" type="xsd:base64Binary" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="FileName" maxOccurs="1" minOccurs="0">
+          <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+              <xsd:maxLength value="255"/>
+            </xsd:restriction>
+          </xsd:simpleType>
+      </xsd:element>
+      <xsd:element name="FileType" type="bsp:SchluesseltabelleType" maxOccurs="1" minOccurs="1">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9005 (application/pdf, text/html, ...)
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="SchluesseltabelleType">
+    <xsd:annotation>
+      <xsd:documentation>Dieser Datentyp wird für Schlüsselwerte benötigt.
+        Mit dem Datentyp SchluesseltabelleType übermittelt man den Schlüssel
+        und die Nummer der Tabelle, in der das Schlüssel-Wert Paar definiert
+        worden ist.
+      </xsd:documentation>
+    </xsd:annotation>
+    <xsd:sequence>
+      <xsd:element name="Tabelle" type="xsd:string"/>
+      <xsd:element name="Schluessel" type="xsd:string"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:simpleType name="StorkQaaLevel">
+    <xsd:restriction base="xsd:string">
+      <!-- since version 1.2 - deprecated -->
+      <xsd:enumeration value="LEVEL_1"/>
+      <xsd:enumeration value="LEVEL_2"/>
+      <xsd:enumeration value="LEVEL_3"/>
+      <xsd:enumeration value="LEVEL_4"/>
+      <!--  since version 1.3 -->
+      <xsd:enumeration value="STORK-QAA-Level-1"/>
+      <xsd:enumeration value="STORK-QAA-Level-2"/>
+      <xsd:enumeration value="STORK-QAA-Level-3"/>
+      <xsd:enumeration value="STORK-QAA-Level-4"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+  <xsd:simpleType name="NonEmptyString">
+    <xsd:restriction base="xsd:string">
+      <xsd:minLength value="1"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+</xsd:schema>
+
+
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/log4j2-local.xml b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/log4j2-local.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5d7001e1f9186d197a2d301d3910c9d73ed05d15
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/main/resources/log4j2-local.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+	<Appenders>
+		<Console name="CONSOLE" target="SYSTEM_OUT">
+			<PatternLayout pattern="[%-5level] %c{1.} %msg%n"/>
+		</Console>
+	</Appenders>
+
+	<Loggers>
+		<Root level="WARN">
+			<appender-ref ref="CONSOLE" />
+		</Root>
+	</Loggers>
+</configuration>
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyGrpcServiceITCase.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyGrpcServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f9468c817590b7f34f0c83318084569ae09eaf6
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyGrpcServiceITCase.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.io.InputStream;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
+import com.github.tomakehurst.wiremock.junit5.WireMockTest;
+
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.akdb.BayernIdRemoteService;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.mock.GrpcBayernIdProxyTestClient;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.mock.MockBayernIdInitializer;
+import io.grpc.StatusRuntimeException;
+import lombok.SneakyThrows;
+import net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration;
+import net.devh.boot.grpc.client.autoconfigure.GrpcClientHealthAutoConfiguration;
+import net.devh.boot.grpc.client.autoconfigure.GrpcClientMetricAutoConfiguration;
+import net.devh.boot.grpc.client.autoconfigure.GrpcClientSecurityAutoConfiguration;
+import net.devh.boot.grpc.client.autoconfigure.GrpcClientTraceAutoConfiguration;
+import net.devh.boot.grpc.client.autoconfigure.GrpcDiscoveryClientAutoConfiguration;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@SpringBootTest(classes = BayernIdProxyApplication.class, properties = {
+		"grpc.server.inProcessName=test",
+		"grpc.client.inProcess.address=in-process:test",
+		"ozgcloud.bayernid.server: http://bayern-id",
+		"ozgcloud.bayernid.useSsl: false"
+})
+@SpringJUnitConfig(classes = BayernIdProxyGrpcServiceITCase.TestConfig.class)
+@DirtiesContext
+@WireMockTest
+@ITCase
+class BayernIdProxyGrpcServiceITCase {
+
+	@Autowired
+	private BayernIdProxyGrpcService service;
+	@Autowired
+	private BayernIdRemoteService bayernIdRemoteService;
+
+	@GrpcClient("inProcess")
+	private BayernIdProxyServiceGrpc.BayernIdProxyServiceStub serviceStub;
+
+	private MockBayernIdInitializer bayernIdInitializer;
+
+	@Value("classpath:test.pdf")
+	private Resource pdfResource;
+	@Value("classpath:test.txt")
+	private Resource txtResource;
+
+	private String pdfName = "test.pdf";
+	private String txtName = "test.txt";
+
+	private GrpcBayernIdProxyTestClient grpcTestClient;
+
+	@BeforeEach
+	void setup(WireMockRuntimeInfo wmRuntimeInfo) {
+		bayernIdRemoteService.setDefaultUri("http://localhost:" + wmRuntimeInfo.getHttpPort());
+		bayernIdInitializer = new MockBayernIdInitializer(wmRuntimeInfo);
+		grpcTestClient = new GrpcBayernIdProxyTestClient(serviceStub);
+	}
+
+	@Test
+	@SneakyThrows
+	void shouldSendMessage() {
+		bayernIdInitializer.createResponseOk();
+
+		var bayernIdResponse = grpcTestClient.sendMessage(GrpcBayernIdMessageMetadataTestFactory.create(), createAttachmentIterator());
+
+		assertThat(bayernIdResponse.isSuccess()).isTrue();
+		assertThat(bayernIdResponse.getStatus()).isEqualTo("0");
+	}
+
+	@SneakyThrows
+	@Test
+	void shouldReceiveErrorResponse() {
+		bayernIdInitializer.createResponseError();
+
+		var bayernIdResponse = grpcTestClient.sendMessage(GrpcBayernIdMessageMetadataTestFactory.create(), createAttachmentIterator());
+
+		assertThat(bayernIdResponse.isSuccess()).isFalse();
+		assertThat(bayernIdResponse.getStatus()).isEqualTo("31");
+		assertThat(bayernIdResponse.getMessage()).isEqualTo("Unzulässiger Nachrichteninhalt");
+	}
+
+	@Test
+	void shouldPassException() {
+		bayernIdInitializer.createResponseWithException();
+
+		try {
+			grpcTestClient.sendMessage(GrpcBayernIdMessageMetadataTestFactory.create(), createAttachmentIterator());
+		} catch (ExecutionException e) {
+			assertException(e.getMessage(), e.getCause());
+		}
+	}
+
+	@Test
+	void shouldPass500Response() {
+		bayernIdInitializer.create500Response();
+
+		try {
+			grpcTestClient.sendMessage(GrpcBayernIdMessageMetadataTestFactory.create(), createAttachmentIterator());
+		} catch (ExecutionException e) {
+			assertException(e.getMessage(), e.getCause());
+		}
+	}
+
+	private void assertException(String exceptionMessage, Throwable cause) {
+		assertThat(cause).isInstanceOf(StatusRuntimeException.class);
+		assertThat(exceptionMessage).contains("(ExceptionId:");
+	}
+
+
+	@SneakyThrows
+	Set<Pair<GrpcAttachmentMetadata, InputStream>> createAttachmentIterator() {
+		return Set.of(
+				Pair.of(GrpcAttachmentMetadata.newBuilder().setFileName(txtName).setFileType("text/plain").build(), txtResource.getInputStream()),
+				Pair.of(GrpcAttachmentMetadata.newBuilder().setFileName(pdfName).setFileType("application/pdf").build(), pdfResource.getInputStream())
+		);
+	}
+
+	@Configuration
+	@ImportAutoConfiguration({
+			GrpcClientAutoConfiguration.class,
+			GrpcClientHealthAutoConfiguration.class,
+			GrpcClientMetricAutoConfiguration.class,
+			GrpcClientSecurityAutoConfiguration.class,
+			GrpcClientTraceAutoConfiguration.class,
+			GrpcDiscoveryClientAutoConfiguration.class
+	})
+	static class TestConfig {
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyServiceTest.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2bda292babf25b186a903b7d261ba22f00c241c8
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdProxyServiceTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.akdb.BayernIdRemoteService;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessage;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdResponse;
+
+class BayernIdProxyServiceTest {
+
+	@InjectMocks
+	private BayernIdProxyService service;
+
+	@Mock
+	private BayernIdRemoteService remoteService;
+	@Mock
+	private BayernIdMessage message;
+	@Mock
+	private BayernIdResponse bayernIdResponse;
+
+	@Test
+	void shouldCallRemoteService() {
+		sendMessage();
+
+		verify(remoteService).sendPostfachNachricht(message);
+	}
+
+	@Test
+	void shouldReturnBayernIdResponse() {
+		when(remoteService.sendPostfachNachricht(any())).thenReturn(bayernIdResponse);
+
+		var result = sendMessage();
+
+		assertThat(result).isEqualTo(bayernIdResponse);
+	}
+
+	private BayernIdResponse sendMessage() {
+		return service.sendPostfachNachricht(message);
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdResponseTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..09b4146c945d211c8001de8b6570ccbae19c07f0
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/BayernIdResponseTestFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdResponse;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdResponse.BayernIdResponseBuilder;
+
+public class BayernIdResponseTestFactory {
+
+	public static final String STATUS = "OK";
+	public static final String MESSAGE = "Message sent successfully";
+
+	public static BayernIdResponse create() {
+		return createBuilder().build();
+	}
+
+	public static BayernIdResponseBuilder createBuilder() {
+		return BayernIdResponse.builder()
+				.success(true)
+				.status(STATUS)
+				.message(MESSAGE);
+	}
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchConfiguration.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcAbsenderTestFactory.java
similarity index 50%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchConfiguration.java
rename to nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcAbsenderTestFactory.java
index 3d9400fffb3cd200d4e2a2a3b80eac2d5498355a..a955fd2dea9219c92f62c327c82c4278f734ddb7 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchConfiguration.java
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcAbsenderTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,34 +21,32 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
 
-import javax.validation.Valid;
+public class GrpcAbsenderTestFactory {
 
-import org.apache.http.Header;
-import org.apache.http.message.BasicHeader;
-import org.elasticsearch.client.RestClientBuilder;
-import org.elasticsearch.client.RestHighLevelClient;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
+	public static final String NAME = "Musterstadt Stadtverwaltung";
+	public static final String ANSCHRIFT = "Musterstraße 1";
+	public static final String EMAIL = "example@mail.loc";
+	public static final String TELEFON = "0456123456789";
+	public static final String HYPERLINK = "http://some.link";
+	public static final String MANDANT = "Musterstadt";
+	public static final String DIENST = "Stadtverwaltung";
+	public static final String GEMEINDE_SCHLUESSEL = "123456789";
 
-@Configuration
-class SearchConfiguration {
-
-	@Autowired
-	@Valid
-	private SearchProperties properties;
-
-	private static final Header[] COMPATIBILITY_HEADERS = new Header[] {
-			new BasicHeader("Accept", "application/vnd.elasticsearch+json;compatible-with=7"),
-			new BasicHeader("Content-Type", "application/vnd.elasticsearch+json;compatible-with=7")
-	};
-
-	@Bean
-	RestHighLevelClient restHighLevelClient(RestClientBuilder client) {
-		client.setDefaultHeaders(COMPATIBILITY_HEADERS);
-		return new RestHighLevelClient(client);
+	public static GrpcAbsender create() {
+		return createBuilder().build();
 	}
 
+	public static GrpcAbsender.Builder createBuilder() {
+		return GrpcAbsender.newBuilder()
+				.setName(NAME)
+				.setAnschrift(ANSCHRIFT)
+				.setEmail(EMAIL)
+				.setTelefon(TELEFON)
+				.setHyperlink(HYPERLINK)
+				.setMandant(MANDANT)
+				.setDienst(DIENST)
+				.setGemeindeschluessel(GEMEINDE_SCHLUESSEL);
+	}
 }
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcAttachmentMetadataTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcAttachmentMetadataTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..6972e7a9c35f9c887e32565a392e1d483282d1ba
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcAttachmentMetadataTestFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+public class GrpcAttachmentMetadataTestFactory {
+
+	public static final String FILE_TYPE = "plain/text";
+	public static final String FILE_NAME = "test.txt";
+
+	public static GrpcAttachmentMetadata create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcAttachmentMetadata.Builder createBuilder() {
+		return GrpcAttachmentMetadata.newBuilder()
+				.setFileType(FILE_TYPE)
+				.setFileName(FILE_NAME);
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcBayernIdMessageMetadataTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcBayernIdMessageMetadataTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..854a5c1a22be51055d84ccb07f068822d358e405
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcBayernIdMessageMetadataTestFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import java.time.ZonedDateTime;
+import java.util.GregorianCalendar;
+import java.util.UUID;
+
+import javax.xml.datatype.DatatypeFactory;
+
+import lombok.SneakyThrows;
+
+public class GrpcBayernIdMessageMetadataTestFactory {
+
+	public static final String MESSAGE_ID = "messageId";
+	public static final ZonedDateTime CREATED_AT = ZonedDateTime.now();
+	public static final String CREATED_AT_STRING = convertZoneDDateTime(CREATED_AT);
+	public static final String STORK_QAA_LEVEL = "LEVEL_1";
+	public static final String SUBJECT = "subject";
+	public static final String VORGANG_ID = UUID.randomUUID().toString();
+	public static final String MESSAGE_TEXT = "some completely random text";
+
+	public static GrpcBayernIdMessageMetadata create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcBayernIdMessageMetadata.Builder createBuilder() {
+		return GrpcBayernIdMessageMetadata.newBuilder()
+				.setMessageId(MESSAGE_ID)
+				.setCreatedAt(convertZoneDDateTime(CREATED_AT))
+				.setAbsender(GrpcAbsenderTestFactory.create())
+				.setEmpfaenger(GrpcEmpfaengerTestFactory.create())
+				.setSubject(SUBJECT)
+				.setStorkQaaLevel(STORK_QAA_LEVEL)
+				.setVorgangId(VORGANG_ID)
+				.setText(MESSAGE_TEXT);
+	}
+
+	@SneakyThrows
+	public static String convertZoneDDateTime(ZonedDateTime dateTime) {
+		return DatatypeFactory.newInstance().newXMLGregorianCalendar(GregorianCalendar.from(dateTime)).toString();
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcEmpfaengerTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcEmpfaengerTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..5a0df823236427815e28e4851d6f428dc25cd8bf
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/GrpcEmpfaengerTestFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+public class GrpcEmpfaengerTestFactory {
+
+	public static final String POSTFACH_ID = "postfach-id-1";
+	public static final String NAME = "Max Empfaenger";
+	public static final String ANSCHRIFT = "anschrift";
+
+	public static GrpcEmpfaenger create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcEmpfaenger.Builder createBuilder() {
+		return GrpcEmpfaenger.newBuilder()
+				.setPostkorbId(POSTFACH_ID)
+				.setName(NAME)
+				.setAnschrift(ANSCHRIFT);
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/UploadStreamObserverTest.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/UploadStreamObserverTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d6efd88993fe8d530db3edaeefa7f26ca8c28f3f
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/UploadStreamObserverTest.java
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Path;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import com.google.protobuf.ByteString;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.Attachment;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessage.BayernIdMessageBuilder;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessageMapper;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessageTestFactory;
+import io.grpc.stub.StreamObserver;
+import lombok.SneakyThrows;
+
+class UploadStreamObserverTest {
+
+	@Spy
+	@InjectMocks
+	private UploadStreamObserver uploadStreamObserver;
+
+	@Mock
+	private StreamObserver<GrpcSendBayernIdMessageResponse> responseObserver;
+	@Mock
+	private BayernIdProxyService proxyService;
+	@Mock
+	private BayernIdMessageMapper messageMapper;
+	@Mock
+	private BayernIdMessageBuilder bayernIdMessageBuilder;
+	@Mock
+	private AtomicReference<BayernIdMessageBuilder> messageBuilderAtomicReference;
+
+	@Nested
+	class TestOnNext {
+
+		@Test
+		void shouldCallReadMetadata() {
+			var messageMetadata = GrpcBayernIdMessageMetadataTestFactory.create();
+			var sendRequest = GrpcSendBayernIdMessageRequest.newBuilder().setMessageMetadata(messageMetadata).build();
+
+			uploadStreamObserver.onNext(sendRequest);
+
+			verify(uploadStreamObserver).readMessageMetadata(messageMetadata);
+			verify(uploadStreamObserver, never()).readAttachments(any());
+		}
+
+		@Test
+		void shouldCallReadAttachment() {
+			var attachments = GrpcAttachments.newBuilder().setAttachmentMetadata(GrpcAttachmentMetadataTestFactory.create()).build();
+			var sendRequest = GrpcSendBayernIdMessageRequest.newBuilder().setAttachments(attachments).build();
+			doNothing().when(uploadStreamObserver).readAttachments(any());
+
+			uploadStreamObserver.onNext(sendRequest);
+
+			verify(uploadStreamObserver).readAttachments(attachments);
+			verify(uploadStreamObserver, never()).readMessageMetadata(any());
+		}
+	}
+
+	@Nested
+	class TestReadMessageMetadata {
+
+		private GrpcBayernIdMessageMetadata messageMetadata = GrpcBayernIdMessageMetadataTestFactory.create();
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(uploadStreamObserver, "messageBuilder", messageBuilderAtomicReference);
+		}
+
+		@Test
+		void shouldCallMessageMapper() {
+			uploadStreamObserver.readMessageMetadata(messageMetadata);
+
+			verify(messageMapper).toBayernIdMessage(messageMetadata);
+		}
+
+		@Test
+		void shouldSetMessageBuilder() {
+			when(messageMapper.toBayernIdMessage(any())).thenReturn(bayernIdMessageBuilder);
+
+			uploadStreamObserver.readMessageMetadata(messageMetadata);
+
+			verify(messageBuilderAtomicReference).set(bayernIdMessageBuilder);
+		}
+
+	}
+
+	@Nested
+	class TestReadAttachments {
+
+		@Test
+		void shouldCallAddContainer() {
+			var attachmentMetadata = GrpcAttachmentMetadataTestFactory.create();
+			doNothing().when(uploadStreamObserver).addDataContainer(any());
+
+			uploadStreamObserver.readAttachments(GrpcAttachments.newBuilder().setAttachmentMetadata(attachmentMetadata).build());
+
+			verify(uploadStreamObserver).addDataContainer(attachmentMetadata);
+			verify(uploadStreamObserver, never()).writeAttachment(any());
+		}
+
+		@Test
+		void shouldCallWriteAttachment() {
+			var content = ByteString.copyFromUtf8("attachment");
+			var attachment = GrpcAttachments.newBuilder().setContent(content).build();
+			doNothing().when(uploadStreamObserver).writeAttachment(any());
+
+			uploadStreamObserver.readAttachments(attachment);
+
+			verify(uploadStreamObserver).writeAttachment(content);
+			verify(uploadStreamObserver, never()).addDataContainer(any());
+		}
+
+		@Nested
+		class TestAddDataContainer {
+
+			private GrpcAttachmentMetadata grpcAttachmentMetadata = GrpcAttachmentMetadataTestFactory.create();
+
+			@Mock
+			private Attachment attachment;
+
+			@Mock
+			private AtomicReference<BayernIdMessageBuilder> atomicMessageBuilder;
+
+			@BeforeEach
+			void setup() {
+				when(atomicMessageBuilder.get()).thenReturn(bayernIdMessageBuilder);
+				ReflectionTestUtils.setField(uploadStreamObserver, "messageBuilder", atomicMessageBuilder);
+			}
+
+			@Test
+			void shouldCallBuildAttachment() {
+				uploadStreamObserver.addDataContainer(grpcAttachmentMetadata);
+
+				verify(uploadStreamObserver).buildAttachment(grpcAttachmentMetadata);
+			}
+
+			@Test
+			void shouldAddAttachment() {
+				doReturn(attachment).when(uploadStreamObserver).buildAttachment(any());
+
+				uploadStreamObserver.addDataContainer(grpcAttachmentMetadata);
+
+				verify(bayernIdMessageBuilder).attachment(attachment);
+			}
+		}
+
+		@Nested
+		class TestBuildAttachment {
+
+			private GrpcAttachmentMetadata grpcAttachmentMetadata = GrpcAttachmentMetadataTestFactory.create();
+
+			@Mock
+			private InputStream tmpFileInputStream;
+
+			@BeforeEach
+			void setup() {
+				doReturn(tmpFileInputStream).when(uploadStreamObserver).createTemporallyFile(any());
+			}
+
+			@Test
+			void shouldCallCreateTemporallyFile() {
+				uploadStreamObserver.buildAttachment(grpcAttachmentMetadata);
+
+				verify(uploadStreamObserver).createTemporallyFile(GrpcAttachmentMetadataTestFactory.FILE_NAME);
+			}
+
+			@Test
+			void shouldSetTemporallyFile() {
+				var result = uploadStreamObserver.buildAttachment(grpcAttachmentMetadata);
+
+				assertThat(result.getContent()).isEqualTo(tmpFileInputStream);
+			}
+
+			@Test
+			void shouldSetAttachmentName() {
+				var result = uploadStreamObserver.buildAttachment(grpcAttachmentMetadata);
+
+				assertThat(result.getName()).isEqualTo(GrpcAttachmentMetadataTestFactory.FILE_NAME);
+			}
+
+			@Test
+			void shouldSetAttachmentType() {
+				var result = uploadStreamObserver.buildAttachment(grpcAttachmentMetadata);
+
+				assertThat(result.getType()).isEqualTo(GrpcAttachmentMetadataTestFactory.FILE_TYPE);
+			}
+		}
+
+		@Nested
+		class TestCreateTemporallyFile {
+
+			@Mock
+			private OutputStream attachmentWriter;
+			@Mock
+			private InputStream tmpFileInputStream;
+
+			private Path tempFilePath = Path.of("tempFile");
+
+			@Test
+			void shouldCallCloseTemporallyFile() {
+
+				uploadStreamObserver.createTemporallyFile("test.txt");
+
+				verify(uploadStreamObserver).closeTemporallyWriter();
+			}
+
+			@SneakyThrows
+			@Test
+			void shouldCallCreateFile() {
+				uploadStreamObserver.createTemporallyFile(GrpcAttachmentMetadataTestFactory.FILE_NAME);
+
+				verify(uploadStreamObserver).createFile(GrpcAttachmentMetadataTestFactory.FILE_NAME);
+			}
+
+			@SneakyThrows
+			@Test
+			void shouldCallNewOutputStream() {
+				doReturn(tempFilePath).when(uploadStreamObserver).createFile(any());
+
+				uploadStreamObserver.createTemporallyFile(GrpcAttachmentMetadataTestFactory.FILE_NAME);
+
+				verify(uploadStreamObserver).newOutputStream(tempFilePath);
+			}
+
+			@SneakyThrows
+			@Test
+			void shouldInitializeOutputWriter() {
+				doReturn(attachmentWriter).when(uploadStreamObserver).newOutputStream(any());
+
+				uploadStreamObserver.createTemporallyFile(GrpcAttachmentMetadataTestFactory.FILE_NAME);
+
+				assertThat(getAttachmentWriter()).isEqualTo(attachmentWriter);
+			}
+
+			@SneakyThrows
+			@Test
+			void shouldCallNewInputStream() {
+				doReturn(tempFilePath).when(uploadStreamObserver).createFile(any());
+
+				uploadStreamObserver.createTemporallyFile(GrpcAttachmentMetadataTestFactory.FILE_NAME);
+
+				verify(uploadStreamObserver).newInputStream(tempFilePath);
+			}
+
+			@SneakyThrows
+			@Test
+			void shouldReturnInputStream() {
+				doReturn(tmpFileInputStream).when(uploadStreamObserver).newInputStream(any());
+
+				var result = uploadStreamObserver.createTemporallyFile(GrpcAttachmentMetadataTestFactory.FILE_NAME);
+
+				assertThat(result).isEqualTo(tmpFileInputStream);
+			}
+
+			@SneakyThrows
+			@Test
+			void shouldThrowException() {
+				doThrow(new IOException()).when(uploadStreamObserver).createFile(any());
+
+				assertThrows(TechnicalException.class, () -> uploadStreamObserver.createTemporallyFile(GrpcAttachmentMetadataTestFactory.FILE_NAME));
+			}
+
+			private OutputStream getAttachmentWriter() {
+				return (OutputStream) ReflectionTestUtils.getField(uploadStreamObserver, "attachmentWriter");
+			}
+		}
+	}
+
+	@Nested
+	class TestOnError {
+
+		@Test
+		void shouldCallCloseTemporallyWriter() {
+			try {
+				uploadStreamObserver.onError(new RuntimeException());
+			} catch (TechnicalException e) {
+				// expected
+			}
+
+			verify(uploadStreamObserver).closeTemporallyWriter();
+		}
+
+		@Test
+		void shouldTrowTechnicalException() {
+			var cause = new RuntimeException();
+
+			var thrownException = assertThrows(TechnicalException.class, () -> uploadStreamObserver.onError(cause));
+
+			assertThat(thrownException.getCause()).isEqualTo(cause);
+		}
+	}
+
+	@Nested
+	class TestOnComplete {
+
+		@BeforeEach
+		void setup() {
+			when(messageBuilderAtomicReference.get()).thenReturn(bayernIdMessageBuilder);
+			ReflectionTestUtils.setField(uploadStreamObserver, "messageBuilder", messageBuilderAtomicReference);
+		}
+
+		@Test
+		void shouldCallCloseTemporallyWriter() {
+			uploadStreamObserver.onCompleted();
+
+			verify(uploadStreamObserver).closeTemporallyWriter();
+		}
+
+		@Test
+		void shouldCallSendBayernIdMessage() {
+			var bayernIdMessage = BayernIdMessageTestFactory.create();
+			when(bayernIdMessageBuilder.build()).thenReturn(bayernIdMessage);
+
+			uploadStreamObserver.onCompleted();
+
+			verify(proxyService).sendPostfachNachricht(bayernIdMessage);
+		}
+
+		@Test
+		void shouldCallMessageMapper() {
+			var bayernIdResponse = BayernIdResponseTestFactory.create();
+			when(proxyService.sendPostfachNachricht(any())).thenReturn(bayernIdResponse);
+
+			uploadStreamObserver.onCompleted();
+
+			verify(messageMapper).fromBayernIdResponse(bayernIdResponse);
+		}
+
+		@Test
+		void shouldCallResponseObserver() {
+			var grpcSendResponse = GrpcSendBayernIdMessageResponse.newBuilder().build();
+			when(messageMapper.fromBayernIdResponse(any())).thenReturn(grpcSendResponse);
+
+			uploadStreamObserver.onCompleted();
+
+			verify(responseObserver).onNext(grpcSendResponse);
+		}
+
+		@Test
+		void shouldCallSendResponse() {
+			uploadStreamObserver.onCompleted();
+
+			verify(responseObserver).onNext(any());
+		}
+
+		@Test
+		void shouldCallComplete() {
+			uploadStreamObserver.onCompleted();
+
+			verify(responseObserver).onCompleted();
+		}
+
+		@Test
+		void shouldThrowTechnicalException() {
+			var cause = new RuntimeException();
+
+			doThrow(cause).when(proxyService).sendPostfachNachricht(any());
+
+			var receivedException = assertThrows(TechnicalException.class, () -> uploadStreamObserver.onCompleted());
+			assertThat(receivedException.getCause()).isEqualTo(cause);
+		}
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/akdb/BayernIdRemoteServiceTest.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/akdb/BayernIdRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d257bd0ad3013894d2cb1fdde68ca318bf18716
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/akdb/BayernIdRemoteServiceTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.akdb;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import jakarta.xml.bind.JAXBElement;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.ws.client.core.WebServiceTemplate;
+
+import akdb.bsp.postkorb.komm.webservice.ObjectFactory;
+import akdb.bsp.postkorb.komm.webservice.SendBspNachrichtNative;
+import akdb.bsp.postkorb.komm.webservice.SendBspNachrichtNativeOutput;
+import de.akdb.egov.bsp.nachrichten.BspNachricht;
+import de.akdb.egov.bsp.nachrichten.BspQuittung;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessage;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessageMapper;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdResponse;
+
+class BayernIdRemoteServiceTest {
+
+	@Spy
+	@InjectMocks
+	private BayernIdRemoteService service;
+
+	@Mock
+	private BayernIdMessageMapper messageMapper;
+	@Mock
+	private ObjectFactory objectFactory;
+
+	@Nested
+	class TestSendPostfachNachricht {
+
+		@Mock
+		private SendBspNachrichtNative sendNachricht;
+		@Mock
+		private SendBspNachrichtNativeOutput sendBspNachrichtResponse;
+		@Mock
+		private BspQuittung bspQuittung;
+		@Mock
+		private JAXBElement<SendBspNachrichtNativeOutput> jaxbSendBspNachrichtNativeOutput;
+		@Mock
+		private BayernIdResponse response;
+		@Mock
+		private BayernIdMessage message;
+
+		@BeforeEach
+		void setup(){
+			doReturn(bspQuittung).when(service).createBspQuitung(any());
+			doReturn(sendNachricht).when(service).createSendNachricht(any());
+		}
+
+		@Test
+		void shouldCallCreateSendNachricht() {
+			doReturn(jaxbSendBspNachrichtNativeOutput).when(service).send(any());
+
+			sendMessage();
+
+			verify(service).createSendNachricht(message);
+		}
+
+		@Test
+		void shouldCallSendBspNachricht() {
+			doReturn(jaxbSendBspNachrichtNativeOutput).when(service).send(any());
+
+			sendMessage();
+
+			verify(service).sendBspNachricht(sendNachricht);
+		}
+
+		@Test
+		void shouldCallCreateBspQuitung() {
+			doReturn(sendBspNachrichtResponse).when(service).sendBspNachricht(any());
+
+			sendMessage();
+
+			verify(service).createBspQuitung(sendBspNachrichtResponse);
+		}
+
+		@Test
+		void shouldCallMessageMapper() {
+			doReturn(sendBspNachrichtResponse).when(service).sendBspNachricht(any());
+
+			sendMessage();
+
+			verify(messageMapper).toBayernIdResponse(bspQuittung);
+		}
+
+		@Test
+		void shouldReturnResponse() {
+			doReturn(response).when(messageMapper).toBayernIdResponse(bspQuittung);
+			doReturn(sendBspNachrichtResponse).when(service).sendBspNachricht(any());
+
+			var result = sendMessage();
+
+			assertThat(result).isEqualTo(response);
+		}
+
+		private BayernIdResponse sendMessage() {
+			return service.sendPostfachNachricht(message);
+		}
+
+	}
+
+	@Nested
+	class TestCreateSendNachricht {
+
+		private static final String RESULT_STRING = "result";
+
+		@Mock
+		private BayernIdMessage message;
+		@Mock
+		private BspNachricht bspNachricht;
+
+		@BeforeEach
+		void setup() {
+			doReturn(RESULT_STRING).when(service).buildBspNachrichtXml(any());
+		}
+
+		@Test
+		void shouldCallMessageMapper() {
+			service.createSendNachricht(message);
+
+			verify(messageMapper).toBspNachricht(message);
+		}
+
+		@Test
+		void shouldCallBuildBspNachrichtXml() {
+			when(messageMapper.toBspNachricht(any())).thenReturn(bspNachricht);
+
+			service.createSendNachricht(message);
+
+			verify(service).buildBspNachrichtXml(bspNachricht);
+		}
+
+		@Test
+		void shouldSetBspNachricht() {
+			var result = service.createSendNachricht(message);
+
+			assertThat(result.getBspNachricht()).isEqualTo(RESULT_STRING);
+		}
+	}
+
+	@Nested
+	class TestSendBspNachricht {
+
+		@Mock
+		private SendBspNachrichtNative sendBspNachrichtRequest;
+		@Mock
+		private JAXBElement<SendBspNachrichtNative> jaxbSendBspNachrichtNative;
+		@Mock
+		private JAXBElement<SendBspNachrichtNativeOutput> jaxbSendBspNachrichtNativeOutput;
+		@Mock
+		private SendBspNachrichtNativeOutput response;
+
+		@BeforeEach
+		void setup() {
+			doReturn(jaxbSendBspNachrichtNativeOutput).when(service).send(any());
+			when(jaxbSendBspNachrichtNativeOutput.getValue()).thenReturn(response);
+		}
+
+		@Test
+		void shouldCallMarshaller() {
+			service.sendBspNachricht(sendBspNachrichtRequest);
+
+			verify(objectFactory).createSendBspNachrichtNative(sendBspNachrichtRequest);
+		}
+
+		@Test
+		void shouldReturnValue() {
+			var sendBspNachrichtNativeOutput = service.sendBspNachricht(sendBspNachrichtRequest);
+
+			assertThat(sendBspNachrichtNativeOutput).isEqualTo(response);
+		}
+
+		@Test
+		void shouldCallSend() {
+			when(objectFactory.createSendBspNachrichtNative(any())).thenReturn(jaxbSendBspNachrichtNative);
+
+			service.sendBspNachricht(sendBspNachrichtRequest);
+
+			verify(service).send(jaxbSendBspNachrichtNative);
+		}
+
+	}
+
+	@Nested
+	class TestSend {
+
+		@Mock
+		private JAXBElement<SendBspNachrichtNative> jaxbSendBspNachrichtNative;
+		@Mock
+		private WebServiceTemplate webServiceTemplate;
+
+		@Test
+		void shouldCallMarshalSendAndReceive() {
+			doReturn(webServiceTemplate).when(service).getWebServiceTemplate();
+
+			service.send(jaxbSendBspNachrichtNative);
+
+			verify(webServiceTemplate).marshalSendAndReceive(jaxbSendBspNachrichtNative);
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/errorhandling/ExceptionHandlerTest.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/errorhandling/ExceptionHandlerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ad74aecebb47abac348397281e65549b481a052b
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/errorhandling/ExceptionHandlerTest.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.errorhandling;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.common.grpc.GrpcUtil;
+import io.grpc.Metadata;
+import io.grpc.Status;
+import io.grpc.Status.Code;
+import io.grpc.StatusException;
+
+class ExceptionHandlerTest {
+
+	@Spy
+	@InjectMocks
+	private ExceptionHandler exceptionHandler;
+
+	@Nested
+	class TestHandleTechnicalException {
+
+		private static final TechnicalException EXCEPTION = new TechnicalException("Test");
+
+		@Mock
+		private Metadata metadata;
+		@Mock
+		private StatusException statusException;
+
+		@Test
+		void shouldCallBuildInternalStatus() {
+			exceptionHandler.handleTechnicalException(EXCEPTION);
+
+			verify(exceptionHandler).buildInternalStatus(EXCEPTION);
+		}
+
+		@Test
+		void shouldCallBuildMetadata() {
+			exceptionHandler.handleTechnicalException(EXCEPTION);
+
+			verify(exceptionHandler).buildMetadata(EXCEPTION.getExceptionId());
+		}
+
+		@Test
+		void shouldCallCreateStatusException() {
+			var status = Status.INTERNAL;
+			doReturn(status).when(exceptionHandler).buildInternalStatus(any());
+			doReturn(metadata).when(exceptionHandler).buildMetadata(any());
+
+			exceptionHandler.handleTechnicalException(EXCEPTION);
+
+			verify(exceptionHandler).createStatusException(status, metadata);
+		}
+
+		@Test
+		void shouldReturnStatusException() {
+			doReturn(statusException).when(exceptionHandler).createStatusException(any(), any());
+
+			var result = exceptionHandler.handleTechnicalException(EXCEPTION);
+
+			assertThat(result).isEqualTo(statusException);
+		}
+	}
+
+	@Nested
+	class TestHandleRuntimeException {
+
+		private static final RuntimeException EXCEPTION = new RuntimeException("Test");
+
+		@Mock
+		private Metadata metadata;
+		@Mock
+		private StatusException statusException;
+
+		@Test
+		void shouldCallBuildInternalStatus() {
+			exceptionHandler.handleRuntimeException(EXCEPTION);
+
+			verify(exceptionHandler).buildInternalStatus(EXCEPTION);
+		}
+
+		@Test
+		void shouldCallCreateExceptionId() {
+			exceptionHandler.handleRuntimeException(EXCEPTION);
+
+			verify(exceptionHandler).createExceptionId();
+		}
+
+		@Test
+		void shouldCallBuildMetadata() {
+			var exceptionId = "42";
+			doReturn(exceptionId).when(exceptionHandler).createExceptionId();
+
+			exceptionHandler.handleRuntimeException(EXCEPTION);
+
+			verify(exceptionHandler).buildMetadata(exceptionId);
+		}
+
+		@Test
+		void shouldCallCreateStatusException() {
+			var status = Status.INTERNAL;
+			doReturn(status).when(exceptionHandler).buildInternalStatus(any());
+			doReturn(metadata).when(exceptionHandler).buildMetadata(any());
+
+			exceptionHandler.handleRuntimeException(EXCEPTION);
+
+			verify(exceptionHandler).createStatusException(status, metadata);
+		}
+
+		@Test
+		void shouldReturnStatusException() {
+			doReturn(statusException).when(exceptionHandler).createStatusException(any(), any());
+
+			var result = exceptionHandler.handleRuntimeException(EXCEPTION);
+
+			assertThat(result).isEqualTo(statusException);
+		}
+	}
+
+	@Nested
+	class TestBuildInternalStatus {
+
+		private static final Exception CAUSE = new Exception("Cause");
+		private static final RuntimeException EXCEPTION = new RuntimeException("Test", CAUSE);
+
+		@Test
+		void shouldSetInternalStatusCode() {
+			var result = exceptionHandler.buildInternalStatus(EXCEPTION);
+
+			assertThat(result.getCode()).isEqualTo(Code.INTERNAL);
+		}
+
+		@Test
+		void shouldSetDescription() {
+			var result = exceptionHandler.buildInternalStatus(EXCEPTION);
+
+			assertThat(result.getDescription()).isEqualTo(EXCEPTION.getMessage());
+		}
+
+		@Test
+		void shouldSetCause() {
+			var result = exceptionHandler.buildInternalStatus(EXCEPTION);
+
+			assertThat(result.getCause()).isEqualTo(CAUSE);
+		}
+	}
+
+	@Nested
+	class TestBuildMetadata {
+
+		private static final String EXCEPTION_ID = "42";
+		@Test
+		void shouldSetExceptionIdKey() {
+			var result = exceptionHandler.buildMetadata(EXCEPTION_ID);
+
+			assertThat(result.keys()).containsOnly(ExceptionHandler.KEY_EXCEPTION_ID.toLowerCase());
+		}
+
+		@Test
+		void shouldSetExceptionIdValue() {
+			var result = exceptionHandler.buildMetadata(EXCEPTION_ID);
+
+			assertThat(result.get(GrpcUtil.keyOfString(ExceptionHandler.KEY_EXCEPTION_ID))).isEqualTo(EXCEPTION_ID);
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/AbsenderTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/AbsenderTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..31164b3b208dd923bc8d7f0ee156bcc73546d841
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/AbsenderTestFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.Absender.AbsenderBuilder;
+
+public class AbsenderTestFactory {
+
+	public static final String ABSENDER_POSTKORB_ID = "absenderPostkorbId";
+	public static final String NAME = "Musterstadt Stadtverwaltung";
+	public static final String ANSCHRIFT = "Musterstraße 1";
+	public static final String EMAIL = "mail@exam.ple";
+	public static final String TELEFON = "0456123456789";
+	public static final String HYPERLINK = "http://some.link";
+	public static final String MANDANT = "Musterstadt";
+	public static final String DIENST = "Stadtverwaltung";
+	public static final String GEMEINDE_SCHLUESSEL = "123456789";
+
+	public static Absender create() {
+		return createBuilder().build();
+	}
+
+	public static AbsenderBuilder createBuilder() {
+		return Absender.builder()
+				.postkorbId(ABSENDER_POSTKORB_ID)
+				.name(NAME)
+				.anschrift(ANSCHRIFT)
+				.email(EMAIL)
+				.telefon(TELEFON)
+				.hyperlink(HYPERLINK)
+				.mandant(MANDANT)
+				.dienst(DIENST)
+				.gemeindeschluessel(GEMEINDE_SCHLUESSEL);
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/AttachmentTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/AttachmentTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc3f4fd378d3af6be1a28a3fbb892f760f4e1d38
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/AttachmentTestFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import java.io.ByteArrayInputStream;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.Attachment.AttachmentBuilder;
+
+public class AttachmentTestFactory {
+
+	public static final String FILE_NAME = "test.txt";
+	public static final String TYPE = "plain/text";
+	public static final byte[] CONTENT = "test".getBytes();
+
+	public static Attachment create() {
+		return createBuilder().build();
+	}
+
+	public static AttachmentBuilder createBuilder() {
+		return Attachment.builder()
+				.name(FILE_NAME)
+				.type(TYPE)
+				.content(new ByteArrayInputStream(CONTENT));
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageMapperTest.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f807b82c3e86863a7041a9fa29b148205f083262
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageMapperTest.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.ByteArrayInputStream;
+import java.util.List;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.Mockito;
+import org.testcontainers.shaded.org.apache.commons.io.IOUtils;
+
+import de.akdb.egov.bsp.nachrichten.BspNachricht;
+import de.akdb.egov.bsp.nachrichten.BspQuittung;
+import de.akdb.egov.bsp.nachrichten.DataContainerType;
+import de.akdb.egov.bsp.nachrichten.FreiTextType;
+import de.akdb.egov.bsp.nachrichten.NachrichtenInhaltType;
+import de.akdb.egov.bsp.nachrichten.NachrichtenKopfType;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.BayernIdResponseTestFactory;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAbsenderTestFactory;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcBayernIdMessageMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcBayernIdMessageMetadataTestFactory;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcEmpfaengerTestFactory;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+import lombok.SneakyThrows;
+
+class BayernIdMessageMapperTest {
+
+	private BayernIdMessageMapper mapper = Mappers.getMapper(BayernIdMessageMapper.class);
+
+	@Nested
+	class ToBayernIdMessage {
+
+		private static final GrpcBayernIdMessageMetadata MESSAGE_METADATA = GrpcBayernIdMessageMetadataTestFactory.create();
+
+		@Test
+		void shouldSetMessageId() {
+			var result = mapToBayernIdMessage();
+
+			assertThat(result.getMessageId()).isEqualTo(GrpcBayernIdMessageMetadataTestFactory.MESSAGE_ID);
+		}
+
+		@Test
+		void shouldSetCreatedAt() {
+			var result = mapToBayernIdMessage();
+
+			assertThat(result.getCreatedAt()).isEqualTo(GrpcBayernIdMessageMetadataTestFactory.CREATED_AT_STRING);
+		}
+
+		@Test
+		void shouldSetSubject() {
+			var result = mapToBayernIdMessage();
+
+			assertThat(result.getSubject()).isEqualTo(GrpcBayernIdMessageMetadataTestFactory.SUBJECT);
+		}
+
+		@Test
+		void shoulSetStorkQaaLevel() {
+			var result = mapToBayernIdMessage();
+
+			assertThat(result.getStorkQaaLevel()).isEqualTo(GrpcBayernIdMessageMetadataTestFactory.STORK_QAA_LEVEL);
+		}
+
+		@Test
+		void shouldSetVorgangId() {
+			var result = mapToBayernIdMessage();
+
+			assertThat(result.getVorgangId()).isEqualTo(GrpcBayernIdMessageMetadataTestFactory.VORGANG_ID);
+		}
+
+		@Test
+		void shouldSetText() {
+			var result = mapToBayernIdMessage();
+
+			assertThat(result.getText()).isEqualTo(GrpcBayernIdMessageMetadataTestFactory.MESSAGE_TEXT);
+		}
+
+		@Nested
+		class TestSetAbsender {
+
+			@Test
+			void shouldSetName() {
+				var result = mapToAbsender();
+
+				assertThat(result.getName()).isEqualTo(GrpcAbsenderTestFactory.NAME);
+			}
+
+			@Test
+			void shouldSetAnschrift() {
+				var result = mapToAbsender();
+
+				assertThat(result.getAnschrift()).isEqualTo(GrpcAbsenderTestFactory.ANSCHRIFT);
+			}
+
+			@Test
+			void shouldSetEmail() {
+				var result = mapToAbsender();
+
+				assertThat(result.getEmail()).isEqualTo(GrpcAbsenderTestFactory.EMAIL);
+			}
+
+			@Test
+			void shouldSetTelefon() {
+				var result = mapToAbsender();
+
+				assertThat(result.getTelefon()).isEqualTo(GrpcAbsenderTestFactory.TELEFON);
+			}
+
+			@Test
+			void shouldSetHyperlink() {
+				var result = mapToAbsender();
+
+				assertThat(result.getHyperlink()).isEqualTo(GrpcAbsenderTestFactory.HYPERLINK);
+			}
+
+			@Test
+			void shouldSetMandant() {
+				var result = mapToAbsender();
+
+				assertThat(result.getMandant()).isEqualTo(GrpcAbsenderTestFactory.MANDANT);
+			}
+
+			@Test
+			void shouldSetDienst() {
+				var result = mapToAbsender();
+
+				assertThat(result.getDienst()).isEqualTo(GrpcAbsenderTestFactory.DIENST);
+			}
+
+			@Test
+			void shouldSetGemeindeschluessel() {
+				var result = mapToAbsender();
+
+				assertThat(result.getGemeindeschluessel()).isEqualTo(GrpcAbsenderTestFactory.GEMEINDE_SCHLUESSEL);
+			}
+
+			private Absender mapToAbsender() {
+				var bayernIdMessage = mapToBayernIdMessage();
+				assertThat(bayernIdMessage.getAbsender()).isNotNull();
+				return bayernIdMessage.getAbsender();
+			}
+		}
+
+		@Nested
+		class TestSetEmpfaenger {
+
+			@Test
+			void shouldSetPostfachId() {
+				var result = mapToEmpfänger();
+
+				assertThat(result.getPostkorbId()).isEqualTo(GrpcEmpfaengerTestFactory.POSTFACH_ID);
+			}
+
+			@Test
+			void shouldSetName() {
+				var result = mapToEmpfänger();
+
+				assertThat(result.getName()).isEqualTo(GrpcEmpfaengerTestFactory.NAME);
+			}
+
+			@Test
+			void shouldSetAnschrift() {
+				var result = mapToEmpfänger();
+
+				assertThat(result.getAnschrift()).isEqualTo(GrpcEmpfaengerTestFactory.ANSCHRIFT);
+			}
+
+			private Empfaenger mapToEmpfänger() {
+				var bayernIdMessage = mapToBayernIdMessage();
+				assertThat(bayernIdMessage.getEmpfaenger()).isNotNull();
+				return bayernIdMessage.getEmpfaenger();
+
+			}
+		}
+
+		private BayernIdMessage mapToBayernIdMessage() {
+			return mapper.toBayernIdMessage(MESSAGE_METADATA).build();
+		}
+	}
+
+	@Nested
+	class TestFromBayernIdResponse {
+
+		private static final BayernIdResponse BAYERN_ID_RESPONSE = BayernIdResponseTestFactory.create();
+
+		@Test
+		void shouldSetSuccess() {
+			var result = mapToGrpcSendBayernIdMessageResponse();
+
+			assertThat(result.getSuccess()).isTrue();
+		}
+
+		@Test
+		void shouldSetStatus() {
+			var result = mapToGrpcSendBayernIdMessageResponse();
+
+			assertThat(result.getStatus()).isEqualTo(BayernIdResponseTestFactory.STATUS);
+		}
+
+		@Test
+		void shouldSetMessage() {
+			var result = mapToGrpcSendBayernIdMessageResponse();
+
+			assertThat(result.getMessage()).isEqualTo(BayernIdResponseTestFactory.MESSAGE);
+		}
+
+		private GrpcSendBayernIdMessageResponse mapToGrpcSendBayernIdMessageResponse() {
+			return mapper.fromBayernIdResponse(BAYERN_ID_RESPONSE);
+		}
+	}
+
+	@Nested
+	class TestToBspNachricht {
+
+		@Nested
+		class TestSetNachrichtenKopf {
+
+			@Test
+			void shouldSetNachrichtId() {
+				var result = mapToNachrichtenKopf().getIdentifikationNachricht();
+
+				assertThat(result.getNachrichtenId()).isEqualTo(BayernIdMessageTestFactory.MESSAGE_ID);
+			}
+
+			@Test
+			void shouldSetErstellungszeitpunkt() {
+				var result = mapToNachrichtenKopf().getIdentifikationNachricht();
+
+				assertThat(result.getErstellungszeitpunkt()).hasToString(BayernIdMessageTestFactory.CREATED_AT);
+			}
+
+			@Nested
+			class TestMapEmpfaenger {
+
+				@Test
+				void shouldSetPostkorbId() {
+					var result = mapToNachrichtenKopf().getEmpfaenger();
+
+					assertThat(result.getPostkorbId()).isEqualTo(EmpfaengerTestFactory.POSTKORB_ID);
+				}
+
+				@Test
+				void shouldSetName() {
+					var result = mapToNachrichtenKopf().getEmpfaenger();
+
+					assertThat(result.getName()).isEqualTo(EmpfaengerTestFactory.NAME);
+				}
+
+				@Test
+				void shouldSetAnschrift() {
+					var result = mapToNachrichtenKopf().getEmpfaenger();
+
+					assertThat(result.getAnschrift()).isEqualTo(EmpfaengerTestFactory.ANSCHRIFT);
+				}
+			}
+
+			@Nested
+			class TestMapAbsender {
+
+				@Test
+				void shouldSetName() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getName()).isEqualTo(AbsenderTestFactory.NAME);
+				}
+
+				@Test
+				void shouldSetAnschrift() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getAnschrift()).isEqualTo(AbsenderTestFactory.ANSCHRIFT);
+				}
+
+				@Test
+				void shouldSetEmail() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getEmail()).isEqualTo(AbsenderTestFactory.EMAIL);
+				}
+
+				@Test
+				void shouldSetTelefon() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getTelefon()).isEqualTo(AbsenderTestFactory.TELEFON);
+				}
+
+				@Test
+				void shouldSetHyperlink() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getHyperlink()).isEqualTo(AbsenderTestFactory.HYPERLINK);
+				}
+
+				@Test
+				void shouldSetMandant() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getMandant()).isEqualTo(AbsenderTestFactory.MANDANT);
+				}
+
+				@Test
+				void shouldSetDienst() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getDienst()).isEqualTo(AbsenderTestFactory.DIENST);
+				}
+
+				@Test
+				void shouldSetGemeindeschluessel() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getGemeindeschluessel().getSchluessel()).isEqualTo(AbsenderTestFactory.GEMEINDE_SCHLUESSEL);
+				}
+
+				@Test
+				void shouldSetPostkorbId() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getPostkorbId()).isEqualTo(AbsenderTestFactory.ABSENDER_POSTKORB_ID);
+				}
+
+				@Test
+				void shouldSetGemeindeschluesselTabelle() {
+					var result = mapToNachrichtenKopf().getAbsender();
+
+					assertThat(result.getGemeindeschluessel().getTabelle()).isEqualTo(BayernIdMessageMapper.TABELLE_NUMMER_GEMEINDE_SCHLUESSEL);
+				}
+
+			}
+
+			private NachrichtenKopfType mapToNachrichtenKopf() {
+				var bspNachricht = mapToBspNachricht();
+				assertThat(bspNachricht.getNachrichtenKopf()).isNotNull();
+				return bspNachricht.getNachrichtenKopf();
+			}
+		}
+
+		@Nested
+		class TestNachrichtenInhalt {
+
+			@Test
+			void shouldSetBetreff() {
+				var result = mapToNachrichtenInhalt();
+
+				assertThat(result.getBetreff()).isEqualTo(BayernIdMessageTestFactory.SUBJECT);
+			}
+
+			@Test
+			void shouldSetStorkQaaLevel() {
+				var result = mapToNachrichtenInhalt();
+
+				assertThat(result.getStorkQaaLevel().name()).isEqualTo(BayernIdMessageTestFactory.STORK_QAA_LEVEL);
+			}
+
+			@Test
+			void shouldSetVorgangsId() {
+				var result = mapToNachrichtenInhalt();
+
+				assertThat(result.getZuVorgang().getVorgangsId()).isEqualTo(BayernIdMessageTestFactory.VORGANG_ID);
+			}
+
+			@Nested
+			class TestMapFreiText {
+
+				@Test
+				void shouldSetEncodingSchluessel() {
+					var result = mapToFreiText();
+
+					assertThat(result.getEncoding().getSchluessel()).isEqualTo(BayernIdMessageMapper.TEXT_ENCODING_PLAIN_TEXT);
+				}
+
+				@Test
+				void shouldSetEncodingTabelle() {
+					var result = mapToFreiText();
+
+					assertThat(result.getEncoding().getTabelle()).isEqualTo(BayernIdMessageMapper.TABELLE_NUMMER_TEXT_ENCODING);
+				}
+
+				@Test
+				void shouldSetText() {
+					var result = mapToFreiText();
+
+					assertThat(result.getText()).isEqualTo(BayernIdMessageTestFactory.TEXT);
+				}
+
+				private FreiTextType mapToFreiText() {
+					var bspNachricht = mapToBspNachricht();
+					assertThat(bspNachricht.getNachrichtenInhalt().getFreiText()).isNotNull();
+					return bspNachricht.getNachrichtenInhalt().getFreiText();
+				}
+			}
+
+			@Nested
+			class TestMapAttachments {
+
+				@Test
+				void shouldSetName() {
+					var result = mapToDataContainerType();
+
+					assertThat(result.get(0).getFileName()).isEqualTo(AttachmentTestFactory.FILE_NAME);
+				}
+
+				@Test
+				void shouldSetFileType() {
+					var result = mapToDataContainerType();
+
+					assertThat(result.get(0).getFileType().getSchluessel()).isEqualTo(AttachmentTestFactory.TYPE);
+				}
+
+				@Test
+				void shouldSetFielTypeTable() {
+					var result = mapToDataContainerType();
+
+					assertThat(result.get(0).getFileType().getTabelle()).isEqualTo(BayernIdMessageMapper.TABELLE_NUMMER_MIME_TYPE);
+				}
+
+				@Test
+				void shouldSetInhalt() {
+					var result = mapToDataContainerType();
+
+					var attachmentInputStream = result.get(0);
+					assertThat(attachmentInputStream.getInhalt()).isEqualTo(AttachmentTestFactory.CONTENT);
+				}
+
+				@SneakyThrows
+				@Test
+				void shouldCloseSourceStream() {
+					var inputStream = spy(new ByteArrayInputStream(AttachmentTestFactory.CONTENT));
+
+					var r1 = mapper.toDataContainerType(AttachmentTestFactory.createBuilder().content(inputStream).build());
+
+					verify(inputStream).close();
+				}
+
+				private List<DataContainerType> mapToDataContainerType() {
+					return mapToNachrichtenInhalt().getDataContainer();
+				}
+			}
+
+			private NachrichtenInhaltType mapToNachrichtenInhalt() {
+				var bspNachricht = mapToBspNachricht();
+				assertThat(bspNachricht.getNachrichtenInhalt()).isNotNull();
+				return bspNachricht.getNachrichtenInhalt();
+			}
+		}
+
+		private BspNachricht mapToBspNachricht() {
+			return mapper.toBspNachricht(BayernIdMessageTestFactory.create());
+		}
+	}
+
+	@Nested
+	class TestMapToBayernIdResponse {
+
+		@Test
+		void shouldSetSuccess() {
+			var result = mapToBayernIdResponse();
+
+			assertThat(result.isSuccess()).isTrue();
+		}
+
+		@Test
+		void shouldSetStatus() {
+			var result = mapToBayernIdResponse();
+
+			assertThat(result.getStatus()).isEqualTo(BspQuitungTestFactory.STATUS_SCHLUESSEL);
+		}
+
+		@Test
+		void shouldSetMessage() {
+			var result = mapToBayernIdResponse();
+
+			assertThat(result.getMessage()).isEqualTo(BspQuitungTestFactory.ERGAENZENDE_HINWEISE);
+		}
+
+		private BayernIdResponse mapToBayernIdResponse() {
+			return mapper.toBayernIdResponse(BspQuitungTestFactory.create());
+		}
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9de0cb463ce242f7c327f0bdf1a5de7fb1b590a
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdMessageTestFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import java.util.Collections;
+import java.util.List;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.message.BayernIdMessage.BayernIdMessageBuilder;
+
+public class BayernIdMessageTestFactory {
+
+	public static final String MESSAGE_ID = "messageId";
+	public static final String CREATED_AT = "2021-01-01T00:00:00Z";
+	public static final String VORGANG_ID = "vorgangId";
+	public static final String SUBJECT = "subject";
+	public static final String STORK_QAA_LEVEL = "LEVEL_1";
+	public static final String TEXT = "text";
+
+	public static BayernIdMessage create() {
+		return createBuilder().build();
+	}
+
+	public static BayernIdMessageBuilder createBuilder() {
+		return BayernIdMessage.builder()
+				.messageId(MESSAGE_ID)
+				.createdAt(CREATED_AT)
+				.vorgangId(VORGANG_ID)
+				.subject(SUBJECT)
+				.storkQaaLevel(STORK_QAA_LEVEL)
+				.text(TEXT)
+				.empfaenger(EmpfaengerTestFactory.create())
+				.absender(AbsenderTestFactory.create())
+				.attachments(List.of(AttachmentTestFactory.create()));
+	}
+
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandExecutedEventTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdRsponseTestFactory.java
similarity index 77%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandExecutedEventTestFactory.java
rename to nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdRsponseTestFactory.java
index a7a1ec13d8bea906378bbb208c48a2eb58bdbd1c..a66934b4c61a437c29a15f6e426488f8f8e51ada 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandExecutedEventTestFactory.java
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BayernIdRsponseTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
 
-public class CommandExecutedEventTestFactory {
+public class BayernIdRsponseTestFactory {
 
-	public static CommandExecutedEvent createFor(Command command) {
-		return new CommandExecutedEvent(command.getId());
-	}
 
 }
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BspQuitungTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BspQuitungTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a526db4943155c6b1d4301abb6374de7bcf80bd5
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/BspQuitungTestFactory.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+import de.akdb.egov.bsp.nachrichten.BspQuittung;
+import de.akdb.egov.bsp.nachrichten.SchluesseltabelleType;
+
+public class BspQuitungTestFactory {
+
+	public static final String STATUS_SCHLUESSEL = "OK";
+	public static final String ERGAENZENDE_HINWEISE = "Hinweis";
+
+	public static BspQuittung create() {
+		var statusTable  = new SchluesseltabelleType();
+		statusTable.setSchluessel(STATUS_SCHLUESSEL);
+		var quittung = new BspQuittung();
+		quittung.setAnnahmeErfolgreich(true);
+		quittung.setErgebnisStatus(statusTable);
+		quittung.setErgaenzendeHinweise(ERGAENZENDE_HINWEISE);
+		return quittung;
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/EmpfaengerTestFactory.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/EmpfaengerTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce10fb25a7a096df6b04309a52b80d8bd1ecaa85
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/message/EmpfaengerTestFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.message;
+
+public class EmpfaengerTestFactory {
+
+	public static final String POSTKORB_ID = "postfachId";
+	public static final String NAME = "name";
+	public static final String ANSCHRIFT = "anschrift";
+
+	public static Empfaenger create() {
+		return createBuilder().build();
+	}
+
+	public static Empfaenger.EmpfaengerBuilder createBuilder() {
+		return Empfaenger.builder()
+				.postkorbId(POSTKORB_ID)
+				.name(NAME)
+				.anschrift(ANSCHRIFT);
+	}
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/BayernIdResponse.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/BayernIdResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e580efe72ed4adf560a30d132329b182808ab35
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/BayernIdResponse.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.mock;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class BayernIdResponse {
+
+	private boolean success;
+	private String status;
+	private String message;
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/GrpcBayernIdProxyTestClient.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/GrpcBayernIdProxyTestClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..14377844a1a24d94727bb4e32893e0b36ffcec43
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/GrpcBayernIdProxyTestClient.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.mock;
+
+import java.io.InputStream;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.BayernIdProxyServiceGrpc;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAttachmentMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcBayernIdMessageMetadata;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+
+@RequiredArgsConstructor
+public class GrpcBayernIdProxyTestClient {
+
+	static final int CHUNK_SIZE = 255 * 1024;
+
+	private final BayernIdProxyServiceGrpc.BayernIdProxyServiceStub serviceStub;
+
+	@SneakyThrows
+	public BayernIdResponse sendMessage(GrpcBayernIdMessageMetadata messageMetadata, Set<Pair<GrpcAttachmentMetadata, InputStream>> attachments) throws
+			ExecutionException {
+		var streamer = new MockChunkedDataStreamer(messageMetadata, attachments, CHUNK_SIZE);
+		var future = new CompletableFuture<BayernIdResponse>();
+		serviceStub.sendMessageAsStream(new MockBayernIdSendStreamObserver(future, streamer));
+		return future.get(10, TimeUnit.SECONDS);
+	}
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockBayernIdInitializer.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockBayernIdInitializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8783960212ad82bc38654f8103e29deeb5027f2
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockBayernIdInitializer.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.mock;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class MockBayernIdInitializer {
+
+	private static final String RESPONSE_TEMPLATE = """
+			<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
+				<SOAP-ENV:Header/>
+				<SOAP-ENV:Body>
+					<ns2:sendBspNachrichtNativeOutput xmlns:ns2="urn:akdb:bsp:postkorb:komm:webservice">
+						<bspQuittung>%s</bspQuittung>
+					</ns2:sendBspNachrichtNativeOutput>
+				</SOAP-ENV:Body>
+			</SOAP-ENV:Envelope>
+						""";
+	public static final String BSP_NACHRICHT_SUCCESS = "&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;&lt;BspQuittung version=\"1.5\" fassung=\"2020-03-15\" xmlns=\"http://www.akdb.de/egov/bsp/nachrichten\"&gt;&lt;AnnahmeErfolgreich&gt;true&lt;/AnnahmeErfolgreich&gt;&lt;ErgebnisStatus&gt;&lt;Tabelle&gt;9006&lt;/Tabelle&gt;&lt;Schluessel&gt;0&lt;/Schluessel&gt;&lt;/ErgebnisStatus&gt;&lt;ErgaenzendeHinweise&gt;Nachricht wurde angenommen&lt;/ErgaenzendeHinweise&gt;&lt;/BspQuittung&gt;";
+	public static final String BSP_NACHRICHT_ERROR = "&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?&gt;&lt;BspQuittung version=\"1.5\" fassung=\"2020-03-15\" xmlns=\"http://www.akdb.de/egov/bsp/nachrichten\"&gt;&lt;AnnahmeErfolgreich&gt;false&lt;/AnnahmeErfolgreich&gt;&lt;ErgebnisStatus&gt;&lt;Tabelle&gt;9006&lt;/Tabelle&gt;&lt;Schluessel&gt;31&lt;/Schluessel&gt;&lt;/ErgebnisStatus&gt;&lt;ErgaenzendeHinweise&gt;Unzulässiger Nachrichteninhalt&lt;/ErgaenzendeHinweise&gt;&lt;/BspQuittung&gt;";
+
+	public final WireMockRuntimeInfo wmRuntimeInfo;
+
+	public void createResponseOk() {
+		wmRuntimeInfo.getWireMock().register(
+				post("/").willReturn(aResponse()
+						.withStatus(200)
+						.withHeader("Content-Type", "text/xml")
+						.withHeader("charset", "UTF-8")
+						.withBody(RESPONSE_TEMPLATE.formatted(BSP_NACHRICHT_SUCCESS))
+				));
+	}
+
+	public void createResponseError() {
+		wmRuntimeInfo.getWireMock().register(
+				post("/").willReturn(aResponse()
+						.withStatus(200)
+						.withHeader("Content-Type", "text/xml")
+						.withHeader("charset", "UTF-8")
+						.withBody(RESPONSE_TEMPLATE.formatted(BSP_NACHRICHT_ERROR))
+				));
+	}
+
+	public void createResponseWithException() {
+		wmRuntimeInfo.getWireMock().register(
+				post("/").willReturn(aResponse()
+						.withStatus(200)
+						.withHeader("Content-Type", "text/xml")
+						.withHeader("charset", "UTF-8")
+						.withBody("Internal Server Error")
+				));
+	}
+
+	public void create500Response() {
+		wmRuntimeInfo.getWireMock().register(
+				post("/").willReturn(aResponse()
+						.withStatus(500)
+						.withBody("Internal Server Error")
+				));
+	}
+
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockBayernIdSendStreamObserver.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockBayernIdSendStreamObserver.java
new file mode 100644
index 0000000000000000000000000000000000000000..242136773ccd360dba8ebb019b4113b579f5668a
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockBayernIdSendStreamObserver.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.mock;
+
+import java.util.concurrent.CompletableFuture;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+import io.grpc.stub.ClientCallStreamObserver;
+import io.grpc.stub.ClientResponseObserver;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
+class MockBayernIdSendStreamObserver implements ClientResponseObserver<GrpcSendBayernIdMessageRequest, GrpcSendBayernIdMessageResponse> {
+
+	private final CompletableFuture<BayernIdResponse> fileIdFuture;
+	private final MockChunkedDataStreamer fileStreamer;
+
+	@Getter
+	private BayernIdResponse bayernIdResponse;
+
+	private ClientCallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+
+	@Override
+	public void beforeStart(ClientCallStreamObserver<GrpcSendBayernIdMessageRequest> requestStream) {
+		this.requestObserver = requestStream;
+		requestObserver.setOnReadyHandler(() -> fileStreamer.sendChunkedTo(requestObserver));
+	}
+
+	@Override
+	public void onNext(GrpcSendBayernIdMessageResponse response) {
+		bayernIdResponse = BayernIdResponse.builder().success(response.getSuccess()).message(response.getMessage()).status(response.getStatus())
+				.build();
+	}
+
+	@Override
+	public void onError(Throwable t) {
+		fileIdFuture.completeExceptionally(t);
+	}
+
+	@Override
+	public void onCompleted() {
+		fileIdFuture.complete(bayernIdResponse);
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockChunkedDataStreamer.java b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockChunkedDataStreamer.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ecf22321e0254432f47efd0cacc4302fc6b119d
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/proxy/mock/MockChunkedDataStreamer.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy.mock;
+
+import static java.util.Objects.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.tuple.Pair;
+
+import com.google.protobuf.ByteString;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAttachmentMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAttachments;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcBayernIdMessageMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import io.grpc.stub.CallStreamObserver;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+class MockChunkedDataStreamer {
+
+	private Set<Pair<GrpcAttachmentMetadata, InputStream>> attachments;
+	private final int chunkSize;
+	private boolean isFinished = false;
+	private GrpcBayernIdMessageMetadata messageMetadata;
+
+	public MockChunkedDataStreamer(GrpcBayernIdMessageMetadata metadata, Set<Pair<GrpcAttachmentMetadata, InputStream>> attachments, int chunkSize) {
+		this.messageMetadata = metadata;
+		this.attachments = attachments;
+		this.chunkSize = chunkSize;
+	}
+
+	public synchronized void sendChunkedTo(CallStreamObserver<GrpcSendBayernIdMessageRequest> streamObserver) {
+		if (isFinished) {
+			return;
+		}
+		sendMessageMetadata(streamObserver);
+		attachments.forEach(attachment -> {
+			sendAttachmentMetadata(attachment.getLeft(), streamObserver);
+			sendContentChunked(attachment.getRight(), streamObserver);
+		});
+		handleFileEndReached(streamObserver);
+	}
+
+	void sendContentChunked(InputStream contentStream, CallStreamObserver<GrpcSendBayernIdMessageRequest> streamObserver) {
+		var inProgerss = true;
+		do {
+			int size = sendNextChunk(contentStream, streamObserver);
+			if (size < chunkSize) {
+				sendNextChunk(contentStream, streamObserver);
+				inProgerss = false;
+			}
+		} while (inProgerss && streamObserver.isReady());
+		IOUtils.closeQuietly(contentStream);
+	}
+
+	void sendMessageMetadata(CallStreamObserver<GrpcSendBayernIdMessageRequest> streamObserver) {
+		if (nonNull(messageMetadata)) {
+			streamObserver.onNext(buildRequestWithMetadata(messageMetadata));
+			messageMetadata = null;
+		}
+	}
+
+	GrpcSendBayernIdMessageRequest buildRequestWithMetadata(GrpcBayernIdMessageMetadata metadata) {
+		return GrpcSendBayernIdMessageRequest.newBuilder().setMessageMetadata(metadata).build();
+	}
+
+	void sendAttachmentMetadata(GrpcAttachmentMetadata metadata, CallStreamObserver<GrpcSendBayernIdMessageRequest> streamObserver) {
+		streamObserver.onNext(buildRequestWithAttachmentMetadata(metadata));
+	}
+
+	GrpcSendBayernIdMessageRequest buildRequestWithAttachmentMetadata(GrpcAttachmentMetadata attachmentMetadata) {
+		return GrpcSendBayernIdMessageRequest.newBuilder()
+				.setAttachments(GrpcAttachments.newBuilder().setAttachmentMetadata(attachmentMetadata).build()).build();
+	}
+
+	private int sendNextChunk(InputStream contentStream, CallStreamObserver<GrpcSendBayernIdMessageRequest> streamObserver) {
+		try {
+			var content = contentStream.readNBytes(chunkSize);
+			var size = content.length;
+			if (size > 0) {
+				streamObserver.onNext(buildRequestWithContent(content));
+			}
+			return size;
+		} catch (IOException e) {
+			throw new TechnicalException("Error on sending a single chunk", e);
+		}
+	}
+
+	GrpcSendBayernIdMessageRequest buildRequestWithContent(byte[] bytes) {
+		return GrpcSendBayernIdMessageRequest.newBuilder().setAttachments(GrpcAttachments.newBuilder().setContent(ByteString.copyFrom(bytes)).build())
+				.build();
+	}
+
+	synchronized void handleFileEndReached(CallStreamObserver<GrpcSendBayernIdMessageRequest> streamObserver) {
+		isFinished = true;
+		streamObserver.onCompleted();
+	}
+
+}
diff --git a/pluto-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
similarity index 100%
rename from pluto-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
rename to nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/application-itcase.yml b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/application-itcase.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d4d24173ab74f278b1e07c54dc468805f8965fdc
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/application-itcase.yml
@@ -0,0 +1,10 @@
+logging:
+  level:
+    ROOT: INFO
+    '[org.springframework]': WARN
+    '[de.ozgcloud]': INFO
+  config: classpath:log4j2-local.xml
+
+grpc:
+  server:
+    port: -1
diff --git a/pluto-server/src/test/resources/junit-platform.properties b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/junit-platform.properties
similarity index 100%
rename from pluto-server/src/test/resources/junit-platform.properties
rename to nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/junit-platform.properties
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000000000000000000000000000000000..ca6ee9cea8ec189a088d50559325d4e84ff8ad09
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/test.pdf b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/test.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..184dd5915515ca49dfaa8840883e6259d2a667aa
Binary files /dev/null and b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/test.pdf differ
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/test.txt b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/test.txt
new file mode 100644
index 0000000000000000000000000000000000000000..814be41a4bbeee81df9c0f296e3fcc3a3cef33f0
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-impl/src/test/resources/test.txt
@@ -0,0 +1 @@
+some simple text
\ No newline at end of file
diff --git a/pluto-interface/pom.xml b/nachrichten-bayernid-proxy/bayernid-proxy-interface/pom.xml
similarity index 53%
rename from pluto-interface/pom.xml
rename to nachrichten-bayernid-proxy/bayernid-proxy-interface/pom.xml
index 838027c65124485bc79c2989d5f5d7009ba0bce4..90b8f0d2552d456fba68cd195146a733de87d363 100644
--- a/pluto-interface/pom.xml
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-interface/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -24,62 +24,34 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 
 	<parent>
-		<groupId>de.itvsh.kop.common</groupId>
-		<artifactId>kop-common-dependencies</artifactId>
-		<version>1.2.1</version>
-		<relativePath />
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-dependencies</artifactId>
+		<version>3.0.1</version>
+		<relativePath/>
 	</parent>
 
-	<groupId>de.itvsh.ozg.pluto</groupId>
-	<artifactId>pluto-interface</artifactId>
-	<version>1.0.0</version>
+	<groupId>de.ozgcloud.nachrichten</groupId>
+	<artifactId>bayernid-proxy-interface</artifactId>
+	<version>0.1.0</version>
 
-	<name>Pluto Interface</name>
-	<description>Interface (gRPC) for Pluto Server</description>
+	<name>OZG-Cloud BayernID Proxy Interface</name>
+	<description>Interface (gRPC) for BayernID Proxy Service</description>
 
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
 		<java.version>17</java.version>
 		<maven.compiler.source>${java.version}</maven.compiler.source>
 		<maven.compiler.target>${java.version}</maven.compiler.target>
-	</properties>
 
-	<dependencyManagement>
-		<dependencies>
-			<dependency>
-				<groupId>de.itvsh.kop.common</groupId>
-				<artifactId>kop-common-dependencies</artifactId>
-				<version>${kop-common.version}</version>
-				<type>pom</type>
-				<scope>import</scope>
-			</dependency>
-		</dependencies>
-	</dependencyManagement>
+		<find-and-replace-maven-plugin.version>1.1.0</find-and-replace-maven-plugin.version>
+	</properties>
 
 	<dependencies>
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-context</artifactId>
-		</dependency>
-
-		<dependency>
-			<groupId>de.itvsh.kop.common</groupId>
-			<artifactId>kop-common-lib</artifactId>
-		</dependency>
-
-		<dependency>
-			<groupId>org.projectlombok</groupId>
-			<artifactId>lombok</artifactId>
-			<optional>true</optional>
-		</dependency>
-
 		<!-- GRPC -->
 		<dependency>
 			<groupId>io.grpc</groupId>
@@ -89,24 +61,13 @@
 			<groupId>io.grpc</groupId>
 			<artifactId>grpc-protobuf</artifactId>
 		</dependency>
-
-		<!-- Java 9+ compatibility -->
 		<dependency>
-			<groupId>javax.annotation</groupId>
-			<artifactId>javax.annotation-api</artifactId>
+			<groupId>jakarta.annotation</groupId>
+			<artifactId>jakarta.annotation-api</artifactId>
 		</dependency>
-
-
 	</dependencies>
 
 	<build>
-		<extensions>
-			<extension>
-				<groupId>kr.motd.maven</groupId>
-				<artifactId>os-maven-plugin</artifactId>
-			</extension>
-		</extensions>
-
 		<plugins>
 			<plugin>
 				<groupId>com.github.os72</groupId>
@@ -119,32 +80,42 @@
 							<goal>run</goal>
 						</goals>
 						<configuration>
+							<includeMavenTypes>direct</includeMavenTypes>
 							<outputTargets>
 								<outputTarget>
 									<type>java</type>
 								</outputTarget>
 								<outputTarget>
 									<type>grpc-java</type>
-									<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.47.0</pluginArtifact>
+									<pluginArtifact>io.grpc:protoc-gen-grpc-java:${protoc-gen.version}</pluginArtifact>
 								</outputTarget>
 							</outputTargets>
 						</configuration>
 					</execution>
 				</executions>
 			</plugin>
+			<plugin>
+				<groupId>io.github.floverfelt</groupId>
+				<artifactId>find-and-replace-maven-plugin</artifactId>
+				<version>${find-and-replace-maven-plugin.version}</version>
+				<executions>
+					<execution>
+						<id>exec</id>
+						<phase>process-sources</phase>
+						<goals>
+							<goal>find-and-replace</goal>
+						</goals>
+						<configuration>
+							<replacementType>file-contents</replacementType>
+							<baseDir>target/generated-sources/</baseDir>
+							<findRegex>javax</findRegex>
+							<replaceValue>jakarta</replaceValue>
+							<recursive>true</recursive>
+							<fileMask>.java</fileMask>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
 		</plugins>
 	</build>
-
-	<distributionManagement>
-		<repository>
-			<id>ozg-nexus</id>
-			<name>ozg-releases</name>
-			<url>https://nexus.ozg-sh.de/repository/ozg-releases/</url>
-		</repository>
-		<snapshotRepository>
-			<id>ozg-snapshots-nexus</id>
-			<name>ozg-snapshots</name>
-			<url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url>
-		</snapshotRepository>
-	</distributionManagement>
 </project>
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-interface/src/main/protobuf/bayernidproxy.model.proto b/nachrichten-bayernid-proxy/bayernid-proxy-interface/src/main/protobuf/bayernidproxy.model.proto
new file mode 100644
index 0000000000000000000000000000000000000000..91ed9ee0ab3f2db2c03907d0b12447fddab01bd9
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-interface/src/main/protobuf/bayernidproxy.model.proto
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+syntax = "proto3";
+
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+option java_multiple_files = true;
+option java_package = "de.ozgcloud.nachrichten.postfach.bayernid.proxy";
+option java_outer_classname = "BayernIdProxyModelProto";
+
+message GrpcSendBayernIdMessageRequest {
+  oneof request {
+    GrpcBayernIdMessageMetadata messageMetadata = 1;
+    GrpcAttachments attachments = 2;
+  }
+}
+
+message GrpcBayernIdMessageMetadata {
+  string messageId = 1;
+  string createdAt = 2;
+  GrpcAbsender absender = 3;
+  GrpcEmpfaenger empfaenger = 4;
+  string subject = 5;
+  string storkQaaLevel = 6;
+  string vorgangId = 7;
+  string text = 8;
+}
+
+message GrpcAbsender {
+  string name = 1;
+  string anschrift = 2;
+  string email = 3;
+  string telefon = 4;
+  string hyperlink = 5;
+  string dienst = 6;
+  string mandant = 7;
+  string gemeindeschluessel = 8;
+}
+
+message GrpcEmpfaenger {
+  string postkorbId = 1;
+  string name = 2;
+  string anschrift = 3;
+}
+
+message GrpcAttachments {
+  oneof request {
+    GrpcAttachmentMetadata attachmentMetadata = 1;
+    bytes content = 2;
+  }
+}
+
+message GrpcAttachmentMetadata {
+  string fileType = 1;
+  string fileName = 2;
+}
+
+message GrpcSendBayernIdMessageResponse {
+  bool success = 1;
+  string status = 2;
+  string message = 3;
+}
diff --git a/nachrichten-bayernid-proxy/bayernid-proxy-interface/src/main/protobuf/bayernproxy.proto b/nachrichten-bayernid-proxy/bayernid-proxy-interface/src/main/protobuf/bayernproxy.proto
new file mode 100644
index 0000000000000000000000000000000000000000..039909e0f942195f3bc600bf04746a9c8af5f1b6
--- /dev/null
+++ b/nachrichten-bayernid-proxy/bayernid-proxy-interface/src/main/protobuf/bayernproxy.proto
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+syntax = "proto3";
+
+package de.ozgcloud.nachrichten.postfach.bayernid.proxy;
+
+import "bayernidproxy.model.proto";
+
+option java_multiple_files = true;
+option java_package = "de.ozgcloud.nachrichten.postfach.bayernid.proxy";
+option java_outer_classname = "BayernIdProxyProto";
+
+service BayernIdProxyService {
+
+  rpc SendMessageAsStream(stream GrpcSendBayernIdMessageRequest) returns (GrpcSendBayernIdMessageResponse);
+
+}
diff --git a/nachrichten-bayernid-proxy/pom.xml b/nachrichten-bayernid-proxy/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..928e844afb374faf5dc49213dc7a228d8f8b8021
--- /dev/null
+++ b/nachrichten-bayernid-proxy/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-parent</artifactId>
+		<version>3.0.1</version>
+		<relativePath/>
+	</parent>
+
+	<groupId>de.ozgcloud.nachrichten</groupId>
+	<artifactId>nachrichten-bayernid-proxy</artifactId>
+	<version>0.1.0</version>
+	<packaging>pom</packaging>
+
+	<name>OZG-Cloud BayernID Proxy</name>
+	<description>Proxy Service for BayernID</description>
+
+	<modules>
+		<module>bayernid-proxy-impl</module>
+		<module>bayernid-proxy-interface</module>
+	</modules>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<java.version>17</java.version>
+		<maven.compiler.source>${java.version}</maven.compiler.source>
+		<maven.compiler.target>${java.version}</maven.compiler.target>
+		<jaxb-maven-plugin.version>4.0.0</jaxb-maven-plugin.version>
+		<wiremock.version>3.3.1</wiremock.version>
+	</properties>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>com.mycila</groupId>
+				<artifactId>license-maven-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</build>
+</project>
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/run_helm_test.sh b/nachrichten-bayernid-proxy/run_helm_test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4bcf6139c9d08e1632e2bec892dfd34741f0ec76
--- /dev/null
+++ b/nachrichten-bayernid-proxy/run_helm_test.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+
+set -e
+
+helm template  ./src/main/helm/ -f src/test/helm-linter-values.yaml
+helm lint -f src/test/helm-linter-values.yaml ./src/main/helm/
+cd src/main/helm && helm unittest -f '../../test/helm/*.yaml'  .
+
diff --git a/nachrichten-bayernid-proxy/src/main/helm/.helmignore b/nachrichten-bayernid-proxy/src/main/helm/.helmignore
new file mode 100644
index 0000000000000000000000000000000000000000..3d0dbe446770be5127eb719b695414c427b09715
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/.helmignore
@@ -0,0 +1 @@
+tests/
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/main/helm/Chart.yaml b/nachrichten-bayernid-proxy/src/main/helm/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..95a5e39ee7c7177acde0389c8b655efe8f797f6d
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/Chart.yaml
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+appVersion: "1.0"
+description: A Helm chart for Bayernid-Proxy
+name: bayernid-proxy
+version: 0.0.0-MANAGED-BY-JENKINS
+icon: https://simpleicons.org/icons/helm.svg
diff --git a/nachrichten-bayernid-proxy/src/main/helm/templates/_helpers.tpl b/nachrichten-bayernid-proxy/src/main/helm/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..0ea6c8d8c9dd30157cc593c949f47a7be8a738a2
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/templates/_helpers.tpl
@@ -0,0 +1,47 @@
+
+{{/* Default Labels: Helm recommended best-practice labels https://helm.sh/docs/chart_best_practices/labels/ */}}
+{{- define "app.defaultLabels" }}
+app.kubernetes.io/instance: bayernid-proxy
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+app.kubernetes.io/name: {{ .Release.Name }}
+app.kubernetes.io/namespace: {{ .Release.Namespace }}
+app.kubernetes.io/part-of: ozgcloud
+app.kubernetes.io/version: {{ .Chart.Version }}
+helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }}
+app.kubernetes.io/component: bayernid-proxy
+component: bayernid-proxy
+{{- end -}}
+
+{{- define "app.matchLabels" }}
+app.kubernetes.io/name: {{ .Release.Name }}
+app.kubernetes.io/namespace: {{ .Release.Namespace }}
+component: bayernid-proxy
+{{- end -}}
+
+{{- define "app.envSpringProfiles" }}
+{{- if (.Values.env).overrideSpringProfiles -}}
+{{ printf "%s" (.Values.env).overrideSpringProfiles }}
+{{- else -}}
+{{ printf "oc, %s" (include "app.ozgcloudEnvironment" . ) }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.ozgcloudEnvironment" -}}
+{{- required "ozgcloud.environment muss angegeben sein" (.Values.ozgcloud).environment -}}
+{{- end -}}
+
+
+{{ define "app.zertifikatPath" }}
+{{- required "ozgcloud zertifikat path muss angegeben sein" (.Values.ozgcloud).bayernid.zertifikat.path -}}
+{{- end -}}
+
+
+{{ define "app.zertifikatFilename" }}
+{{- required "ozgcloud zertifikat fileName muss angegeben sein" (.Values.ozgcloud).bayernid.zertifikat.fileName -}}
+{{- end -}}
+
+
+{{- define "app.serviceAccountName" -}}
+{{ printf "%s" ( (.Values.serviceAccount).name | default "bayernid-proxy-service-account" ) }}
+{{- end -}}
+
diff --git a/nachrichten-bayernid-proxy/src/main/helm/templates/configmap_bindings_type.yaml b/nachrichten-bayernid-proxy/src/main/helm/templates/configmap_bindings_type.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..621670490dbfef6c04d6b7e15c8d764b77e2a472
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/templates/configmap_bindings_type.yaml
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: bindings-type
+  namespace: {{ .Release.Namespace }}
+data:
+  type: |
+    ca-certificates
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/main/helm/templates/deployment.yaml b/nachrichten-bayernid-proxy/src/main/helm/templates/deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e78b63092a620fb270bad73603ccfe8a24354564
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/templates/deployment.yaml
@@ -0,0 +1,166 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ .Release.Name }}
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+spec:
+  progressDeadlineSeconds: 600
+  replicas: {{ .Values.replicaCount }}
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      {{- include "app.matchLabels" . | indent 6 }}
+  strategy:
+    rollingUpdate:
+      maxSurge: 1
+      maxUnavailable: 0
+    type: RollingUpdate
+  template:
+    metadata:
+      labels:
+        {{- include "app.defaultLabels" . | indent 8 }}
+    spec:  
+      {{- if (.Values.serviceAccount).create }}
+      serviceAccountName: {{ include "app.serviceAccountName" . }}
+      {{- end }}
+      topologySpreadConstraints:
+      - maxSkew: 1
+        topologyKey: kubernetes.io/hostname
+        whenUnsatisfiable: ScheduleAnyway
+        labelSelector:
+          matchLabels:
+            app.kubernetes.io/name: {{ .Release.Name }}
+      containers:
+      - env:
+          - name: SERVICE_BINDING_ROOT
+            value: "/bindings"
+          - name: spring_profiles_active
+            value: {{ include "app.envSpringProfiles" . }}
+
+          {{- with (.Values.env).customList }}
+{{ toYaml . | indent 10 }}
+          {{- end }}
+
+          - name: ozgcloud_bayernid_server
+            value: {{ required "ozgcloud.bayernid.server must be set" (.Values.ozgcloud).bayernid.server }}
+
+          - name: spring_ssl_bundle_jks_bayern-id-ca_keystore_location
+            value: "/keystore/bayernid/bayern-id-ca.p12"
+          - name: spring_ssl_bundle_jks_bayern-id-ca_keystore_type
+            value: PKCS12
+          - name: spring_ssl_bundle_jks_bayern-id-ca_keystore_password
+            valueFrom:
+              secretKeyRef:
+                name: {{ required "ozgcloud.bayernid.certificateSecretName must be set" ((.Values.ozgcloud).bayernid).certificateSecretName }}
+                key: password
+                optional: false
+
+        image: "{{ .Values.image.repo }}/{{ .Values.image.name }}:{{ coalesce (.Values.image).tag "latest" }}"
+        imagePullPolicy: Always
+        name: bayernid-proxy
+        ports:
+          - containerPort: 9090
+            name: grpc-9090
+            protocol: TCP
+          - containerPort: 8081
+            name: metrics
+            protocol: TCP
+        readinessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /actuator/health/readiness
+            port: 8081
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 3
+        startupProbe:
+          httpGet:
+            path: /actuator/health/readiness
+            port: 8081
+            scheme: HTTP
+          failureThreshold: 10
+          initialDelaySeconds: 20
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 5
+        resources:
+        {{- with .Values.resources }}
+{{ toYaml . | indent 10 }}
+        {{- end }}
+        securityContext:
+          allowPrivilegeEscalation: false
+          privileged: false
+          readOnlyRootFilesystem: false
+          runAsNonRoot: true
+          {{- with (.Values.securityContext).runAsUser }}
+          runAsUser: {{ . }}
+          {{- end }}
+          {{- with (.Values.securityContext).runAsGroup }}
+          runAsGroup: {{ . }}
+          {{- end }}
+        stdin: true
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+        tty: true
+        volumeMounts:
+          - name: bindings
+            mountPath: "/bindings/ca-certificates/type"
+            subPath: type
+            readOnly: true
+          - name: bayern-id-ca
+            mountPath: "/keystore/bayernid/bayern-id-ca.p12"
+            subPath: zertifikat
+            readOnly: true
+          - name: temp-dir
+            mountPath: "/tmp"
+      
+      volumes: 
+        - name: bindings
+          configMap:
+            name: bindings-type
+        - name: bayern-id-ca
+          secret:
+            secretName: {{ required "ozgcloud.bayernid.certificateSecretName must be set" ((.Values.ozgcloud).bayernid).certificateSecretName }}
+            optional: false
+        - name: temp-dir
+          emptyDir: {}
+      dnsConfig: {}
+      dnsPolicy: ClusterFirst
+      imagePullSecrets:
+      - name: {{ required "imagePullSecret must be set" .Values.imagePullSecret  }}
+   
+      restartPolicy: Always
+      {{- with .Values.hostAliases }}
+      hostAliases:
+{{ toYaml . | indent 8 }}
+      {{- end }}
+      schedulerName: default-scheduler
+      securityContext: {}
+      terminationGracePeriodSeconds: 30
diff --git a/nachrichten-bayernid-proxy/src/main/helm/templates/network_policy.yaml b/nachrichten-bayernid-proxy/src/main/helm/templates/network_policy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e0effc809597979a1cdb01c636f868c63574f617
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/templates/network_policy.yaml
@@ -0,0 +1,66 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if not (.Values.networkPolicy).disabled }} 
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+  name: network-policy-bayernid-proxy
+  namespace: {{ .Release.Namespace }}
+spec:
+  podSelector:
+    matchLabels:
+      component: bayernid-proxy
+  policyTypes:
+    - Ingress
+    - Egress
+  ingress:
+  - ports:
+    - port: 9090
+    from:
+    - podSelector: 
+        matchLabels:
+          component: vorgang-manager
+{{- with (.Values.networkPolicy).additionalIngressConfig }}
+{{ toYaml . | indent 2 }}
+{{- end }}
+  egress:
+  - to:
+    - namespaceSelector:
+        matchLabels:
+          kubernetes.io/metadata.name: {{ required "networkPolicy.dnsServerNamespace must be set" (.Values.networkPolicy).dnsServerNamespace }}
+    ports:
+      - port: 53
+        protocol: UDP
+      - port: 53
+        protocol: TCP
+      - port: 5353
+        protocol: UDP
+      - port: 5353
+        protocol: TCP
+{{- with (.Values.networkPolicy).additionalEgressConfig }}
+{{ toYaml . | indent 2 }}
+{{- end }}
+
+{{- end }}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/main/helm/templates/service.yaml b/nachrichten-bayernid-proxy/src/main/helm/templates/service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..082882cebb0855f66aa58cb792c5fbc86f8b086b
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/templates/service.yaml
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{.Release.Name }}
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+spec:
+  type: ClusterIP
+  ports:
+    - name: grpc-9090
+      port: 9090
+      protocol: TCP
+    - name: metrics
+      port: 8081
+      protocol: TCP
+  selector:
+    {{- include "app.matchLabels" . | indent 4 }}
diff --git a/nachrichten-bayernid-proxy/src/main/helm/templates/service_account.yaml b/nachrichten-bayernid-proxy/src/main/helm/templates/service_account.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..231d53f52dfe67b27f474ebf552d1e10a052f042
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/templates/service_account.yaml
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if (.Values.serviceAccount).create }}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "app.serviceAccountName" . }}
+  namespace: {{ .Release.Namespace }}
+{{- end }}
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/main/helm/values.yaml b/nachrichten-bayernid-proxy/src/main/helm/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..da920667057f20433f288ebb77a286279de8d29a
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/main/helm/values.yaml
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+
+replicaCount: 2
+
+
+image:
+  repo: docker.ozg-sh.de
+  name: bayernid-proxy
+  tag: latest # [default: latest]
+
+    
+vorgangmanagerName: vorgang-manager
+
+imagePullSecret: ozgcloud-image-pull-secret
+
+
diff --git a/nachrichten-bayernid-proxy/src/test/helm-linter-values.yaml b/nachrichten-bayernid-proxy/src/test/helm-linter-values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7712c51e4039964b81fab40d1f84ebad68cf7f10
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm-linter-values.yaml
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+ozgcloud:
+  environment: test
+  bayernid:
+      server: "https://test"
+      certificateSecretName: "bayernidCertificat"
+
+networkPolicy:
+  dnsServerNamespace: test-dns-namespace
+
diff --git a/nachrichten-bayernid-proxy/src/test/helm/configmap_bindings_type_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/configmap_bindings_type_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1c592b4972fa231b2f49a1e0e0c66ca5779c25af
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/configmap_bindings_type_test.yaml
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: Certificate ConfigMap Binding
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/configmap_bindings_type.yaml
+tests:
+  - it: validate configMap values
+    asserts:
+      - isKind:
+          of: ConfigMap
+      - equal:
+          path: metadata.name
+          value: bindings-type
+      - equal:
+          path: metadata.namespace
+          value: sh-helm-test
+      - equal:
+          path: data
+          value:
+            type: | 
+              ca-certificates
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_actuator_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_actuator_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f038b3eac3ead8efde98c54eeaa988f8b8a6c093
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_actuator_test.yaml
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment actuator 
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: testIsDeployment
+    template: deployment.yaml
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe
+          value:
+            failureThreshold: 3
+            httpGet:
+              path: /actuator/health/readiness
+              port: 8081
+              scheme: HTTP
+            periodSeconds: 10
+            successThreshold: 1
+            timeoutSeconds: 3
+      - equal: 
+          path: spec.template.spec.containers[0].startupProbe
+          value: 
+            httpGet:
+              path: /actuator/health/readiness
+              port: 8081
+              scheme: HTTP
+            failureThreshold: 10
+            initialDelaySeconds: 20
+            periodSeconds: 10
+            successThreshold: 1
+            timeoutSeconds: 5    
+        
+
+
+
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_bayernid_certificate_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_bayernid_certificate_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..70bd21da3534b32163c0d61c1e0b24e6e5b993b9
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_bayernid_certificate_test.yaml
@@ -0,0 +1,114 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test bayernid certificate
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "https://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should contains bayernid server
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_bayernid_server
+            value: "https://test"
+
+  - it: should fail when bayernid server not set 
+    set: 
+      ozgcloud:
+        environment: dev
+        bayernid:
+          server: ""
+    asserts:
+      - failedTemplate:
+          errorMessage: "ozgcloud.bayernid.server must be set"
+
+
+  - it: should set variable keystore certificate
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_ssl_bundle_jks_bayern-id-ca_keystore_location
+            value: /keystore/bayernid/bayern-id-ca.p12
+
+  - it: should set variable keystore type
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_ssl_bundle_jks_bayern-id-ca_keystore_type
+            value: PKCS12
+
+  - it: should set variable keystore password secret reference
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_ssl_bundle_jks_bayern-id-ca_keystore_password
+            valueFrom:
+              secretKeyRef:
+                name: bayernidCertificat
+                key: password
+                optional: false
+
+  - it: should fail when secret name for bayernid certificat is not set
+    set: 
+      ozgcloud:
+        environment: dev
+        bayernid:
+          server: "bayernIdServer"
+          certificateSecretName:
+    asserts:
+      - failedTemplate:
+          errorMessage: "ozgcloud.bayernid.certificateSecretName must be set"
+
+  - it: should have volumeMount for bayernid certificate keystore
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: bayern-id-ca
+            mountPath: "/keystore/bayernid/bayern-id-ca.p12"
+            subPath: zertifikat
+            readOnly: true
+
+  - it: should have volume for bayernid certificate keystore
+    asserts:
+      - contains:
+           path: spec.template.spec.volumes
+           content:
+              name: bayern-id-ca
+              secret:
+                 secretName: bayernidCertificat
+                 optional: false
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_bindings_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_bindings_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c33535a5a9e6a89ca8072f1025d14fed02ed98e3
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_bindings_test.yaml
@@ -0,0 +1,72 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment bayernid-proxy bindings
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should have volumeMounts for temp folder
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: temp-dir
+            mountPath: "/tmp"
+            
+  - it: should have volume for temp folder
+    asserts:
+      - contains:
+           path: spec.template.spec.volumes
+           content:
+              name: temp-dir
+              emptyDir: {}
+
+  - it: should have bindings-type volume
+    asserts:
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: bindings
+            configMap:
+              name: bindings-type  
+
+  - it: should have bindings-type volumeMount
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: bindings
+            mountPath: "/bindings/ca-certificates/type"
+            subPath: type
+            readOnly: true
+                
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_container_basic_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_container_basic_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ac4a183d4641c93464f43c39673d898398153a1d
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_container_basic_test.yaml
@@ -0,0 +1,64 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment container basics
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should have correct values for container image, name, imagePullPolicy
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].image
+          value: docker.ozg-sh.de/bayernid-proxy:latest
+      - equal:
+          path: spec.template.spec.containers[0].name
+          value: bayernid-proxy
+      - equal: 
+          path: spec.template.spec.containers[0].imagePullPolicy
+          value: Always
+  - it: should have correct values for container ports
+    asserts:
+      - contains: 
+          path: spec.template.spec.containers[0].ports
+          content:  
+            containerPort: 9090
+            name: grpc-9090
+            protocol: TCP
+      - contains: 
+          path: spec.template.spec.containers[0].ports
+          content:  
+            containerPort: 8081
+            name: metrics
+            protocol: TCP
+            
+            
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_container_other_values_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_container_other_values_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..af6154ac5d2168678e012c9b9d193894cafe9378
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_container_other_values_test.yaml
@@ -0,0 +1,76 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+   
+   #
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment container other values
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should have correct values for container terminationMessagePolicy, terminationMessagePath, stdin, tty
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].terminationMessagePolicy
+          value: File
+      - equal:
+          path: spec.template.spec.containers[0].terminationMessagePath
+          value: /dev/termination-log
+      - equal: 
+          path: spec.template.spec.containers[0].stdin
+          value: true
+      - equal: 
+          path: spec.template.spec.containers[0].tty
+          value: true
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_container_security_context_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_container_security_context_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8d56527831ac4e3630a14cddb34b45f934489254
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_container_security_context_test.yaml
@@ -0,0 +1,69 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment container security context
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: check default values
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.privileged
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.runAsNonRoot
+          value: true
+      - isNull:
+          path: spec.template.spec.containers[0].securityContext.runAsUser
+      - isNull:
+          path: spec.template.spec.containers[0].securityContext.runAsGroup
+  - it: check runAsUser
+    set:
+      securityContext.runAsUser: 1000
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.runAsUser
+          value: 1000
+  - it: check runAsGroup
+    set:
+      securityContext.runAsGroup: 1000
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.runAsGroup
+          value: 1000
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_defaults_labels_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_defaults_labels_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0d8eea9255c23c13e927aafe54f18cb970693b70
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_defaults_labels_test.yaml
@@ -0,0 +1,75 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment default labels
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: check metadata.labels
+    asserts:
+      - equal:
+          path: metadata.labels
+          value:
+            app.kubernetes.io/instance: bayernid-proxy
+            app.kubernetes.io/managed-by: Helm
+            app.kubernetes.io/name: bayernid-proxy
+            app.kubernetes.io/namespace: sh-helm-test
+            app.kubernetes.io/part-of: ozgcloud
+            app.kubernetes.io/version: 0.0.0-MANAGED-BY-JENKINS
+            helm.sh/chart: bayernid-proxy-0.0.0-MANAGED-BY-JENKINS
+            app.kubernetes.io/component: bayernid-proxy
+            component: bayernid-proxy
+  
+  - it: should set spec.selector.matchLabels
+    asserts:
+      - equal:
+          path: spec.selector.matchLabels
+          value:
+            app.kubernetes.io/name: bayernid-proxy
+            app.kubernetes.io/namespace: sh-helm-test
+            component: bayernid-proxy
+
+  - it: should have correct deyploment spec.template.metadata.labels
+    asserts:
+      - equal:
+          path: spec.template.metadata.labels
+          value: 
+            app.kubernetes.io/instance: bayernid-proxy
+            app.kubernetes.io/managed-by: Helm
+            app.kubernetes.io/name: bayernid-proxy
+            app.kubernetes.io/namespace: sh-helm-test
+            app.kubernetes.io/part-of: ozgcloud
+            app.kubernetes.io/version: 0.0.0-MANAGED-BY-JENKINS
+            helm.sh/chart: bayernid-proxy-0.0.0-MANAGED-BY-JENKINS
+            app.kubernetes.io/component: bayernid-proxy
+            component: bayernid-proxy
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_env_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_env_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b633ee6fa180d9cfc2196f98a946ccdd5273269d
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_env_test.yaml
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment container environments 
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "https://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: check customList
+    set:
+      env.customList:
+        - name: my_test_environment_name
+          value: "A test value"
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
+
+  - it: check customList test value is not set by default
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_imagepull_secret_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_imagepull_secret_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c7a633acf37fded5b2d12c0a491bb3153f446073
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_imagepull_secret_test.yaml
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment image pull secret
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should use correct imagePull secret
+    asserts:
+      - equal:
+          path: spec.template.spec.imagePullSecrets[0].name
+          value: ozgcloud-image-pull-secret
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_ozgcloud_base_values_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_ozgcloud_base_values_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5f6befa7afe562e1b3d99b8fe128ea136e5626bf
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_ozgcloud_base_values_test.yaml
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test ozgcloud base values
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+
+tests:
+
+  - it: should fail on missing environment
+    asserts:
+      - failedTemplate:
+          errorMessage: ozgcloud.environment muss angegeben sein
+  - it: should not fail on not missing environment
+    set:
+      ozgcloud:
+        environment: dev
+        bayernid:
+          server: "http://test"
+          certificateSecretName: "bayernidCertificat"
+    asserts:
+      - notFailedTemplate: {}
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_resources_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_resources_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..39bcbe62a6e412165037f24d40faf611c5910f46
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_resources_test.yaml
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment container resources
+release:
+  name: bayernid-proxy
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should generate resources when values set
+    set:
+      resources:
+        limits:
+          cpu: 11m
+          memory: 22Mi
+        requests:
+          cpu: 33m
+          memory: 44Mi
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.cpu
+          value: 11m
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.memory
+          value: 22Mi
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.cpu
+          value: 33m
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.memory
+          value: 44Mi
+  - it: should not generate resources when values not set
+    asserts:
+      - isEmpty:
+          path: spec.template.spec.containers[0].resources
+
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_service_account_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_service_account_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..334d3f74c55057973868eefe40e1977ffe32b7de
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_service_account_test.yaml
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment service account
+release:
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should use service account with default name
+    set:
+      serviceAccount:
+        create: true
+    asserts:
+      - equal:
+          path: spec.template.spec.serviceAccountName
+          value: bayernid-proxy-service-account
+  - it: should use service account with name
+    set:
+      serviceAccount:
+        create: true
+        name: helm-service-account
+    asserts:
+      - equal:
+          path: spec.template.spec.serviceAccountName
+          value: helm-service-account
+  - it: should use default service account
+    asserts:
+      - isNull:
+          path: spec.template.spec.serviceAccountName
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_springProfile_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_springProfile_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..20838079c916477b2dc50031fa9c4f1d3e09e136
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_springProfile_test.yaml
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment spring profiles
+release:
+  name: bayernid-proxy
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should override spring profiles
+    set:
+      env.overrideSpringProfiles: oc,stage,ea
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc,stage,ea
+  - it: should generate spring profiles 
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc, dev
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deployment_template_other_values_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deployment_template_other_values_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5d54017f81715f8325c59f9c6ae4e0bf44fdef27
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deployment_template_other_values_test.yaml
@@ -0,0 +1,81 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment template other values
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+tests:
+  - it: should have correct spec.template.spec.topologySpreadConstraints values 
+    asserts: 
+      - contains:
+          path: spec.template.spec.topologySpreadConstraints
+          content: 
+            maxSkew: 1
+            topologyKey: kubernetes.io/hostname
+            whenUnsatisfiable: ScheduleAnyway
+            labelSelector:
+              matchLabels:
+                app.kubernetes.io/name: bayernid-proxy
+  - it: should have correct deployment spec.template.spec.dnsConfig dnsPolicy restartPolicy schedulerName and terminationGracePeriodSeconds values 
+    asserts:
+      - equal:
+          path: spec.template.spec.dnsConfig
+          value: {}
+      - equal:
+          path: spec.template.spec.dnsPolicy
+          value: ClusterFirst
+      - equal:
+          path: spec.template.spec.restartPolicy
+          value: Always
+      - equal:
+          path: spec.template.spec.terminationGracePeriodSeconds
+          value: 30
+      - equal:
+          path: spec.template.spec.schedulerName
+          value: default-scheduler
+  - it: should not generate spec.template.spec.hostAlias when values set
+    set: 
+      hostAliases: test-alias
+    asserts:
+      - equal:
+          path: spec.template.spec.hostAliases 
+          value: test-alias
+    
+    
+  - it: should not generate spec.template.spec.hostAlias when values not set
+    asserts:
+      - isNull:
+          path: spec.template.spec.hostAliases 
+         
+      
+      
diff --git a/nachrichten-bayernid-proxy/src/test/helm/deyploment_general_value_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/deyploment_general_value_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8df0a6a816fea0314d45234d956a043a7d0d7329
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/deyploment_general_value_test.yaml
@@ -0,0 +1,78 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment general values
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      server: "http://test"
+      certificateSecretName: "bayernidCertificat"
+
+tests:
+  - it: should have correct apiVersion
+    asserts:
+      - isKind:
+          of: Deployment
+      - isAPIVersion:
+           of: "apps/v1"
+    
+  
+  - it: should have correct deployment metadata 
+    asserts: 
+      - equal:
+          path: metadata.name
+          value: bayernid-proxy
+      - equal: 
+          path: metadata.namespace
+          value: sh-helm-test
+
+
+  - it: should have correct deyployment general spec values
+    asserts:
+      - equal:
+          path: spec.progressDeadlineSeconds
+          value: 600
+      - equal:
+          path: spec.replicas
+          value: 2
+      - equal:
+          path: spec.revisionHistoryLimit
+          value: 10
+  - it: should have correct deployment spec strategy values
+    asserts:
+      - equal: 
+          path: spec.strategy
+          value: 
+            rollingUpdate:
+              maxSurge: 1
+              maxUnavailable: 0
+            type: RollingUpdate
+          
+
diff --git a/nachrichten-bayernid-proxy/src/test/helm/network_policy_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/network_policy_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7382ad0947be9db238ff1b5d7f9de08439716165
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/network_policy_test.yaml
@@ -0,0 +1,163 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: network policy test
+release:
+  namespace: by-helm-test
+templates:
+  - templates/network_policy.yaml
+tests:
+  - it: should match apiVersion
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - isAPIVersion:
+          of: networking.k8s.io/v1
+
+  - it: should match kind
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - isKind:
+          of: NetworkPolicy
+
+  - it: should match metadata
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - equal:
+          path: metadata
+          value:
+            name: network-policy-bayernid-proxy
+            namespace: by-helm-test
+
+  - it: should generate spec
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - equal:
+          path: spec
+          value:
+            podSelector:
+              matchLabels:
+                component: bayernid-proxy
+            policyTypes:
+              - Ingress
+              - Egress
+            ingress:
+            - ports:
+              - port: 9090
+              from:
+              - podSelector: 
+                  matchLabels:
+                    component: vorgang-manager
+            egress:
+            - to:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: test-dns-namespace
+              ports:
+                - port: 53
+                  protocol: UDP
+                - port: 53
+                  protocol: TCP
+                - port: 5353
+                  protocol: UDP
+                - port: 5353
+                  protocol: TCP
+
+  - it: add ingress rule by values
+    set:
+      networkPolicy:
+        ssoPublicIp: 51.89.117.53/32
+        dnsServerNamespace: test-namespace-dns
+        additionalIngressConfig:
+        - from:
+          - podSelector: 
+              matchLabels:
+                component: client2
+    asserts:
+      - contains:
+          path: spec.ingress
+          content:
+            from:
+            - podSelector: 
+                matchLabels:
+                  component: client2
+
+  - it: add egress rules by values
+    set:
+      networkPolicy:
+        additionalEgressConfig:
+        - to:
+          - ipBlock:
+              cidr: 1.2.3.4/32
+        - to:
+          - podSelector:
+              matchLabels:
+                component: ozg-testservice
+          ports:
+            - port: 12345
+              protocol: TCP
+
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+    - contains:
+        path: spec.egress
+        content:
+          to:
+          - ipBlock:
+              cidr: 1.2.3.4/32
+    - contains:
+        path: spec.egress
+        content:
+          to:
+          - podSelector:
+              matchLabels:
+                component: ozg-testservice
+          ports:
+            - port: 12345
+              protocol: TCP
+
+  - it: test network policy disabled
+    set:
+      networkPolicy:
+        disabled: true
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - hasDocuments:
+          count: 0
+
+  - it: test network policy unset should be disabled
+    set:
+      networkPolicy:
+        disabled: false
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - hasDocuments:
+          count: 1
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/service_account_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/service_account_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..41565540d17ddc7998397ff62407b0e5bdf7c249
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/service_account_test.yaml
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test service account
+release:
+  namespace: sh-helm-test
+templates:
+  - templates/service_account.yaml
+tests:
+  - it: should create service account with default name
+    set:
+      serviceAccount:
+        create: true
+    asserts:
+      - isKind:
+          of: ServiceAccount
+      - isAPIVersion:
+           of: v1
+      - equal:
+          path: metadata.name
+          value: bayernid-proxy-service-account
+      - equal:
+          path: metadata.namespace
+          value: sh-helm-test
+
+  - it: should create service account with name
+    set:
+      serviceAccount:
+        create: true
+        name: helm-service-account
+    asserts:
+      - isKind:
+          of: ServiceAccount
+      - equal:
+          path: metadata.name
+          value: helm-service-account
+      - equal:
+          path: metadata.namespace
+          value: sh-helm-test
+
+  - it: should not create service account
+    asserts:
+      - hasDocuments:
+         count: 0
\ No newline at end of file
diff --git a/nachrichten-bayernid-proxy/src/test/helm/service_test.yaml b/nachrichten-bayernid-proxy/src/test/helm/service_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2953b478151ed080a3cfe6d771c095726cac2385
--- /dev/null
+++ b/nachrichten-bayernid-proxy/src/test/helm/service_test.yaml
@@ -0,0 +1,85 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test service
+release:
+  name: bayernid-proxy
+  namespace: sh-helm-test
+templates:
+  - templates/service.yaml
+tests:
+  - it: should have the label component with correct value 
+    asserts:
+      - isKind:
+          of: Service
+      - isAPIVersion:
+           of: v1
+      - equal:
+          path: metadata.labels.component
+          value: bayernid-proxy
+  - it: should be of type ClusterIP
+    asserts:
+      - equal:
+          path: spec.type
+          value: ClusterIP
+  - it: ports should contain the grpc port
+    asserts:
+      - contains:
+          path: spec.ports
+          content:
+            name: grpc-9090
+            port: 9090
+            protocol: TCP
+          count: 1
+          any: true
+  - it: ports should contain the metrics port
+    asserts:
+      - contains:
+          path: spec.ports
+          content:
+            name: metrics
+            port: 8081
+            protocol: TCP
+          count: 1
+          any: true
+  - it: selector should contain the component label with correct value
+    asserts:
+      - equal:
+          path: spec.selector.component
+          value: bayernid-proxy
+
+  - it: selector should contain helm recommended labels name and namespace
+    asserts:
+      - equal:
+          path: spec.selector
+          value:
+            app.kubernetes.io/name: bayernid-proxy
+            app.kubernetes.io/namespace: sh-helm-test
+            component: bayernid-proxy
+
+  - it: check component label for service
+    asserts:
+      - equal:
+          path: metadata.labels["component"]
+          value: bayernid-proxy
\ No newline at end of file
diff --git a/nachrichten-manager/lombok.config b/nachrichten-manager/lombok.config
new file mode 100644
index 0000000000000000000000000000000000000000..81661f0fd9c5f6e2f40f39aa9ee13f7017fc2726
--- /dev/null
+++ b/nachrichten-manager/lombok.config
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+lombok.log.fieldName=LOG
+lombok.log.slf4j.flagUsage = ERROR
+lombok.log.log4j.flagUsage = ERROR
+lombok.data.flagUsage = ERROR
+lombok.nonNull.exceptionType = IllegalArgumentException
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
diff --git a/mail-service/pom.xml b/nachrichten-manager/pom.xml
similarity index 55%
rename from mail-service/pom.xml
rename to nachrichten-manager/pom.xml
index 89d1ab89399259585539627cc0f55521ebbab5c5..321d63736f1a8a68d24ce315a851e8b61ffd56ed 100644
--- a/mail-service/pom.xml
+++ b/nachrichten-manager/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -24,34 +24,64 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 
 	<parent>
-		<groupId>de.itvsh.kop.common</groupId>
-		<artifactId>kop-common-parent</artifactId>
-		<version>1.2.1</version>
-		<relativePath />
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-parent</artifactId>
+		<version>3.0.1</version>
+		<relativePath/>
 	</parent>
 
-	<groupId>de.itvsh.ozg.mail</groupId>
-	<artifactId>mail-service</artifactId>
-	<version>1.0.0</version>
+	<groupId>de.ozgcloud.nachrichten</groupId>
+	<artifactId>nachrichten-manager</artifactId>
+	<version>2.4.0</version>
+	<name>OZG-Cloud Nachrichten Manager</name>
 
 	<properties>
 		<java.version>17</java.version>
 		<!-- TODO version management -->
 		<shedlock.version>4.25.0</shedlock.version>
 		<logcaptor.version>2.7.10</logcaptor.version>
+		<ozgcloud.license.version>1.6.0</ozgcloud.license.version>
+		<jaxb-maven-plugin.version>3.0.1</jaxb-maven-plugin.version>
+		<ozg-info-manager-interface.version>0.1.0-SNAPSHOT</ozg-info-manager-interface.version>
+		<bayernid-proxy-interface.version>0.1.0</bayernid-proxy-interface.version>
 	</properties>
 
 	<dependencies>
 		<dependency>
-			<groupId>de.itvsh.ozg.pluto</groupId>
-			<artifactId>pluto-interface</artifactId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-base</artifactId>
 			<version>${project.version}</version>
 		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-interface</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.command</groupId>
+			<artifactId>command-manager</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-utils</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.nachrichten</groupId>
+			<artifactId>bayernid-proxy-interface</artifactId>
+			<version>${bayernid-proxy-interface.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>de.ozgcloud.info</groupId>
+			<artifactId>info-manager-interface</artifactId>
+			<version>${ozg-info-manager-interface.version}</version>
+		</dependency>
 
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
@@ -74,6 +104,15 @@
 			<artifactId>spring-boot-starter-validation</artifactId>
 		</dependency>
 
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web-services</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.glassfish.jaxb</groupId>
+			<artifactId>jaxb-runtime</artifactId>
+		</dependency>
 
 		<dependency>
 			<groupId>net.javacrumbs.shedlock</groupId>
@@ -107,8 +146,12 @@
 			<artifactId>commons-lang3</artifactId>
 		</dependency>
 		<dependency>
-			<groupId>org.apache.httpcomponents</groupId>
-			<artifactId>httpclient</artifactId>
+			<groupId>org.apache.httpcomponents.client5</groupId>
+			<artifactId>httpclient5</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>commons-beanutils</groupId>
+			<artifactId>commons-beanutils</artifactId>
 		</dependency>
 
 		<!-- DEV -->
@@ -142,6 +185,13 @@
 			<version>${logcaptor.version}</version>
 			<scope>test</scope>
 		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-base</artifactId>
+			<version>${project.version}</version>
+			<type>test-jar</type>
+			<scope>test</scope>
+		</dependency>
 	</dependencies>
 
 	<build>
@@ -166,6 +216,40 @@
 				</executions>
 			</plugin>
 
+			<plugin>
+				<groupId>org.jvnet.jaxb</groupId>
+				<artifactId>jaxb-maven-plugin</artifactId>
+				<version>${jaxb-maven-plugin.version}</version>
+				<configuration>
+					<schemas>
+						<schema>
+							<fileset>
+								<directory>${basedir}/src/main/resources/bayernid</directory>
+								<includes>
+									<include>*.wsdl</include>
+								</includes>
+							</fileset>
+						</schema>
+						<schema>
+							<fileset>
+								<directory>${basedir}/src/main/resources/bayernid</directory>
+								<includes>
+									<include>*.xsd</include>
+								</includes>
+							</fileset>
+						</schema>
+					</schemas>
+					<episode>false</episode>
+				</configuration>
+				<executions>
+					<execution>
+						<goals>
+							<goal>generate</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-compiler-plugin</artifactId>
@@ -187,6 +271,33 @@
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-surefire-plugin</artifactId>
 			</plugin>
+
+			<plugin>
+				<groupId>com.mycila</groupId>
+				<artifactId>license-maven-plugin</artifactId>
+				<configuration>
+					<mapping>
+						<config>SCRIPT_STYLE</config>
+					</mapping>
+					<licenseSets>
+						<licenseSet>
+							<header>license/eupl_v1_2_de/header.txt</header>
+							<excludes>
+								<exclude>**/README</exclude>
+								<exclude>src/test/resources/**</exclude>
+								<exclude>src/main/resources/**</exclude>
+							</excludes>
+						</licenseSet>
+					</licenseSets>
+				</configuration>
+				<dependencies>
+					<dependency>
+						<groupId>de.ozgcloud.common</groupId>
+						<artifactId>ozgcloud-common-license</artifactId>
+						<version>${ozgcloud.license.version}</version>
+					</dependency>
+				</dependencies>
+			</plugin>
 		</plugins>
 	</build>
 
@@ -202,4 +313,4 @@
 			<url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url>
 		</snapshotRepository>
 	</distributionManagement>
-</project>
\ No newline at end of file
+</project>
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/NachrichtenManagerProperties.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/NachrichtenManagerProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..5ed6c0421991a58872531e359024b04e9776a831
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/NachrichtenManagerProperties.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Configuration
+@ConfigurationProperties(prefix = "ozgcloud.nachrichten-manager")
+@Setter
+@Getter
+public class NachrichtenManagerProperties {
+
+	private String url;
+}
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeRemoteService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeRemoteService.java
similarity index 81%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeRemoteService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeRemoteService.java
index 25dfbcc9f145b073da9b1a29b8e727913552c38e..099d97614e6fdd17c33326e24c42bb62351a6478 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeRemoteService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeRemoteService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,16 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.attributes;
+package de.ozgcloud.nachrichten.attributes;
 
 import org.springframework.stereotype.Service;
 
-import de.itvsh.ozg.mail.common.grpc.NachrichtenCallContextAttachingInterceptor;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttributeValue;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcSetClientAttributeRequest;
+import de.ozgcloud.nachrichten.common.grpc.NachrichtenCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcAccessPermission;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttribute;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttributeValue;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcSetClientAttributeRequest;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @Service
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeService.java
similarity index 94%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeService.java
index 971563247a02d8f8082d71d10dc145db422eaf3f..4046f7f45587e46c5d48f7b5ee55fc71ffaa7e04 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.attributes;
+package de.ozgcloud.nachrichten.attributes;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeTestFactory.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeTestFactory.java
similarity index 90%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeTestFactory.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeTestFactory.java
index a8a6aa8984d32a0ef41b4a9824b1c1390965fffa..2162b80e619b31b56a3d26edb9c9429fa2992c2a 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/attributes/ClientAttributeTestFactory.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/attributes/ClientAttributeTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.attributes;
+package de.ozgcloud.nachrichten.attributes;
 
 public class ClientAttributeTestFactory {
 
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/common/errorhandling/FunctionalException.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/errorhandling/FunctionalException.java
similarity index 90%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/common/errorhandling/FunctionalException.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/errorhandling/FunctionalException.java
index 8baeb15b17002022d57690fa19e871805d3a8953..08afd948b627e5dcfebf77a99e4f1984984820ba 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/common/errorhandling/FunctionalException.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/errorhandling/FunctionalException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.common.errorhandling;
+package de.ozgcloud.nachrichten.common.errorhandling;
 
 public class FunctionalException extends RuntimeException {
 
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/common/errorhandling/TechnicalException.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/errorhandling/TechnicalException.java
similarity index 84%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/common/errorhandling/TechnicalException.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/errorhandling/TechnicalException.java
index 4bc628214156bdac7a5c82fdedeb93edf237e839..0620d844821a13eb18a860572cd2926a30f7319a 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/common/errorhandling/TechnicalException.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/errorhandling/TechnicalException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.common.errorhandling;
+package de.ozgcloud.nachrichten.common.errorhandling;
 
-@Deprecated /** please use {@link de.itvsh.kop.common.errorhandling.TechnicalException} */
+@Deprecated /** please use {@link de.ozgcloud.common.errorhandling.TechnicalException} */
 public class TechnicalException extends RuntimeException {
 
 	private static final long serialVersionUID = 1L;
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/common/grpc/NachrichtenCallContextAttachingInterceptor.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptor.java
similarity index 87%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/common/grpc/NachrichtenCallContextAttachingInterceptor.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptor.java
index d6867de7812614932c05d16f0f26c8b33a1d885c..d94e5382aec3ef54307b56e303b44efd3600fdd1 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/common/grpc/NachrichtenCallContextAttachingInterceptor.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.common.grpc;
+package de.ozgcloud.nachrichten.common.grpc;
+
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
 
 import java.util.UUID;
 
@@ -31,7 +33,6 @@ import io.grpc.ClientCall;
 import io.grpc.ClientInterceptor;
 import io.grpc.ForwardingClientCall.SimpleForwardingClientCall;
 import io.grpc.Metadata;
-import io.grpc.Metadata.Key;
 import io.grpc.MethodDescriptor;
 
 public class NachrichtenCallContextAttachingInterceptor implements ClientInterceptor {
@@ -40,7 +41,7 @@ public class NachrichtenCallContextAttachingInterceptor implements ClientInterce
 	static final String KEY_CLIENT_NAME = "CLIENT_NAME-bin";
 	static final String KEY_REQUEST_ID = "REQUEST_ID-bin";
 
-	public static final String NACHRICHTEN_MANAGER_CLIENT_NAME = "KopNachrichtenManager";
+	public static final String NACHRICHTEN_MANAGER_CLIENT_NAME = "OzgCloud_NachrichtenManager";
 	static final String NACHRICHTEN_MANAGER_SENDER_USER_ID = "system-nachrichten_manager-sender";
 
 	// <A> = Request, <B> = Response
@@ -78,9 +79,4 @@ public class NachrichtenCallContextAttachingInterceptor implements ClientInterce
 
 	}
 
-	// TODO move to common grpc utils
-	public static Key<byte[]> createKeyOf(String key) {
-		return Key.of(key, Metadata.BINARY_BYTE_MARSHALLER);
-	}
-
 }
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/email/EMailService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/EMailService.java
similarity index 93%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/email/EMailService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/EMailService.java
index 63f0afbb546fadefaac2c47a9ab49ba7f17fb721..cb67b46db5453b9f2b343e6c53626ca9bb1fbdf5 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/email/EMailService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/EMailService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import java.util.Objects;
 
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
@@ -36,8 +33,10 @@ import org.springframework.mail.javamail.JavaMailSender;
 import org.springframework.mail.javamail.MimeMessageHelper;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.ozg.mail.email.MailSendRequest.MailAttachment;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.email.MailSendRequest.MailAttachment;
+import jakarta.mail.MessagingException;
+import jakarta.mail.internet.MimeMessage;
 import lombok.extern.log4j.Log4j2;
 
 @Service
@@ -92,7 +91,7 @@ class EMailService {
 			return mailRecipient.email();
 		}
 		var builder = new StringBuilder();
-		if (StringUtils.isNotEmpty(mailRecipient.firstName())){
+		if (StringUtils.isNotEmpty(mailRecipient.firstName())) {
 			builder.append(mailRecipient.firstName()).append(" ");
 		}
 		if (StringUtils.isNotEmpty(mailRecipient.lastName())) {
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/email/EmailGrpcService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/EmailGrpcService.java
similarity index 90%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/email/EmailGrpcService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/EmailGrpcService.java
index e11c6f4147bed59d47ce49b24c23b735640b768c..f984bbe81f4988110ded8dd729604ead6a695ff9 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/email/EmailGrpcService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/EmailGrpcService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
+
+import java.util.List;
 
-import de.itvsh.ozg.mail.email.MailSendRequest.MailSendRequestBuilder;
-import io.grpc.stub.StreamObserver;
-import net.devh.boot.grpc.server.service.GrpcService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 
-import java.util.List;
+import de.ozgcloud.nachrichten.email.MailSendRequest.MailSendRequestBuilder;
+import io.grpc.stub.StreamObserver;
+import net.devh.boot.grpc.server.service.GrpcService;
 
 @GrpcService
 public class EmailGrpcService extends EmailServiceGrpc.EmailServiceImplBase {
@@ -37,7 +38,7 @@ public class EmailGrpcService extends EmailServiceGrpc.EmailServiceImplBase {
 	@Autowired
 	private MailService mailService;
 
-	@Value("${kop.notification.mail-from}")
+	@Value("${ozgcloud.notification.mail-from}")
 	private String mailFrom;
 
 	@Override
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailRecipient.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailRecipient.java
similarity index 90%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/email/MailRecipient.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailRecipient.java
index b115dbc49eb5267d796654637e60a2eca2e88041..59dded36b6f85feef5cd7c604251d122d25dbc93 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailRecipient.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailRecipient.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import lombok.Builder;
 
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSendErrorEvent.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSendErrorEvent.java
similarity index 92%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSendErrorEvent.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSendErrorEvent.java
index 6883892ade8ee7772b63167e9e34f5d7777d7920..acd550327ab2b861b5d6591275b5ec6147213b5a 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSendErrorEvent.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSendErrorEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import org.springframework.context.ApplicationEvent;
 
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSendRequest.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSendRequest.java
similarity index 91%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSendRequest.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSendRequest.java
index 12e29155c1724804853d0c79066edb688dfc6635..f361127f89e8ad1627bcb29c28ccf83976b26ee5 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSendRequest.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSendRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import java.util.Collection;
 
-import javax.activation.DataSource;
-
+import jakarta.activation.DataSource;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Singular;
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSentEvent.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSentEvent.java
similarity index 92%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSentEvent.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSentEvent.java
index 50eaf09f32bbb5160aef06dc8a387dfa59391c7d..aea4e8ddab5999ea94a439b29fbac01ac5f57f56 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailSentEvent.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailSentEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import org.springframework.context.ApplicationEvent;
 
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailService.java
similarity index 92%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/email/MailService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailService.java
index 68704ba4b399c4a16fe15ea8ec274d3cef5f6c97..53e00933df7bc68ba2807e40fcad6b2a0d3ffa62 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/email/MailService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/email/MailService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/AttachmentFile.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/AttachmentFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..995f3d1209e12d5cd0ae1c7a9776f1bec9c91199
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/AttachmentFile.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import static java.util.Objects.*;
+
+import java.io.InputStream;
+import java.util.function.Supplier;
+
+import lombok.AccessLevel;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.ToString;
+
+@Builder
+@Getter
+@ToString
+public class AttachmentFile {
+	private String name;
+	private String contentType;
+	@Getter(AccessLevel.NONE)
+	@ToString.Exclude
+	private Supplier<InputStream> content;
+
+	public InputStream getContent() {
+		if (isNull(content)) {
+			return InputStream.nullInputStream();
+		}
+		return content.get();
+	}
+
+}
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/BinaryFileService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/BinaryFileService.java
similarity index 91%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/BinaryFileService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/BinaryFileService.java
index 75942f26e28a7dd08cfbfc53c750fd0c298d5244..f6a1c0fcffd6ec65cfc74da9f084420e756bd22f 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/BinaryFileService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/BinaryFileService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import java.io.InputStream;
 
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/FileId.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/FileId.java
similarity index 89%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/FileId.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/FileId.java
index c596e384195ac4e8cc947ad5ff946ca32f976399..3c8e6f07a5b2f6a23468f583682624f2a0e08a8f 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/FileId.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/FileId.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import java.util.UUID;
 
-import de.itvsh.kop.common.datatype.StringBasedValue;
+import de.ozgcloud.common.datatype.StringBasedValue;
 import lombok.EqualsAndHashCode;
 
 @EqualsAndHashCode(callSuper = true)
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachNachrichtMapper.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachNachrichtMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..775675f16f86af04b95ea21246d8d08d6ea7970d
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachNachrichtMapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+
+@Mapper(uses = GrpcObjectMapper.class)
+public interface GrpcPostfachNachrichtMapper {
+
+	@Mapping(target = "attachments", source = "attachmentList")
+	@Mapping(target = "createdAt", ignore = true)
+	@Mapping(target = "createdBy", ignore = true)
+	@Mapping(target = "direction", constant = "OUT")
+	@Mapping(target = "messageCode", ignore = true)
+	@Mapping(target = "messageId", ignore = true)
+	@Mapping(target = "postfachId", ignore = true)
+	@Mapping(target = "sentAt", ignore = true)
+	@Mapping(target = "sentSuccessful", ignore = true)
+	@Mapping(target = "vorgangId", ignore = true)
+	PostfachNachricht mapFromGrpc(GrpcPostfachNachricht nachricht);
+
+	default PostfachAddressIdentifier map(GrpcObject value) {
+		return StringBasedIdentifier.builder().postfachId(value.getProperty(0).getValue(0)).build();
+	}
+}
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/NotConfiguredException.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/NotConfiguredException.java
similarity index 73%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/NotConfiguredException.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/NotConfiguredException.java
index f6650b947fd95c00225a76f498c5cb5234e10721..544d42533837e63fd2ecbab3fc139f3c28db8042 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/NotConfiguredException.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/NotConfiguredException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
-class NotConfiguredException extends OsiPostfachException { // NOSONAR
+public class NotConfiguredException extends PostfachException { // NOSONAR
 
 	private static final long serialVersionUID = 1L;
 
 	public NotConfiguredException() {
-		super("Osi-Postfach is not completely configured. Sending and receiving of postfach mails is not possible.",
-				OsiPostfachMessageCode.SERVER_CONNECTION_FAILED_MESSAGE_CODE);
+		super("Postfach is not completely configured. Sending and receiving of postfach mails is not possible.",
+				PostfachMessageCode.SERVER_CONNECTION_FAILED_MESSAGE_CODE);
 	}
 
 }
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PersistPostfachMailService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PersistPostfachNachrichtService.java
similarity index 81%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PersistPostfachMailService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PersistPostfachNachrichtService.java
index 8c45304ebc8947ef8bae5d73b80a840a75e84d9e..e5936b5f7ac5f6457e20a578f3c08357760278f0 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PersistPostfachMailService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PersistPostfachNachrichtService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,16 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Stream;
 
 //Temporally replacement for usign GRPC Api
-public interface PersistPostfachMailService {
+public interface PersistPostfachNachrichtService {
 
-	void persistMail(Optional<String> userId, PostfachMail mail);
+	void persistNachricht(Optional<String> userId, PostfachNachricht nachricht);
 
 	Stream<Map<String, Object>> findByVorgangAsMap(String vorgangId);
 
@@ -41,5 +41,5 @@ public interface PersistPostfachMailService {
 	Map<String, Object> getById(String itemId);
 
 	// TODO use file id as soon it is available
-	String persistAttachment(String vorgangId, MessageAttachment attachment);
+	String persistAttachment(String vorgangId, AttachmentFile attachment);
 }
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/Postfach.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/Postfach.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f47589b0bcc349b0e373651825f350c07f39b59
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/Postfach.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+class Postfach {
+
+	private String type;
+
+	private boolean isReplyAllowed;
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachAddress.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachAddress.java
new file mode 100644
index 0000000000000000000000000000000000000000..5681a1cb927a57ae7ca6910b0f1dcbd3fc6f337f
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachAddress.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+public class PostfachAddress {
+
+	public static final String VERSION_FIELD = "version";
+	public static final String TYPE_FIELD = "type";
+	public static final String IDENTIFIER_FIELD = "identifier";
+	public static final String SERVICEKONTO_TYPE_FIELD = "serviceKontoType";
+
+	private String version;
+	private int type;
+	private PostfachAddressIdentifier identifier;
+	private String serviceKontoType;
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachAddressIdentifier.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachAddressIdentifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..b237435fdf1dea41e8d22a541d787d7beee90ff8
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachAddressIdentifier.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+public interface PostfachAddressIdentifier {
+
+}
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachBadRequestException.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachBadRequestException.java
similarity index 73%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachBadRequestException.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachBadRequestException.java
index 6b54c44f0fbe9a4c9e161001f45074091f0c7c52..089963102c2445280c89c22e5a8989b2bbc510c3 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachBadRequestException.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachBadRequestException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
-class OsiPostfachBadRequestException extends OsiPostfachException {
+public class PostfachBadRequestException extends PostfachException {
 
 	private static final long serialVersionUID = 1L;
 
-	public OsiPostfachBadRequestException(Throwable cause) {
-		super("Bad-Request Received from OSI-Postfach Server", OsiPostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE, cause);
+	public PostfachBadRequestException(Throwable cause) {
+		super("Bad-Request Received from Postfach Server", PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE, cause);
 	}
 }
\ No newline at end of file
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachEventListener.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachEventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..7928256e519addc144336b5c5cd473545d2b41d8
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachEventListener.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Log4j2
+public class PostfachEventListener {
+
+	private static final String IS_SEND_POSTFACH_NACHRICHT_COMMAND = "{T(de.ozgcloud.nachrichten.postfach.PostfachEventListener).IS_SEND_POSTFACH_NACHRICHT.test(event.getSource())}";
+
+	public static final Predicate<Command> IS_SEND_POSTFACH_NACHRICHT = command -> command.getOrder().equals("SEND_POSTFACH_NACHRICHT");
+
+	@Autowired
+	private PostfachService service;
+
+	@EventListener(condition = IS_SEND_POSTFACH_NACHRICHT_COMMAND)
+	public void sendPostfachNachricht(CommandCreatedEvent event) {
+		var command = event.getSource();
+		try {
+			service.sendMail(command.getId(), command.getCreatedBy(), buildNachricht(command, command.getBodyObject()));
+		} catch (RuntimeException e) {
+			service.publishMailSentFailedEvent(command.getId(), "Error on sending Postfach Nachricht: " + e.getMessage());
+			LOG.error("Error on sending Postfach Nachricht.", e);
+		}
+	}
+
+	private PostfachNachricht buildNachricht(Command command, Map<String, Object> commandBody) {
+		var postfachMailBuilder = PostfachNachricht.builder()
+				.id(isNewNachricht(command) ? null : command.getRelationId())
+				.vorgangId(command.getVorgangId())
+				.postfachId(MapUtils.getString(commandBody, PostfachNachricht.FIELD_POSTFACH_ID))
+				.replyOption(PostfachNachricht.ReplyOption.valueOf(MapUtils.getString(commandBody, PostfachNachricht.FIELD_REPLY_OPTION)))
+				.createdBy(command.getCreatedBy())
+				.direction(Direction.OUT)
+				.subject(MapUtils.getString(commandBody, PostfachNachricht.FIELD_SUBJECT))
+				.mailBody(MapUtils.getString(commandBody, PostfachNachricht.FIELD_MAIL_BODY))
+				.attachments(getStringListValue(commandBody, PostfachNachricht.FIELD_ATTACHMENTS));
+
+		Optional.ofNullable(getPostfachAddress(commandBody)).map(this::buildPostfachAddress).ifPresent(postfachMailBuilder::postfachAddress);
+
+		return postfachMailBuilder.build();
+	}
+
+	private boolean isNewNachricht(Command command) {
+		return Objects.isNull(command.getRelationId()) || StringUtils.equals(command.getVorgangId(), command.getRelationId());
+	}
+
+	private PostfachAddress buildPostfachAddress(Map<String, Object> postfachAddress) {
+		return PostfachAddress.builder()
+				.type(MapUtils.getIntValue(postfachAddress, PostfachAddress.TYPE_FIELD))
+				.version(MapUtils.getString(postfachAddress, PostfachAddress.VERSION_FIELD))
+				.identifier(buildIdentifier(postfachAddress))
+				.serviceKontoType(MapUtils.getString(postfachAddress, PostfachAddress.SERVICEKONTO_TYPE_FIELD))
+				.build();
+	}
+
+	@SuppressWarnings("unchecked")
+	private Map<String, Object> getPostfachAddress(Map<String, Object> commandBody) {
+		return (Map<String, Object>) commandBody.get(PostfachNachricht.POSTFACH_ADDRESS_FIELD);
+	}
+
+	private PostfachAddressIdentifier buildIdentifier(Map<String, Object> postfachAddress) {
+		var identifier = getIdentifier(postfachAddress);
+		return StringBasedIdentifier.builder().postfachId(MapUtils.getString(identifier, PostfachNachricht.FIELD_POSTFACH_ID)).build();
+	}
+
+	@SuppressWarnings("unchecked")
+	private Map<String, Object> getIdentifier(Map<String, Object> postfachAddress) {
+		return (Map<String, Object>) postfachAddress.get(PostfachAddress.IDENTIFIER_FIELD);
+	}
+
+	List<String> getStringListValue(Map<String, Object> commandBody, String fieldName) {
+		return Optional.ofNullable(commandBody.get(fieldName))
+				.map(this::mapObjectToList)
+				.orElse(Collections.emptyList());
+	}
+
+	private List<String> mapObjectToList(Object object) {
+		if (object instanceof Collection<?> objects) {
+			return objects.stream().map(Objects::toString).toList();
+		} else {
+			return List.of(object.toString());
+		}
+	}
+}
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachException.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachException.java
similarity index 70%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachException.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachException.java
index f24953ae69b929d6a13ec251fdf7778fce4058bd..93851e6cc0a8dbb50c7f739c83d5aae2a8a4bed8 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachException.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,23 +21,23 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
-import de.itvsh.ozg.mail.common.errorhandling.TechnicalException;
+import de.ozgcloud.common.errorhandling.TechnicalException;
 import lombok.Getter;
 
-public class OsiPostfachException extends TechnicalException {
+public class PostfachException extends TechnicalException {
 
 	private static final long serialVersionUID = 1L;
 	@Getter
-	private final OsiPostfachMessageCode messageCode;
+	private final PostfachMessageCode messageCode;
 
-	public OsiPostfachException(String message, OsiPostfachMessageCode messageCode) {
+	public PostfachException(String message, PostfachMessageCode messageCode) {
 		super(message);
 		this.messageCode = messageCode;
 	}
 
-	public OsiPostfachException(String message, OsiPostfachMessageCode messageCode, Throwable cause) {
+	public PostfachException(String message, PostfachMessageCode messageCode, Throwable cause) {
 		super(message, cause);
 
 		this.messageCode = messageCode;
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachGrpcService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachGrpcService.java
similarity index 67%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachGrpcService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachGrpcService.java
index d132d1a8b0eadd7bbefa2e4c9a1f569132924801..84ae6393e180c736fe796a16380a194f21264f3c 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachGrpcService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachGrpcService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.ozg.mail.postfach.PostfachServiceGrpc.PostfachServiceImplBase;
+import de.ozgcloud.nachrichten.postfach.PostfachServiceGrpc.PostfachServiceImplBase;
 import io.grpc.stub.StreamObserver;
 import net.devh.boot.grpc.server.service.GrpcService;
 
@@ -35,7 +36,20 @@ class PostfachGrpcService extends PostfachServiceImplBase {
 	@Autowired
 	private PostfachService service;
 	@Autowired
-	private PostfachMailMapper mapper;
+	private PostfachNachrichtMapper mapper;
+	@Autowired
+	private PostfachMapper postfachMapper;
+
+	@Autowired
+	private GrpcPostfachNachrichtMapper nachrichtMapper;
+
+	@Override
+	public void saveNachrichtDraft(GrpcSaveNachrichtDraftRequest request, StreamObserver<GrpcSaveNachrichtDraftResponse> response) {
+		service.saveDraft(request.getVorgangId(), nachrichtMapper.mapFromGrpc(request.getNachricht()));
+
+		response.onNext(GrpcSaveNachrichtDraftResponse.newBuilder().build());
+		response.onCompleted();
+	}
 
 	@Override
 	public void sendPostfachMail(GrpcSendPostfachMailRequest req, StreamObserver<GrpcSendPostfachMailResponse> response) {
@@ -75,4 +89,18 @@ class PostfachGrpcService extends PostfachServiceImplBase {
 		response.onNext(GrpcIsPostfachConfiguredResponse.newBuilder().setIsConfigured(service.isPostfachConfigured()).build());
 		response.onCompleted();
 	}
+
+	@Override
+	public void getPostfachConfig(GrpcGetPostfachConfigRequest request, StreamObserver<GrpcGetPostfachConfigResponse> response) {
+		response.onNext(buildGetPostfachConfigResponse());
+		response.onCompleted();
+	}
+
+	GrpcGetPostfachConfigResponse buildGetPostfachConfigResponse() {
+		var grpcPostfachs = service.getPostfachs().map(postfachMapper::toGrpc).toList();
+		if (CollectionUtils.isEmpty(grpcPostfachs)) {
+			return GrpcGetPostfachConfigResponse.newBuilder().setConfigured(false).build();
+		}
+		return GrpcGetPostfachConfigResponse.newBuilder().setConfigured(true).addAllPostfach(grpcPostfachs).build();
+	}
 }
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailSentEvent.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMailSentEvent.java
similarity index 87%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailSentEvent.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMailSentEvent.java
index 2bdab2222f0cf149aac8678df6d70bec019fe3c7..8e1b821ab953ba9f5d9e4bc08594bde00e068216 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailSentEvent.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMailSentEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
-import de.itvsh.ozg.pluto.command.CommandExecutedEvent;
+import de.ozgcloud.command.CommandExecutedEvent;
 
 public class PostfachMailSentEvent extends CommandExecutedEvent {
 
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailSentFailedEvent.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMailSentFailedEvent.java
similarity index 88%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailSentFailedEvent.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMailSentFailedEvent.java
index bf3d72471e97a2cb90cf88ecc124aaac0b446864..314c217c9e8d1a1314ab8bdb6565f4bd097f3f8d 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMailSentFailedEvent.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMailSentFailedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
-import de.itvsh.ozg.pluto.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
 
 public class PostfachMailSentFailedEvent extends CommandFailedEvent {
 
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMapper.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..ee1555bd9828bd01e0d2bf5807e4905b5ce10917
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMapper.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import org.mapstruct.Mapper;
+
+@Mapper
+public interface PostfachMapper {
+
+	GrpcPostfach toGrpc(Postfach postfach);
+}
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachMessageCode.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java
similarity index 90%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachMessageCode.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java
index fdd91032b775f033365299e452f5a19d6b5363f6..a335f84eebd058212ca0c370e784e78143b5cfac 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachMessageCode.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
 @AllArgsConstructor(access = AccessLevel.PRIVATE)
-enum OsiPostfachMessageCode {
+public enum PostfachMessageCode {
 
 	PROCESS_FAILED_MESSAGE_CODE("postfachnachricht.server.processing_failed"),
 	SERVER_CONNECTION_FAILED_MESSAGE_CODE("postfachnachricht.server.connection_failed"),
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMail.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachricht.java
similarity index 87%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMail.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachricht.java
index 9f93f5e6560caa2c66ac4bd7918bfb0b9b2853a5..77682b44099062650284567b23f313172f9b8dee 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachMail.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachricht.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,25 +21,30 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import java.time.ZonedDateTime;
 import java.util.Collections;
 import java.util.List;
 
-import javax.validation.constraints.NotNull;
-
-import de.itvsh.ozg.mail.postfach.Message.ReplyOption;
+import jakarta.validation.constraints.NotNull;
 import lombok.Builder;
 import lombok.Getter;
 
 @Builder(toBuilder = true)
 @Getter
-public class PostfachMail {
+public class PostfachNachricht {
+
+	public enum ReplyOption {
+		POSSIBLE, MANDATORY, FORBIDDEN
+	}
 
 	public static final String FIELD_ID = "id";
 	public static final String FIELD_VORGANG_ID = "vorgangId";
+
 	public static final String FIELD_POSTFACH_ID = "postfachId";
+	public static final String POSTFACH_ADDRESS_FIELD = "postfachAddress";
+
 	public static final String FIELD_MESSAGE_ID = "messageId";
 	public static final String FIELD_CREATED_AT = "createdAt";
 	public static final String FIELD_CREATED_BY = "createdBy";
@@ -60,6 +65,7 @@ public class PostfachMail {
 
 	private String vorgangId;
 	private String postfachId;
+	private PostfachAddress postfachAddress;
 	private String messageId;
 
 	@Builder.Default
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapper.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb72cb4ce4a8ca77365f3ae480c095fbfbf1d9e7
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapper.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import java.time.ZonedDateTime;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.MappingConstants;
+import org.mapstruct.ReportingPolicy;
+import org.mapstruct.ValueMapping;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction;
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN)
+public abstract class PostfachNachrichtMapper {
+
+	@Autowired
+	private GrpcObjectMapper grpcObjectMapper;
+
+	@Mapping(target = "attachments", source = "attachmentList")
+	@Mapping(target = "createdAt", ignore = true)
+	@Mapping(target = "createdBy", ignore = true)
+	@Mapping(target = "direction", ignore = true)
+	@Mapping(target = "messageId", ignore = true)
+	@Mapping(target = "sentAt", ignore = true)
+	@Mapping(target = "sentSuccessful", ignore = true)
+	@ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL)
+	@ValueMapping(source = "UNDEFINED", target = MappingConstants.NULL)
+	public abstract PostfachNachricht fromGrpcMail(GrpcPostfachMail grpcMail);
+
+	public PostfachAddressIdentifier toPostfachAddressIdentifier(GrpcObject grpcObject) {
+		var postfachId = grpcObject.getPropertyList().get(0).getValue(0);
+		return StringBasedIdentifier.builder().postfachId(postfachId).build();
+	}
+
+	@SuppressWarnings("unchecked")
+	public GrpcPostfachMail fromMap(Map<String, Object> mailMap) {
+		var postfachMailBuilder = GrpcPostfachMail.newBuilder()
+				.setId(MapUtils.getString(mailMap, PostfachNachricht.FIELD_ID))
+				.setVorgangId(MapUtils.getString(mailMap, PostfachNachricht.FIELD_VORGANG_ID))
+				.setPostfachId(MapUtils.getString(mailMap, PostfachNachricht.FIELD_POSTFACH_ID, StringUtils.EMPTY))
+				.setCreatedAt(MapUtils.getString(mailMap, PostfachNachricht.FIELD_CREATED_AT))
+				.setCreatedBy(MapUtils.getString(mailMap, PostfachNachricht.FIELD_CREATED_BY, StringUtils.EMPTY))
+				.setSentAt(MapUtils.getString(mailMap, PostfachNachricht.FIELD_SENT_AT, StringUtils.EMPTY))
+				.setSentSuccessful(MapUtils.getBooleanValue(mailMap, PostfachNachricht.FIELD_SENT_SUCCESSFUL, false))
+				.setMessageCode(MapUtils.getString(mailMap, PostfachNachricht.FIELD_MESSAGE_CODE, StringUtils.EMPTY))
+				.setDirection(GrpcDirection.valueOf(MapUtils.getString(mailMap, PostfachNachricht.FIELD_DIRECTION)))
+				.setSubject(MapUtils.getString(mailMap, PostfachNachricht.FIELD_SUBJECT))
+				.setMailBody(MapUtils.getString(mailMap, PostfachNachricht.FIELD_MAIL_BODY))
+				.setReplyOption(MapUtils.getString(mailMap, PostfachNachricht.FIELD_REPLY_OPTION))
+				.addAllAttachment((Iterable<String>) mailMap.getOrDefault(PostfachNachricht.FIELD_ATTACHMENTS, Collections.emptyList()));
+
+		Optional.ofNullable(getAsMap(mailMap, PostfachNachricht.POSTFACH_ADDRESS_FIELD))
+				.filter(MapUtils::isNotEmpty)
+				.map(this::buildGrpcPostfachAddress)
+				.ifPresent(postfachMailBuilder::setPostfachAddress);
+
+		return postfachMailBuilder.build();
+	}
+
+	GrpcPostfachAddress buildGrpcPostfachAddress(Map<String, Object> postfachAddressMap) {
+		var postfachAddressBuilder = GrpcPostfachAddress.newBuilder()
+				.setType(MapUtils.getIntValue(postfachAddressMap, PostfachAddress.TYPE_FIELD))
+				.setVersion(MapUtils.getString(postfachAddressMap, PostfachAddress.VERSION_FIELD))
+				.setIdentifier(grpcObjectMapper.fromMap(postfachAddressMap));
+		Optional.ofNullable(MapUtils.getString(postfachAddressMap, PostfachAddress.SERVICEKONTO_TYPE_FIELD))
+				.ifPresent(postfachAddressBuilder::setServiceKontoType);
+		return postfachAddressBuilder.build();
+	}
+
+	PostfachNachricht fromMapToPostfachMail(Map<String, Object> mailMap) {
+		var postfachMailBuilder = PostfachNachricht.builder()
+				.id(MapUtils.getString(mailMap, PostfachNachricht.FIELD_ID))
+				.vorgangId(MapUtils.getString(mailMap, (PostfachNachricht.FIELD_VORGANG_ID)))
+				.postfachId(MapUtils.getString(mailMap, PostfachNachricht.FIELD_POSTFACH_ID, StringUtils.EMPTY))
+				.messageId(MapUtils.getString(mailMap, PostfachNachricht.FIELD_MESSAGE_ID))
+				.createdAt(ZonedDateTime.parse(MapUtils.getString(mailMap, PostfachNachricht.FIELD_CREATED_AT)))
+				.createdBy(MapUtils.getString(mailMap, PostfachNachricht.FIELD_CREATED_BY))
+				.sentAt(getString(mailMap, PostfachNachricht.FIELD_SENT_AT).map(ZonedDateTime::parse).orElse(null))
+				.sentSuccessful(MapUtils.getBoolean(mailMap, PostfachNachricht.FIELD_SENT_SUCCESSFUL))
+				.messageCode(MapUtils.getString(mailMap, PostfachNachricht.FIELD_MESSAGE_CODE))
+				.direction(Direction.valueOf(MapUtils.getString(mailMap, PostfachNachricht.FIELD_DIRECTION)))
+				.subject(MapUtils.getString(mailMap, PostfachNachricht.FIELD_SUBJECT))
+				.mailBody(MapUtils.getString(mailMap, PostfachNachricht.FIELD_MAIL_BODY))
+				.replyOption(PostfachNachricht.ReplyOption.valueOf(MapUtils.getString(mailMap, PostfachNachricht.FIELD_REPLY_OPTION)))
+				.attachments(getAsList(mailMap, PostfachNachricht.FIELD_ATTACHMENTS));
+
+		Optional.ofNullable(getAsMap(mailMap, PostfachNachricht.POSTFACH_ADDRESS_FIELD))
+				.filter(MapUtils::isNotEmpty)
+				.map(this::buildPostfachAddress)
+				.ifPresent(postfachMailBuilder::postfachAddress);
+
+		return postfachMailBuilder.build();
+	}
+
+	private Optional<String> getString(Map<String, Object> mailMap, String key) {
+		return Optional.ofNullable(MapUtils.getString(mailMap, key));
+	}
+
+	@SuppressWarnings("unchecked")
+	private List<String> getAsList(Map<String, Object> mailMap, String fieldName) {
+		return (List<String>) mailMap.getOrDefault(fieldName, Collections.emptyList());
+	}
+
+	PostfachAddress buildPostfachAddress(Map<String, Object> postfachAddressMap) {
+		return PostfachAddress.builder()
+				.type(MapUtils.getIntValue(postfachAddressMap, PostfachAddress.TYPE_FIELD))
+				.version(MapUtils.getString(postfachAddressMap, PostfachAddress.VERSION_FIELD))
+				.identifier(buildIdentifier(postfachAddressMap))
+				.serviceKontoType(MapUtils.getString(postfachAddressMap, PostfachAddress.SERVICEKONTO_TYPE_FIELD))
+				.build();
+	}
+
+	PostfachAddressIdentifier buildIdentifier(Map<String, Object> postfachAddressMap) {
+		return StringBasedIdentifier.builder().postfachId(getPostfachId(postfachAddressMap)).build();
+	}
+
+	private String getPostfachId(Map<String, Object> postfachAddressMap) {
+		var identifier = getAsMap(postfachAddressMap, PostfachAddress.IDENTIFIER_FIELD);
+		return MapUtils.getString(identifier, PostfachNachricht.FIELD_POSTFACH_ID);
+
+	}
+
+	@SuppressWarnings("unchecked")
+	Map<String, Object> getAsMap(Map<String, Object> map, String fieldName) {
+		return MapUtils.getMap(map, fieldName, Collections.emptyMap());
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachRemoteService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4e2d19ecdd2ce9cb9380bd8cd2d291b61da8801
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachRemoteService.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import java.util.stream.Stream;
+
+public interface PostfachRemoteService {
+
+	void sendMessage(PostfachNachricht nachricht);
+
+	Stream<PostfachNachricht> getAllMessages();
+
+	void deleteMessage(String messageId);
+
+	String getPostfachType();
+
+	boolean isReplyAllowed();
+}
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachRuntimeException.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachRuntimeException.java
similarity index 73%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachRuntimeException.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachRuntimeException.java
index cba2d9267dfff6787f2a4cf3dd507fe8a5d06660..93c72511650beb432606791c5d5258d927130bff 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachRuntimeException.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachRuntimeException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
-class OsiPostfachRuntimeException extends OsiPostfachException {// NOSONAR
+public class PostfachRuntimeException extends PostfachException {// NOSONAR
 
 	private static final long serialVersionUID = 1L;
 
-	public OsiPostfachRuntimeException(Throwable cause) {
-		super("Error executing Request to OSI Postfach", OsiPostfachMessageCode.SERVER_CONNECTION_FAILED_MESSAGE_CODE, cause);
+	public PostfachRuntimeException(Throwable cause) {
+		super("Error executing Request to Postfach", PostfachMessageCode.SERVER_CONNECTION_FAILED_MESSAGE_CODE, cause);
 	}
 }
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachScheduler.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachScheduler.java
similarity index 75%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachScheduler.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachScheduler.java
index 9ec80e6bad4161dc16baa6a32cde8d25d374d0df..2c1dd27c72ad3a0b901b80d6b53c9259bc78c8b9 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachScheduler.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachScheduler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Profile;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -33,14 +34,15 @@ import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
 
 @Component
 @Profile("!itcase")
-@ConditionalOnProperty(prefix = OsiPostfachProperties.PREFIX, name = { "proxyapi.url", "proxyapi.key", "proxyapi.realm", "scheduler.enabled" })
+@ConditionalOnBean(PostfachRemoteService.class)
+@ConditionalOnProperty(name = { "ozgcloud.osi.postfach.scheduler.enabled" })
 class PostfachScheduler {
 
 	@Autowired
 	private PostfachService service;
 
-	@Scheduled(initialDelayString = "${kop.osi.postfach.scheduler.initialDelay:5000}", //
-			fixedDelayString = "${kop.osi.postfach.scheduler.fixedDelay:900000}")
+	@Scheduled(initialDelayString = "${ozgcloud.osi.postfach.scheduler.initialDelay:5000}", //
+			fixedDelayString = "${ozgcloud.osi.postfach.scheduler.fixedDelay:900000}")
 	@SchedulerLock(name = "PostfachScheduler")
 	void runGetMessagesTask() {
 		service.fetchAndPersistReplies();
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java
new file mode 100644
index 0000000000000000000000000000000000000000..bfe95c29ad6c7ef39743138971640c12d7891bc1
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import java.time.ZonedDateTime;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import jakarta.validation.Valid;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import de.ozgcloud.nachrichten.attributes.ClientAttributeService;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.ReplyOption;
+import de.ozgcloud.nachrichten.postfach.antragsraum.AntragsraumService;
+import de.ozgcloud.nachrichten.postfach.osi.OsiPostfachServerProcessException;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import lombok.NonNull;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@Service
+@Validated
+class PostfachService {
+
+	private static final Predicate<PostfachNachricht> IS_FROM_HUMAN_USER = nachricht -> !StringUtils.startsWith(nachricht.getCreatedBy(), "system");
+	private static final Set<String> POSTFACH_TYPES_WITH_ANTRAGSRAUM = Set.of("BayernId");
+
+	@Autowired(required = false)
+	private PostfachRemoteService postfachRemoteService;
+
+	private static final Set<ReplyOption> REPLY_POSSIBLE_OPTION = EnumSet.of(ReplyOption.POSSIBLE, ReplyOption.MANDATORY);
+
+	@Autowired
+	private PostfachNachrichtMapper mapper;
+
+	@Autowired
+	private PersistPostfachNachrichtService persistingService;
+	@Autowired
+	private ClientAttributeService clientAttributeService;
+
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	@Autowired
+	private CurrentUserService userService;
+
+	@Autowired(required = false)
+	private AntragsraumService antragsraumService;
+
+	public void saveDraft(String vorgangId, PostfachNachricht nachricht) {
+		persistMail(userService.getUser().getUserId(),
+				nachricht.toBuilder().vorgangId(vorgangId)
+						.createdBy(userService.getUser().getUserId().orElse(null))
+						.build());
+	}
+
+	public void sendMail(String commandId, String userId, @Valid PostfachNachricht mail) {
+		var sendResponse = handleSendMail(commandId, mail);
+		persistSentMail(userId, addMailSentInformation(mail, sendResponse));
+	}
+
+	PostfachNachricht addMailSentInformation(PostfachNachricht mail, SendPostfachNachrichtResponse sendResponse) {
+		return mail.toBuilder().sentAt(ZonedDateTime.now()).sentSuccessful(sendResponse.isSentSuccessful())
+				.messageCode(sendResponse.getMessageCode().getMessageCode())
+				.build();
+	}
+
+	void persistSentMail(@NonNull String userId, PostfachNachricht mail) {
+		persistMail(Optional.of(userId), mail.toBuilder()
+				.direction(Direction.OUT)
+				.createdAt(ZonedDateTime.now().withNano(0)).createdBy(userId)
+				.build());
+
+	}
+
+	public Optional<Map<String, Object>> findById(String nachrichtId) {
+		return persistingService.findById(nachrichtId);
+	}
+
+	public Stream<Map<String, Object>> findByVorgang(String vorgangId) {
+		return persistingService.findByVorgangAsMap(vorgangId);
+	}
+
+	public void fetchAndPersistReplies() {
+		ifPostfachConfigured(() -> postfachRemoteService.getAllMessages().forEach(this::persistReceivedMail));
+	}
+
+	private void persistReceivedMail(PostfachNachricht nachricht) {
+		persistMail(Optional.empty(), nachricht);
+		clientAttributeService.setHasNewPostfachNachricht(nachricht.getVorgangId());
+
+		postfachRemoteService.deleteMessage(nachricht.getMessageId());
+	}
+
+	void persistMail(Optional<String> userId, PostfachNachricht mail) {
+		persistingService.persistNachricht(userId, mail);
+
+		if (IS_FROM_HUMAN_USER.test(mail)) {
+			clientAttributeService.setHasPostfachNachricht(mail.getVorgangId());
+		}
+	}
+
+	public void resendMail(String commandId, String postfachMailId) {
+		PostfachNachricht nachricht = mapper.fromMapToPostfachMail(persistingService.getById(postfachMailId));
+
+		var sendResponse = handleSendMail(commandId, nachricht);
+		patchMail(nachricht.getId(), createResendPatchMap(sendResponse));
+	}
+
+	SendPostfachNachrichtResponse handleSendMail(String commandId, PostfachNachricht mail) {
+		try {
+			var processedPostfachNachricht = processForAntragsraum(mail).orElse(mail);
+			doSendMail(processedPostfachNachricht);
+
+			publishMailSentEvent(commandId);
+			return buildSendNachrichtResponse(true, PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE);
+		} catch (OsiPostfachServerProcessException e) {
+			return proceedwithWarnException(commandId, e);
+
+		} catch (PostfachException e) {
+			return proceedWithErrorException(commandId, e);
+		}
+	}
+
+	Optional<PostfachNachricht> processForAntragsraum(PostfachNachricht mail) {
+		if (isNotifyAntragsraum(mail.getReplyOption())) {
+			antragsraumService.notifyAntragsraum(mail);
+			return adjustMail(mail);
+		}
+		return Optional.empty();
+	}
+
+	boolean isNotifyAntragsraum(ReplyOption replyOption) {
+		return REPLY_POSSIBLE_OPTION.contains(replyOption) && isPostfachWithAntragsraum(postfachRemoteService);
+	}
+
+	Optional<PostfachNachricht> adjustMail(PostfachNachricht nachricht) {
+		return getAntragsraumService().map(antragsraum -> nachricht.toBuilder().mailBody(antragsraum.getUserNotificationText()).build());
+	}
+
+	SendPostfachNachrichtResponse proceedwithWarnException(String commandId, OsiPostfachServerProcessException e) {
+		LOG.warn(e.getMessage(), e);
+		return proceedWithException(commandId, e);
+	}
+
+	SendPostfachNachrichtResponse proceedWithErrorException(String commandId, PostfachException e) {
+		LOG.error(e.getMessage(), e);
+		return proceedWithException(commandId, e);
+	}
+
+	private SendPostfachNachrichtResponse proceedWithException(String commandId, PostfachException e) {
+		publishMailSentFailedEvent(commandId, e.getMessage());
+		return buildSendNachrichtResponse(false, e.getMessageCode());
+
+	}
+
+	void doSendMail(PostfachNachricht nachricht) {
+		ifPostfachConfigured(() -> postfachRemoteService.sendMessage(nachricht));
+	}
+
+	private void publishMailSentEvent(String commandId) {
+		publisher.publishEvent(new PostfachMailSentEvent(commandId));
+	}
+
+	public void publishMailSentFailedEvent(String commandId, String message) {
+		publisher.publishEvent(new PostfachMailSentFailedEvent(commandId, message));
+	}
+
+	private SendPostfachNachrichtResponse buildSendNachrichtResponse(boolean sentSuccesful, PostfachMessageCode messageCode) {
+		return SendPostfachNachrichtResponse.builder().sentSuccessful(sentSuccesful).messageCode(messageCode).build();
+	}
+
+	Map<String, Object> createResendPatchMap(SendPostfachNachrichtResponse sendResponse) {
+		return Map.of(PostfachNachricht.FIELD_SENT_AT, ZonedDateTime.now().withNano(0).toString(),
+				PostfachNachricht.FIELD_SENT_SUCCESSFUL, sendResponse.isSentSuccessful(),
+				PostfachNachricht.FIELD_MESSAGE_CODE, sendResponse.getMessageCode().getMessageCode());
+	}
+
+	private void patchMail(String postfachMailId, Map<String, Object> propertyMap) {
+		persistingService.patch(postfachMailId, propertyMap);
+	}
+
+	public boolean isPostfachConfigured() {
+		return postfachRemoteService != null;
+	}
+
+	public Stream<Postfach> getPostfachs() {
+		return isPostfachConfigured() ? Stream.of(buildPostfach(postfachRemoteService)) : Stream.empty();
+	}
+
+	Postfach buildPostfach(PostfachRemoteService postfachRemoteService) {
+		return Postfach.builder().type(postfachRemoteService.getPostfachType()).isReplyAllowed(isReplyAllowed(postfachRemoteService)).build();
+	}
+
+	boolean isReplyAllowed(PostfachRemoteService postfachRemoteService) {
+		return isPostfachWithAntragsraum(postfachRemoteService) || postfachRemoteService.isReplyAllowed();
+	}
+
+	boolean isPostfachWithAntragsraum(PostfachRemoteService postfachRemoteService) {
+		return POSTFACH_TYPES_WITH_ANTRAGSRAUM.contains(postfachRemoteService.getPostfachType()) && getAntragsraumService().isPresent();
+	}
+
+	Optional<AntragsraumService> getAntragsraumService() {
+		return Optional.ofNullable(antragsraumService);
+	}
+
+	private void ifPostfachConfigured(Runnable block) {
+		if (!isPostfachConfigured()) {
+			throw new NotConfiguredException();
+		}
+		block.run();
+	}
+
+}
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/SendPostfachNachrichtResponse.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/SendPostfachNachrichtResponse.java
similarity index 88%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/SendPostfachNachrichtResponse.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/SendPostfachNachrichtResponse.java
index 24e60ff11f7eb78aef73f89f3d2231b15d837665..0ac7feb610808e47d55fc7ec6d45e2568f0ea04e 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/SendPostfachNachrichtResponse.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/SendPostfachNachrichtResponse.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import lombok.AllArgsConstructor;
 import lombok.Builder;
@@ -32,5 +32,5 @@ import lombok.Getter;
 @AllArgsConstructor
 class SendPostfachNachrichtResponse {
 	private boolean sentSuccessful;
-	private OsiPostfachMessageCode messageCode;
+	private PostfachMessageCode messageCode;
 }
\ No newline at end of file
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/StringBasedIdentifier.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/StringBasedIdentifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..12f171c24dcac9864cee10487c5eefd7829f6a1a
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/StringBasedIdentifier.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class StringBasedIdentifier implements PostfachAddressIdentifier {
+
+	private String postfachId;
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumProperties.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..3685aacb277fc230cf02a3f3f086d56c2a9a4daf
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumProperties.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import jakarta.validation.constraints.NotEmpty;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Configuration
+@ConditionalOnProperty(AntragsraumProperties.PROPERTY_ANTRAGSRAUM_URL)
+@ConfigurationProperties(prefix = "ozgcloud.antragsraum")
+@Validated
+class AntragsraumProperties {
+
+	static final String PROPERTY_ANTRAGSRAUM_URL  = "ozgcloud.antragsraum.url";
+
+	@NotEmpty
+	private String url;
+
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumService.java
new file mode 100644
index 0000000000000000000000000000000000000000..50defe406b8cfef2ee28d9ac2c06db6608a52ec5
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumService.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import static java.util.Objects.*;
+
+import jakarta.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.nachrichten.NachrichtenManagerProperties;
+import de.ozgcloud.nachrichten.postfach.PostfachException;
+import de.ozgcloud.nachrichten.postfach.PostfachMessageCode;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+
+@Service
+@ConditionalOnProperty(AntragsraumProperties.PROPERTY_ANTRAGSRAUM_URL)
+public class AntragsraumService {
+
+	static final String USER_NOTIFICATION_TEMPLATE = """
+			Guten Tag,
+			  
+			bei der Bearbeitung Ihres Antrags hat sich eine Rückfrage ergeben. Bitte beantworten Sie diese im Antragsraum:
+			  
+			%s
+			  
+			Vielen Dank,
+			Ihre digitale Verwaltung
+			""";
+
+	@Autowired
+	private AntragsraumProperties properties;
+
+	@Autowired
+	private NachrichtenManagerProperties nachrichtenManagerProperties;
+
+	@Autowired
+	private InfomanagerRemoteService infomanagerRemoteService;
+
+	@PostConstruct
+	void init() {
+		if (isNull(nachrichtenManagerProperties.getUrl())) {
+			throw new IllegalStateException("Address of Nachrichten-Manager is not set");
+		}
+	}
+
+	public String getAntragsraumUrl() {
+		return properties.getUrl();
+	}
+
+	public String getUserNotificationText() {
+		return USER_NOTIFICATION_TEMPLATE.formatted(getAntragsraumUrl());
+	}
+
+	public void notifyAntragsraum(PostfachNachricht postfachNachricht) {
+		try {
+			infomanagerRemoteService.sendNotification(builInfomanagerNachricht(postfachNachricht));
+		} catch (RuntimeException e) {
+			throw new PostfachException("Error while sending notification to Antragsraum", PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE, e);
+		}
+	}
+
+	InfomanagerNachricht builInfomanagerNachricht(PostfachNachricht postfachNachricht) {
+		return InfomanagerNachricht.builder()
+				.nachrichtId(postfachNachricht.getId())
+				.vorgangId(postfachNachricht.getVorgangId())
+				.postfachId(postfachNachricht.getPostfachId())
+				.nachrichtenManagerUrl(nachrichtenManagerProperties.getUrl())
+				.build();
+	}
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachricht.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachricht.java
new file mode 100644
index 0000000000000000000000000000000000000000..21babdaa880873b75458a80db6e2c58abdb76c80
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachricht.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class InfomanagerNachricht {
+
+	private String nachrichtId;
+	private String vorgangId;
+	private String postfachId;
+	private String nachrichtenManagerUrl;
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachrichtMapper.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachrichtMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..a02c58713bf649b852138b92c09ae8c82fc764a4
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachrichtMapper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+import de.ozgcloud.info.nachricht.GrpcNachricht;
+
+@Mapper
+interface InfomanagerNachrichtMapper {
+
+	@Mapping(target = "nachrichtenListUrl", source = "nachrichtenManagerUrl")
+	GrpcNachricht toGrpc(InfomanagerNachricht infomanagerNachricht);
+
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerProperties.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..e44ba7c17eac16369fdcbfc15932ffddaca7dde4
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerProperties.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import jakarta.validation.constraints.NotEmpty;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Configuration
+@ConfigurationProperties(prefix = "grpc.client.info-manager")
+@ConditionalOnProperty(AntragsraumProperties.PROPERTY_ANTRAGSRAUM_URL)
+@Validated
+public class InfomanagerProperties {
+
+	@NotEmpty
+	private String address;
+
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerRemoteService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d2509916f768bc2b21adab48cea503ee0bc018b
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerRemoteService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.info.nachricht.GrpcNewNachrichtRequest;
+import de.ozgcloud.info.nachricht.NachrichtServiceGrpc.NachrichtServiceBlockingStub;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Service
+class InfomanagerRemoteService {
+
+	@GrpcClient("info-manager")
+	private NachrichtServiceBlockingStub nachrichtServiceStub;
+
+	@Autowired
+	private InfomanagerNachrichtMapper nachrichtMapper;
+
+	public String sendNotification(InfomanagerNachricht nachricht) {
+		var grpcNewNachrichtReply = nachrichtServiceStub.saveNewNachricht(buildNachrichtRequest(nachricht));
+		return grpcNewNachrichtReply.getStatus();
+	}
+
+	GrpcNewNachrichtRequest buildNachrichtRequest(InfomanagerNachricht nachricht) {
+		return GrpcNewNachrichtRequest.newBuilder().setNachricht(nachrichtMapper.toGrpc(nachricht)).build();
+	}
+
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/Absender.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/Absender.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7b39b9e9f122111aa92bbb80c370be517bace6b
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/Absender.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Pattern;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+@AllArgsConstructor
+class Absender {
+	@Pattern(regexp = "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}")
+	private String postkorbId;
+	@NotBlank
+	private String name;
+	private String anschrift;
+	@NotBlank
+	private String dienst;
+	@NotBlank
+	private String mandant;
+	private String gemeindeSchluessel;
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachment.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachment.java
new file mode 100644
index 0000000000000000000000000000000000000000..75b28430cac0ff5b97283095dadd73e5e39957e5
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachment.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.io.InputStream;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class BayernIdAttachment {
+
+	private String fileName;
+	private String contentType;
+	private InputStream content;
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentService.java
new file mode 100644
index 0000000000000000000000000000000000000000..699214ae8b56c3bb16b9ead22531e0302508681e
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentService.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.io.InputStream;
+import java.util.Optional;
+
+import org.bson.Document;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Service;
+
+import com.mongodb.client.gridfs.model.GridFSFile;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.BinaryFileService;
+import de.ozgcloud.nachrichten.postfach.FileId;
+
+@Service
+@ConditionalOnProperty(prefix = "ozgcloud.bayernid", name = { "enabled" })
+public class BayernIdAttachmentService {
+
+	static final String NAME_KEY = "name";
+	static final String CONTENT_TYPE_KEY = "contentType";
+
+	@Autowired
+	private BinaryFileService binaryFileService;
+
+	public BayernIdAttachment getMessageAttachment(FileId fileId) {
+		return Optional.ofNullable(binaryFileService.getFile(fileId))
+				.map(GridFSFile::getMetadata)
+				.map(metadata -> buildBayernIdAttachment(metadata, getAttachmentContentStream(fileId)))
+				.orElseThrow(() -> new TechnicalException("Can not find attachment with id " + fileId));
+	}
+
+	BayernIdAttachment buildBayernIdAttachment(Document metadata, InputStream attachmentContent) {
+		return BayernIdAttachment.builder()
+				.fileName(metadata.getString(NAME_KEY))
+				.contentType(metadata.getString(CONTENT_TYPE_KEY))
+				.content(attachmentContent)
+				.build();
+	}
+
+	InputStream getAttachmentContentStream(FileId fileId) {
+		return binaryFileService.getUploadedFileStream(fileId);
+	}
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachNachrichtMapper.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachNachrichtMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c33343cfeab08ed4aed145415c38402281909a3
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachNachrichtMapper.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.time.ZonedDateTime;
+import java.util.GregorianCalendar;
+import java.util.Objects;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+
+import org.mapstruct.Condition;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.ReportingPolicy;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.PostfachAddress;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.StringBasedIdentifier;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAbsender;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAttachmentMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcBayernIdMessageMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
+interface BayernIdPostfachNachrichtMapper {
+
+	String MESSAGE_LEVEL = "LEVEL_1";
+
+	@Mapping(target = "attachments", ignore = true)
+	@Mapping(target = "messageMetadata", expression = "java(toBayernIdMessageMetadata(nachricht, absender))")
+	GrpcSendBayernIdMessageRequest toSendBayernIdMessageMetadataRequest(PostfachNachricht nachricht, Absender absender);
+
+	@Mapping(target = "messageId", source = "nachricht.messageId")
+	@Mapping(target = "createdAt", expression = "java(convertZonedDateTime(nachricht.getCreatedAt()))")
+	@Mapping(target = "subject", source = "nachricht.subject")
+	@Mapping(target = "storkQaaLevel", constant = MESSAGE_LEVEL)
+	@Mapping(target = "vorgangId", source = "nachricht.vorgangId")
+	@Mapping(target = "text", source = "nachricht.mailBody")
+	@Mapping(target = "empfaenger.postkorbId", source = "nachricht.postfachAddress")
+	GrpcBayernIdMessageMetadata toBayernIdMessageMetadata(PostfachNachricht nachricht, Absender absender);
+
+	@Mapping(target = "gemeindeschluessel", source = "gemeindeSchluessel")
+	GrpcAbsender toAbsender(Absender absender);
+
+	@Mapping(target = "messageMetadata", ignore = true)
+	@Mapping(target = "attachments.content", ignore = true)
+	@Mapping(target = "attachments.attachmentMetadata", expression = "java(toAttachmentMetadata(bayernIdAttachment))")
+	GrpcSendBayernIdMessageRequest toSendBayernIdAttachmentsMetadataRequest(BayernIdAttachment bayernIdAttachment);
+
+	@Mapping(target = "fileType", source = "contentType")
+	GrpcAttachmentMetadata toAttachmentMetadata(BayernIdAttachment attachment);
+
+	default String convertZonedDateTime(ZonedDateTime zonedDateTime) {
+		try {
+			return DatatypeFactory.newInstance().newXMLGregorianCalendar(GregorianCalendar.from(zonedDateTime)).toString();
+		} catch (DatatypeConfigurationException e) {
+			throw new TechnicalException("Error creating XMLGregorianCalendar which should not happen in this case.", e);
+		}
+	}
+
+	BayernIdResponse fromSendBayernIdMessageResponse(GrpcSendBayernIdMessageResponse response);
+
+	default String toPostkorbId(PostfachAddress postfachAddress) {
+		return ((StringBasedIdentifier) postfachAddress.getIdentifier()).getPostfachId();
+	}
+
+	@Condition
+	default boolean nonNull(String value) {
+		return Objects.nonNull(value);
+	}
+
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachRemoteService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..9666abd3483af4ce0e3f3138f7db53ecba010622
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachRemoteService.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import jakarta.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+
+import com.google.protobuf.ByteString;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.FileId;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.PostfachRemoteService;
+import de.ozgcloud.nachrichten.postfach.PostfachRuntimeException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.BayernIdProxyServiceGrpc.BayernIdProxyServiceStub;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAttachments;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+import io.grpc.stub.CallStreamObserver;
+import io.grpc.stub.StreamObserver;
+import lombok.extern.log4j.Log4j2;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Log4j2
+@ConditionalOnProperty(prefix = "ozgcloud.bayernid", name = { "enabled" }, havingValue = "true")
+@Component
+class BayernIdPostfachRemoteService implements PostfachRemoteService {
+
+	static final String POSTFACH_TYPE = "BayernId";
+
+	@GrpcClient("bayern-id")
+	private BayernIdProxyServiceStub bayernIdProxyServiceStub;
+
+	@Autowired
+	private BayernIdProperties bayernIdProperties;
+	@Autowired
+	private BayernIdPostfachResponseHandler responseHandler;
+	@Autowired
+	private BayernIdPostfachNachrichtMapper mapper;
+	@Autowired
+	private BayernIdAttachmentService bayernIdAttachmentService;
+
+	@PostConstruct
+	void init() {
+		LOG.info("BayernID Postfach remote service initialized.");
+	}
+
+	@Override
+	public void sendMessage(PostfachNachricht nachricht) {
+		try {
+			var sender = createMessageWithFilesSender(nachricht).send();
+			var response = waitUntilTransferCompleted(sender);
+			responseHandler.handleResponse(mapper.fromSendBayernIdMessageResponse(response));
+		} catch (BayernIdServerException e) {
+			throw e;
+		} catch (RuntimeException e) {
+			throw new PostfachRuntimeException(e);
+		}
+	}
+
+	MessageWithFilesSender createMessageWithFilesSender(PostfachNachricht nachricht) {
+		return MessageWithFilesSender.builder()
+				.reqObserverBuilder(buildCallStreamObserverBuilder())
+				.messageMetadata(mapper.toSendBayernIdMessageMetadataRequest(nachricht, bayernIdProperties.getAbsender()))
+				.attachmentIds(nachricht.getAttachments())
+				.toAttachment(buildAttachmentBuilder())
+				.attachmentMetadataMapper(buildAttachmentMetadataMapper())
+				.chunkBuilder(buildChunkRequest())
+				.build();
+	}
+
+	Function<StreamObserver<GrpcSendBayernIdMessageResponse>, CallStreamObserver<GrpcSendBayernIdMessageRequest>> buildCallStreamObserverBuilder() {
+		return responseObserver ->
+				(CallStreamObserver<GrpcSendBayernIdMessageRequest>) bayernIdProxyServiceStub.sendMessageAsStream(responseObserver);
+	}
+
+	Function<String, BayernIdAttachment> buildAttachmentBuilder() {
+		return attachmentId -> bayernIdAttachmentService.getMessageAttachment(FileId.from(attachmentId));
+	}
+
+	BiFunction<byte[], Integer, GrpcSendBayernIdMessageRequest> buildChunkRequest() {
+		return (bytes, length) -> GrpcSendBayernIdMessageRequest.newBuilder()
+				.setAttachments(GrpcAttachments.newBuilder().setContent(ByteString.copyFrom(bytes, 0, length)).build())
+				.build();
+	}
+
+	Function<BayernIdAttachment, GrpcSendBayernIdMessageRequest> buildAttachmentMetadataMapper() {
+		return mapper::toSendBayernIdAttachmentsMetadataRequest;
+	}
+
+	GrpcSendBayernIdMessageResponse waitUntilTransferCompleted(MessageWithFilesSender sender) {
+		try {
+			return sender.getResultFuture().get(2, TimeUnit.MINUTES);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+			sender.cancelOnError(e);
+			throw new TechnicalException("Waiting for finishing upload was interrupted.", e);
+		} catch (ExecutionException | TimeoutException e) {
+			sender.cancelOnTimeout();
+			throw new TechnicalException("Error / Timeout on uploading data.", e);
+		}
+	}
+
+	@Override
+	public Stream<PostfachNachricht> getAllMessages() {
+		throw new UnsupportedOperationException("Bayern ID doesn't support this operation.");
+	}
+
+	@Override
+	public void deleteMessage(String messageId) {
+		throw new UnsupportedOperationException("Bayern ID doesn't support this operation.");
+	}
+
+	@Override
+	public String getPostfachType() {
+		return POSTFACH_TYPE;
+	}
+
+	@Override
+	public boolean isReplyAllowed() {
+		return false;
+	}
+
+}
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangMapper.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachResponseHandler.java
similarity index 53%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangMapper.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachResponseHandler.java
index 651caa2cf6eda3888e4659654bec9bfd5f7de457..a42bdf34ad05cefda14d0f390f67ea11433d1a83 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangMapper.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachResponseHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,26 +21,24 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.nachrichten.postfach.bayernid;
 
-import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
 
-import de.itvsh.ozg.pluto.vorgang.GrpcVorgangWithEingang;
+import lombok.extern.log4j.Log4j2;
 
-@Mapper
-interface VorgangMapper {
+@Log4j2
+@Component
+@ConditionalOnProperty(prefix = "ozgcloud.bayernid", name = { "enabled" })
+class BayernIdPostfachResponseHandler {
 
-	@Mapping(target = "postfachId", source = "eingang.antragsteller.postfachId")
-	@Mapping(target = "vorgangName", source = "name")
-	@Mapping(target = "vorgangNummer", source = "nummer")
-	@Mapping(target = "organisationseinheitenId", source = "eingang.zustaendigeStelle.organisationseinheitenId")
-	Vorgang fromGrpc(GrpcVorgangWithEingang vorgang);
-
-	default VorgangId fromString(String vorgangId) {
-		if (vorgangId == null) {
-			return null;
+	public void handleResponse(BayernIdResponse bayernIdResponse) {
+		if (bayernIdResponse.isSuccess()) {
+			return;
 		}
-		return VorgangId.from(vorgangId);
+		var message = StringUtils.defaultIfBlank(bayernIdResponse.getMessage(), "Cannot send message to BayernID.");
+		throw new BayernIdServerException(message, MailSendingResponseStatus.fromSchluessel(bayernIdResponse.getStatus()));
 	}
 }
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdProperties.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..41fe1609cef6d2e0fdc502593cdb44fc81226f3e
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdProperties.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import jakarta.validation.constraints.NotNull;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Validated
+@Configuration
+@ConfigurationProperties(prefix = "ozgcloud.bayernid")
+@ConditionalOnProperty(prefix = "ozgcloud.bayernid", name = { "enabled" })
+@ConfigurationPropertiesScan
+class BayernIdProperties {
+
+	@NotNull
+	private Absender absender;
+
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdResponse.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..329282c745a5416bcc5917e5bdc08285bae5c471
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdResponse.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class BayernIdResponse {
+
+	private boolean success;
+	private String status;
+	private String message;
+
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerException.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerException.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f22e39ae25b2020f3f36afda8ffaedc3a8cf91c
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdServerException.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.ozgcloud.nachrichten.postfach.PostfachException;
+import de.ozgcloud.nachrichten.postfach.PostfachMessageCode;
+
+class BayernIdServerException extends PostfachException {
+
+	static final String TABELLE_NUMMER_EMPFANG_ERGEBNISSTATUS = "9006";
+	private static final String ERROR_MESSAGE_TEMPLATE = TABELLE_NUMMER_EMPFANG_ERGEBNISSTATUS + " / %s / %s / %s";
+
+	private final MailSendingResponseStatus mailSendingResponseStatus;
+
+	public BayernIdServerException(String message) {
+		super(message, PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE);
+		this.mailSendingResponseStatus = null;
+	}
+
+	public BayernIdServerException(String message, MailSendingResponseStatus mailSendingResponseStatus) {
+		super(message, PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE);
+		this.mailSendingResponseStatus = mailSendingResponseStatus;
+	}
+
+	@Override
+	public String getMessage() {
+		if (mailSendingResponseStatus == null) {
+			return super.getMessage();
+		}
+		return ERROR_MESSAGE_TEMPLATE.formatted(mailSendingResponseStatus.getSchluessel(), mailSendingResponseStatus.getMessage(), super.getMessage());
+	}
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/FileSender.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/FileSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..610b3808b14f417a0ab09edb8f0efc7c4003a2a2
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/FileSender.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+
+import org.apache.commons.io.IOUtils;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import io.grpc.stub.CallStreamObserver;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+class FileSender {
+
+	static final int CHUNK_SIZE = 4 * 1024;
+
+	private final AtomicBoolean metaDataSent = new AtomicBoolean(false);
+	private final AtomicBoolean done = new AtomicBoolean(false);
+
+	private final BiFunction<byte[], Integer, GrpcSendBayernIdMessageRequest> chunkBuilder;
+	private final CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+	private final GrpcSendBayernIdMessageRequest metadata;
+	private final StreamReader streamReader;
+
+	public FileSender(BiFunction<byte[], Integer, GrpcSendBayernIdMessageRequest> chunkBuilder,
+			CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver, GrpcSendBayernIdMessageRequest metadata,
+			InputStream inputStream) {
+		this.chunkBuilder = chunkBuilder;
+		this.requestObserver = requestObserver;
+		this.metadata = metadata;
+		this.streamReader = new StreamReader(inputStream);
+	}
+
+	public void send() {
+		if (!done.get()) {
+			sendMetadata();
+			while (!done.get() && requestObserver.isReady()) {
+				LOG.debug("Sending next chunk.");
+				sendNextChunk();
+			}
+			LOG.debug("Finished or waiting to become ready.");
+		}
+	}
+
+	void sendMetadata() {
+		if (metaDataSent.getAndSet(true)) {
+			return;
+		}
+		LOG.debug("Sending Attachment Metadata.");
+		requestObserver.onNext(metadata);
+	}
+
+	long sendNextChunk() {
+		byte[] contentToSend = streamReader.getNextData();
+
+		if (streamReader.getLastReadSize() > 0) {
+			sendChunk(contentToSend, streamReader.getLastReadSize());
+		} else {
+			endTransfer();
+		}
+		return contentToSend.length;
+	}
+
+	void endTransfer() {
+		done.set(true);
+		LOG.debug("File Transfer done. Closing stream.");
+		streamReader.close();
+	}
+
+	void sendChunk(byte[] content, int length) {
+		LOG.debug("Sending {} byte Data.", length);
+		var chunk = chunkBuilder.apply(content, length);
+		requestObserver.onNext(chunk);
+	}
+
+	@RequiredArgsConstructor
+	class StreamReader {
+
+		private final InputStream inStream;
+		private final byte[] buffer = new byte[CHUNK_SIZE];
+		@Getter
+		private int lastReadSize = 0;
+		@Getter
+		private final AtomicBoolean done = new AtomicBoolean(false);
+
+		byte[] getNextData() {
+			readNext();
+			return buffer;
+		}
+
+		void close() {
+			IOUtils.closeQuietly(inStream);
+		}
+
+		void readNext() {
+			try {
+				lastReadSize = inStream.read(buffer, 0, CHUNK_SIZE);
+			} catch (IOException e) {
+				throw new TechnicalException("Error on reading a single chunk", e);
+			}
+		}
+	}
+
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/MailSendingResponseStatus.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/MailSendingResponseStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..921a6d3128220b9eba18dc821b97b6d65008f8ed
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/MailSendingResponseStatus.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+enum MailSendingResponseStatus {
+	SUCCESS("0", "Nachricht wurde erfolgreich übernommen"),
+	OK_KOMM_SCHEMA_ERROR("10", "Fehler im OK.KOMM-Schema"),
+	OK_KOMM_INVALID_SCHEMA_PARAMETER("11", "Ungültige Parameter im OK.KOMM-Schema"),
+	ERROR_IN_MESSAGE_SCHEMA("20", "Fehler im BSP-Nachrichtenschema"),
+	INVALID_POSTKORB_ID("30", "Ungültiger Postkorb-Handle"),
+	IMPROPER_MESSAGE_CONTENT("31", "Unzulässiger Nachrichteninhalt"),
+	IMPROPER_MESSAGE_ATTACHMENT("32", "Unzulässiger Nachrichtenanhang"),
+	TECHNICAL_ERROR("99", "Sonstiger technischer Fehler"),
+	UNKNOWN("-1", "Unbekannte Server Antwort");
+
+	private String schluessel;
+	private String message;
+
+	MailSendingResponseStatus(String schluessel, String message) {
+		this.schluessel = schluessel;
+		this.message = message;
+	}
+
+	public static MailSendingResponseStatus fromSchluessel(String schluessel) {
+		return switch (schluessel) {
+			case "0" -> MailSendingResponseStatus.SUCCESS;
+			case "10" -> MailSendingResponseStatus.OK_KOMM_SCHEMA_ERROR;
+			case "11" -> MailSendingResponseStatus.OK_KOMM_INVALID_SCHEMA_PARAMETER;
+			case "20" -> MailSendingResponseStatus.ERROR_IN_MESSAGE_SCHEMA;
+			case "30" -> MailSendingResponseStatus.INVALID_POSTKORB_ID;
+			case "31" -> MailSendingResponseStatus.IMPROPER_MESSAGE_CONTENT;
+			case "32" -> MailSendingResponseStatus.IMPROPER_MESSAGE_ATTACHMENT;
+			case "99" -> MailSendingResponseStatus.TECHNICAL_ERROR;
+			default -> MailSendingResponseStatus.UNKNOWN;
+		};
+	}
+
+	public String getSchluessel() {
+		return schluessel;
+	}
+
+	public String getMessage() {
+		return message;
+	}
+}
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/MessageWithFilesSender.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/MessageWithFilesSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..29457e1e4f1af0826f45f899cf8aedfdb289aa81
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/bayernid/MessageWithFilesSender.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static java.util.Objects.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import de.ozgcloud.common.binaryfile.BinaryFileUploadStreamObserver;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+import io.grpc.stub.CallStreamObserver;
+import io.grpc.stub.StreamObserver;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@Builder
+public class MessageWithFilesSender {
+
+	static final int CHUNK_SIZE = 4 * 1024;
+
+	@Getter
+	private final CompletableFuture<GrpcSendBayernIdMessageResponse> resultFuture = new CompletableFuture<>();
+	private final AtomicBoolean done = new AtomicBoolean(false);
+	private final AtomicBoolean metaDataSent = new AtomicBoolean(false);
+
+	private final Function<StreamObserver<GrpcSendBayernIdMessageResponse>, CallStreamObserver<GrpcSendBayernIdMessageRequest>> reqObserverBuilder;
+	private final GrpcSendBayernIdMessageRequest messageMetadata;
+	@Builder.Default
+	private final List<String> attachmentIds = Collections.emptyList();
+	private final Function<String, BayernIdAttachment> toAttachment;
+	private final Function<BayernIdAttachment, GrpcSendBayernIdMessageRequest> attachmentMetadataMapper;
+	private final BiFunction<byte[], Integer, GrpcSendBayernIdMessageRequest> chunkBuilder;
+
+	private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+	private List<FileSender> fileSenders;
+
+	public MessageWithFilesSender send() {
+		var responseStreamObserver = BinaryFileUploadStreamObserver.create(resultFuture, this::sendNext);
+		requestObserver = reqObserverBuilder.apply(responseStreamObserver);
+		return this;
+	}
+
+	public void sendNext() {
+		if (done.get()) {
+			return;
+		}
+		waitForObserver();
+		sendMetadata();
+		sendAttachments();
+	}
+
+	synchronized void waitForObserver() {
+		while (isNull(requestObserver)) {
+			try {
+				LOG.debug("wait for observer");
+				wait(300);
+			} catch (InterruptedException e) {
+				LOG.error("Error on waiting for request Observer.", e);
+				Thread.currentThread().interrupt();
+			}
+		}
+	}
+
+	void sendMetadata() {
+		if (metaDataSent.getAndSet(true)) {
+			return;
+		}
+		requestObserver.onNext(messageMetadata);
+	}
+
+	void sendAttachments() {
+		if (isNull(fileSenders)) {
+			fileSenders = createFileSenders();
+		}
+		fileSenders.forEach(FileSender::send);
+		completeRequest();
+	}
+
+	List<FileSender> createFileSenders() {
+		return attachmentIds.stream().map(toAttachment).map(this::buildFileSender).toList();
+	}
+
+	FileSender buildFileSender(BayernIdAttachment attachment) {
+		return new FileSender(chunkBuilder, requestObserver, attachmentMetadataMapper.apply(attachment), attachment.getContent());
+	}
+
+	void completeRequest() {
+		done.set(true);
+		requestObserver.onCompleted();
+	}
+
+	public void cancelOnTimeout() {
+		LOG.warn("File transfer canceled on timeout");
+		resultFuture.cancel(true);
+		requestObserver.onError(new TechnicalException("Timeout on waiting for upload."));
+	}
+
+	public void cancelOnError(Throwable t) {
+		resultFuture.cancel(true);
+		requestObserver.onError(t);
+	}
+}
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/Message.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/Message.java
similarity index 87%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/Message.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/Message.java
index 005db62121feded0b856e211ad66bb0ffb700ea3..ec175d775f4f23b81ad729542d263063ee86edfa 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/Message.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/Message.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import java.util.List;
 
@@ -42,19 +42,7 @@ import lombok.ToString;
 @AllArgsConstructor
 @ToString
 @Builder
-class Message {
-
-	@RequiredArgsConstructor
-	public enum ReplyOption {
-		POSSIBLE(0), MANDATORY(1), FORBIDDEN(2);
-
-		private final int numValue;
-
-		@JsonValue
-		public int toValue() {
-			return numValue;
-		}
-	}
+public class Message {
 
 	@RequiredArgsConstructor
 	public enum EidasLevel {
@@ -80,6 +68,7 @@ class Message {
 	@JsonProperty("body")
 	private String mailBody;
 
+	@JsonProperty("isHtml")
 	private boolean isHtml;
 
 	@JsonProperty("replyAction")
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MessageAttachment.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachment.java
similarity index 91%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MessageAttachment.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachment.java
index f3cf57178c6b13ed7fe35c76402d3890e42394b4..d1612fa7063dccd9c5dd5a198e28e82109a95629 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MessageAttachment.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachment.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import lombok.AllArgsConstructor;
 import lombok.Builder;
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/AttachmentService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentService.java
similarity index 59%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/AttachmentService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentService.java
index 70ceb28ba84759c28087563ece4f4974bf436117..0b1d1ef828a7258513cd7e8e0216586869b10ea0 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/AttachmentService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,32 +21,39 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.Base64;
 
 import org.apache.commons.io.IOUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.util.Base64Utils;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.AttachmentFile;
+import de.ozgcloud.nachrichten.postfach.BinaryFileService;
+import de.ozgcloud.nachrichten.postfach.FileId;
+import de.ozgcloud.nachrichten.postfach.PersistPostfachNachrichtService;
+import lombok.val;
 
 @Service
-class AttachmentService {
+public class MessageAttachmentService {
 
 	@Autowired
-	private PersistPostfachMailService persistPostfachMailService;
+	private PersistPostfachNachrichtService persistPostfachNachrichtService;
 
 	@Autowired
 	private BinaryFileService binaryFileService;
 
-	MessageAttachment getMessageAttachment(FileId fileId) {
+	public MessageAttachment getMessageAttachment(FileId fileId) {
 		try {
+			val metadata = binaryFileService.getFile(fileId).getMetadata();
 			return MessageAttachment.builder()
-					.fileName(binaryFileService.getFile(fileId).getMetadata().getString("name"))
+					.fileName(metadata.getString("name"))
 					.content(getAttachmentContent(fileId))
 					.build();
 		} catch (IOException e) {
@@ -61,11 +68,17 @@ class AttachmentService {
 	}
 
 	private String encodeAttachmentContent(byte[] content) {
-		return Base64Utils.encodeToString(content);
+		return new String(Base64.getEncoder().encode(content));
 	}
 
-	String persistAttachment(String vorgangId, MessageAttachment attachment) {
-		return persistPostfachMailService.persistAttachment(vorgangId, attachment);
+	public String persistAttachment(String vorgangId, MessageAttachment attachment) {
+		return persistPostfachNachrichtService.persistAttachment(vorgangId, mapAttachmentFile(attachment));
+	}
+
+	AttachmentFile mapAttachmentFile(MessageAttachment attachment) {
+		return AttachmentFile.builder()
+				.name(attachment.getFileName())
+				.content(() -> IOUtils.toInputStream(attachment.getContent(), Charset.defaultCharset())).build();
 	}
 
 	InputStream getAttachmentContentStream(FileId fileId) {
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MockOsiPostfachConfiguration.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MockOsiPostfachConfiguration.java
similarity index 92%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MockOsiPostfachConfiguration.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MockOsiPostfachConfiguration.java
index 08e8d325f4b1a97380698c87fb219c318bab6018..d46ca54c7a3ca63c484c77f16aaf79ca8454f14a 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MockOsiPostfachConfiguration.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MockOsiPostfachConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MockOsiPostfachRestTemplate.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MockOsiPostfachRestTemplate.java
similarity index 92%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MockOsiPostfachRestTemplate.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MockOsiPostfachRestTemplate.java
index 1f6e9ed356e2b71dfb454e179e386f1b59e317bf..543602e24bf97e818eab92f7053e3b80ac1afbe5 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/MockOsiPostfachRestTemplate.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/MockOsiPostfachRestTemplate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpMethod;
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachMessageMapper.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachMessageMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..97b3af448732860dab2dad5f0c0b6c2bc65c8070
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachMessageMapper.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.osi;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.Named;
+import org.mapstruct.ReportingPolicy;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ozgcloud.nachrichten.postfach.FileId;
+import de.ozgcloud.nachrichten.postfach.PostfachAddress;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.StringBasedIdentifier;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN)
+public abstract class OsiPostfachMessageMapper {
+
+	private static final String POSTFACH_ADDRESS_VERSION = "1.0";
+	private static final int POSTFACH_ADDRESS_TYPE = 1;
+
+	@Autowired
+	private MessageAttachmentService messageAttachmentService;
+
+	@Mapping(target = "attachment", ignore = true)
+	@Mapping(target = "isHtml", constant = "true")
+	@Mapping(target = "rechtsverbindlich", constant = "false")
+	@Mapping(target = "eidasLevel", constant = "MEDIUM")
+	@Mapping(target = "postfachId", expression = "java(toPostfachId(nachricht))")
+	@Mapping(target = "mailBody", qualifiedByName = "replaceNewLine")
+	public abstract Message toOsiMessage(PostfachNachricht nachricht);
+
+	@Mapping(target = "createdBy", ignore = true)
+	@Mapping(target = "id", ignore = true)
+	@Mapping(target = "messageCode", ignore = true)
+	@Mapping(target = "sentAt", ignore = true)
+	@Mapping(target = "sentSuccessful", ignore = true)
+	@Mapping(target = "createdAt", expression = "java(java.time.ZonedDateTime.now())")
+	@Mapping(target = "direction", constant = "IN")
+	@Mapping(target = "attachments", expression = "java(persistAttachements(message.getVorgangId() ,message.getAttachments()))")
+	@Mapping(target = "postfachAddress", expression = "java(buildPostfachAddressByPostfachId(message.getPostfachId()))")
+	@Mapping(target = "mailBody", qualifiedByName = "clearReceivedMessage")
+	public abstract PostfachNachricht toPostfachNachricht(Message message);
+
+	List<MessageAttachment> map(List<String> attachedFileIds) {
+		return attachedFileIds.stream().map(FileId::from).map(fileId -> messageAttachmentService.getMessageAttachment(fileId)).toList();
+	}
+
+	List<String> persistAttachements(String vorgangId, List<MessageAttachment> attachments) {
+		return attachments.stream().map(attachment -> messageAttachmentService.persistAttachment(vorgangId, attachment)).toList();
+	}
+
+	@Mapping(target = "attachment", ignore = true)
+	@Mapping(target = "messageId", ignore = true)
+	String toPostfachId(PostfachNachricht nachricht) {
+		return Optional.ofNullable(nachricht.getPostfachAddress())
+				.map(PostfachAddress::getIdentifier)
+				.filter(StringBasedIdentifier.class::isInstance)
+				.map(StringBasedIdentifier.class::cast)
+				.map(StringBasedIdentifier::getPostfachId)
+				.orElse(nachricht.getPostfachId());
+	}
+
+	PostfachAddress buildPostfachAddressByPostfachId(String postfachId) {
+		return PostfachAddress.builder()
+				.type(POSTFACH_ADDRESS_TYPE)
+				.version(POSTFACH_ADDRESS_VERSION)
+				.identifier(StringBasedIdentifier.builder().postfachId(postfachId).build())
+				.serviceKontoType(OsiPostfachRemoteService.POSTFACH_TYPE)
+				.build();
+
+	}
+
+	@Named("replaceNewLine")
+	String replaceNewlines(String nachricht) {
+		return Optional.ofNullable(nachricht).map(str -> str.replaceAll("(\r\n|\n)", "<br>")).orElse(null);
+	}
+
+	@Named("clearReceivedMessage")
+	String clearReceivedMessage(String nachricht) {
+		return Optional.ofNullable(nachricht).map(str -> str.replace("&amp;", "&")).orElse(null);
+	}
+}
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachProperties.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachProperties.java
similarity index 89%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachProperties.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachProperties.java
index 09e5a278ff52b22819bb679464c437053b3b3efb..4912cdac4867e3be1640ed9c9cc4a3c54138c89c 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachProperties.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachProperties.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -34,9 +34,9 @@ import lombok.Setter;
 @Setter
 @Configuration
 @ConfigurationProperties(prefix = OsiPostfachProperties.PROXY_API_PREFIX)
-class OsiPostfachProperties {
+public class OsiPostfachProperties {
 
-	static final String PREFIX = "kop.osi.postfach";
+	static final String PREFIX = "ozgcloud.osi.postfach";
 	static final String PROXY_API_PREFIX = PREFIX + ".proxyapi";
 
 	private String url;
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachService.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteService.java
similarity index 71%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachService.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteService.java
index 92ef02eb3ef59754cf4593625d14839b7d611e65..cd56c72085a91e1d905b4f43068f9306a8a36216 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachService.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,17 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import java.util.Arrays;
 import java.util.Objects;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
 
-import javax.annotation.PostConstruct;
+import jakarta.annotation.PostConstruct;
 
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.ResponseEntity;
@@ -40,12 +41,22 @@ import org.springframework.web.client.HttpClientErrorException;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import de.ozgcloud.nachrichten.postfach.NotConfiguredException;
+import de.ozgcloud.nachrichten.postfach.PostfachBadRequestException;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.PostfachRemoteService;
+import de.ozgcloud.nachrichten.postfach.PostfachRuntimeException;
 import lombok.extern.log4j.Log4j2;
 
 @Service
 @Log4j2
-class OsiPostfachService {
+@ConditionalOnProperty(prefix = OsiPostfachProperties.PROXY_API_PREFIX, name = { "url", "key", "realm" })
+class OsiPostfachRemoteService implements PostfachRemoteService {
 
+	static final String POSTFACH_TYPE = "OSI";
+
+	@Autowired
+	private OsiPostfachMessageMapper mapper;
 	@Autowired
 	private OsiPostfachProperties properties;
 	@Autowired(required = false)
@@ -53,12 +64,26 @@ class OsiPostfachService {
 
 	@PostConstruct
 	public void init() {
+		LOG.info("OSI Postfach remote service initialized.");
 		if (isNotConfigured()) {
 			LOG.warn("OSI Postfach Api not configured. Failed to read config " + OsiPostfachProperties.PROXY_API_PREFIX);
 		}
 	}
 
-	public Stream<Message> getAllMessages() {
+	@Override
+	public void sendMessage(PostfachNachricht nachricht) {
+		checkWhetherIsConfigured();
+
+		HttpEntity<Message> request = new HttpEntity<>(mapper.toOsiMessage(nachricht));
+
+		var response = executeHandlingException(
+				() -> restTemplate.exchange(properties.getUrl(), HttpMethod.POST, request, String.class));
+
+		sentFailed(response);
+	}
+
+	@Override
+	public Stream<PostfachNachricht> getAllMessages() {
 		checkWhetherIsConfigured();
 
 		ResponseEntity<Message[]> response = executeHandlingException(
@@ -68,18 +93,7 @@ class OsiPostfachService {
 			LOG.warn("OSI Postfach response with an empty body");
 			return Stream.empty();
 		}
-		return Arrays.stream(response.getBody());
-	}
-
-	public void sendMessage(Message message) {
-		checkWhetherIsConfigured();
-
-		HttpEntity<Message> request = new HttpEntity<>(message);
-
-		var response = executeHandlingException(
-				() -> restTemplate.exchange(properties.getUrl(), HttpMethod.POST, request, String.class));
-
-		sentFailed(response);
+		return Arrays.stream(response.getBody()).map(mapper::toPostfachNachricht);
 	}
 
 	private void sentFailed(ResponseEntity<String> response) {
@@ -92,6 +106,7 @@ class OsiPostfachService {
 		return StringUtils.equals(response.getBody(), String.valueOf(false));
 	}
 
+	@Override
 	public void deleteMessage(String messageId) {
 		checkWhetherIsConfigured();
 
@@ -105,10 +120,6 @@ class OsiPostfachService {
 		}
 	}
 
-	public boolean isConfigured() {
-		return !isNotConfigured();
-	}
-
 	private boolean isNotConfigured() {
 		return Objects.isNull(restTemplate) || Objects.isNull(properties.getUrl()) || Objects.isNull(properties.getKey());
 	}
@@ -117,9 +128,20 @@ class OsiPostfachService {
 		try {
 			return runnable.get();
 		} catch (HttpClientErrorException e) {
-			throw new OsiPostfachBadRequestException(e);
+			throw new PostfachBadRequestException(e);
 		} catch (RuntimeException e) {
-			throw new OsiPostfachRuntimeException(e);
+			throw new PostfachRuntimeException(e);
 		}
 	}
+
+	@Override
+	public String getPostfachType() {
+		return POSTFACH_TYPE;
+	}
+
+	@Override
+	public boolean isReplyAllowed() {
+		return true;
+	}
+
 }
\ No newline at end of file
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachServerProcessException.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachServerProcessException.java
new file mode 100644
index 0000000000000000000000000000000000000000..4dd4862e34cc5a308a7a2a91559c8aa0538f0341
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachServerProcessException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.osi;
+
+import de.ozgcloud.nachrichten.postfach.PostfachException;
+import de.ozgcloud.nachrichten.postfach.PostfachMessageCode;
+
+public class OsiPostfachServerProcessException extends PostfachException {// NOSONAR
+
+	private static final long serialVersionUID = 1L;
+
+	OsiPostfachServerProcessException() {
+		super("Postfach server returned false", PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE);
+	}
+}
\ No newline at end of file
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachConfiguration.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/PostfachConfiguration.java
similarity index 81%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachConfiguration.java
rename to nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/PostfachConfiguration.java
index cf84089d1730df6ea025acfa06c4e67bfbee8d85..e8fab9ce4f6c9bd2d90841ba635968c7e167a741 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/PostfachConfiguration.java
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/PostfachConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,17 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import java.util.Objects;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.http.HttpHost;
-import org.apache.http.auth.AuthScope;
-import org.apache.http.auth.UsernamePasswordCredentials;
-import org.apache.http.client.CredentialsProvider;
-import org.apache.http.impl.client.BasicCredentialsProvider;
-import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
+import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
+import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.core5.http.HttpHost;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.web.client.RestTemplateBuilder;
@@ -77,19 +78,21 @@ public class PostfachConfiguration implements RestTemplateCustomizer {
 				.setProxy(proxy).setDefaultCredentialsProvider(buildCredentialsProvider(proxy))
 				.build();
 
+		HttpClients.custom().build();
 		restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
 	}
 
 	private CredentialsProvider buildCredentialsProvider(HttpHost proxyHost) {
 		var proxyConfig = properties.getProxyConfiguration();
 
-		if (!proxyConfig.isAuthenticationRequired())
+		if (!proxyConfig.isAuthenticationRequired()) {
 			return null;
+		}
 
-		CredentialsProvider credsProvider = new BasicCredentialsProvider();
+		var credsProvider = new BasicCredentialsProvider();
 		credsProvider.setCredentials(
 				new AuthScope(proxyHost),
-				new UsernamePasswordCredentials(proxyConfig.getUsername(), proxyConfig.getPassword()));
+				new UsernamePasswordCredentials(proxyConfig.getUsername(), proxyConfig.getPassword().toCharArray()));
 		return credsProvider;
 	}
 
diff --git a/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/ReplyOption.java b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/ReplyOption.java
new file mode 100644
index 0000000000000000000000000000000000000000..148e61e4c736362216a0c90a3220307a36a5bfb4
--- /dev/null
+++ b/nachrichten-manager/src/main/java/de/ozgcloud/nachrichten/postfach/osi/ReplyOption.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.osi;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public enum ReplyOption {
+	POSSIBLE(0), MANDATORY(1), FORBIDDEN(2);
+
+	private final int numValue;
+
+	@JsonValue
+	public int toValue() {
+		return numValue;
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/nachrichten-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000000000000000000000000000000000..08abec6c597ed602bc6a36d5de3111b9a0d66a74
--- /dev/null
+++ b/nachrichten-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,20 @@
+net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientMetricAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientHealthAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientSecurityAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientTraceAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcDiscoveryClientAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonTraceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcAdviceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcHealthServiceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataConsulConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataEurekaConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataNacosConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataZookeeperConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcReflectionServiceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerMetricAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerSecurityAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerTraceAutoConfiguration
diff --git a/nachrichten-manager/src/main/resources/bayernid/PostfachnachrichtenServiceBy.wsdl b/nachrichten-manager/src/main/resources/bayernid/PostfachnachrichtenServiceBy.wsdl
new file mode 100644
index 0000000000000000000000000000000000000000..a2df76060c0568ed74ed70e6cc71fdc6a9005c98
--- /dev/null
+++ b/nachrichten-manager/src/main/resources/bayernid/PostfachnachrichtenServiceBy.wsdl
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions name="PostkorbKommService"
+	xmlns="http://schemas.xmlsoap.org/wsdl/"
+	xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+	xmlns:bsp="http://akdb.de/portal/gehaltsabrechnungen-bspnachricht"
+	xmlns:tns="urn:akdb:bsp:postkorb:komm:webservice"
+	xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+	targetNamespace="urn:akdb:bsp:postkorb:komm:webservice">
+	<types>
+		<xs:schema
+			targetNamespace='urn:akdb:bsp:postkorb:komm:webservice' version='1.1'
+			xmlns:tns='urn:akdb:bsp:postkorb:komm:webservice'
+			xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+			<xs:element name='sendBspNachricht'
+				type='tns:sendBspNachricht' />
+			<xs:complexType name='sendBspNachricht'>
+				<xs:sequence>
+					<xs:element minOccurs='1' name='okKommBspNachrichtInput'
+						type='xs:base64Binary' />
+				</xs:sequence>
+			</xs:complexType>
+			<xs:element name='sendBspNachrichtOutput'
+				type='tns:sendBspNachrichtOutput' />
+			<xs:complexType name='sendBspNachrichtOutput'>
+				<xs:sequence>
+					<xs:element minOccurs='1'
+						name='okKommBspNachrichtOutput' type='xs:base64Binary' />
+				</xs:sequence>
+			</xs:complexType>
+			<xs:element name='sendBspNachrichtNative'
+				type='tns:sendBspNachrichtNative' />
+			<xs:complexType name='sendBspNachrichtNative'>
+				<xs:sequence>
+					<xs:element minOccurs='1' name='bspNachricht'
+						type='xs:string' />
+				</xs:sequence>
+			</xs:complexType>
+			<xs:element name='sendBspNachrichtNativeOutput'
+				type='tns:sendBspNachrichtNativeOutput' />
+			<xs:complexType name='sendBspNachrichtNativeOutput'>
+				<xs:sequence>
+					<xs:element minOccurs='1' name='bspQuittung'
+						type='xs:string' />
+				</xs:sequence>
+			</xs:complexType>
+		</xs:schema>
+	</types>
+	<message name='PostkorbKommService_sendBspNachrichtInput'>
+		<part element='tns:sendBspNachricht'
+			name='okKommBspNachrichtInput'></part>
+	</message>
+	<message name='PostkorbKommService_sendBspNachrichtOutput'>
+		<part element='tns:sendBspNachrichtOutput'
+			name='sendBspNachrichtOutput'></part>
+	</message>
+	<message name='PostkorbKommService_sendBspNachrichtNativeInput'>
+		<part element='tns:sendBspNachrichtNative'
+			name='sendBspNachrichtNative'></part>
+	</message>
+	<message
+		name='PostkorbKommService_sendBspNachrichtNativeOutput'>
+		<part element='tns:sendBspNachrichtNativeOutput'
+			name='bspQuittung'></part>
+	</message>
+	<portType name='PostkorbKommPortType'>
+		<operation name='sendBspNachricht'>
+			<input message='tns:PostkorbKommService_sendBspNachrichtInput'></input>
+			<output
+				message='tns:PostkorbKommService_sendBspNachrichtOutput'></output>
+		</operation>
+		<operation name='sendBspNachrichtNative'>
+			<input
+				message='tns:PostkorbKommService_sendBspNachrichtNativeInput'></input>
+			<output
+				message='tns:PostkorbKommService_sendBspNachrichtNativeOutput'></output>
+		</operation>
+	</portType>
+	<binding name="PostkorbKommBinding"
+		type="tns:PostkorbKommPortType">
+		<soap:binding style="document"
+			transport="http://schemas.xmlsoap.org/soap/http" />
+		<operation name='sendBspNachricht'>
+			<soap:operation soapAction='' />
+			<input>
+				<soap:body use='literal' />
+			</input>
+			<output>
+				<soap:body use="literal" />
+			</output>
+		</operation>
+		<operation name='sendBspNachrichtNative'>
+			<soap:operation soapAction='' />
+			<input>
+				<soap:body use='literal' />
+			</input>
+			<output>
+				<soap:body use="literal" />
+			</output>
+		</operation>
+	</binding>
+	<service name="PostkorbKommService">
+		<port name="PostkorbKommPort" binding="tns:PostkorbKommBinding">
+			<!-- <soap:address location="${web-services-base- url}/bspservices/postkorbkomm" 
+				/> -->
+			<soap:address location="http://localhost:8080/bspx-postkorb-okkomm-ws/bspservices/postkorbkomm" />
+		</port>
+	</service>
+</definitions>
diff --git a/nachrichten-manager/src/main/resources/bayernid/bspnachrichten-2.13.xsd b/nachrichten-manager/src/main/resources/bayernid/bspnachrichten-2.13.xsd
new file mode 100644
index 0000000000000000000000000000000000000000..23b0e247d2bd9d2ab3f2206e4354d0c497844f28
--- /dev/null
+++ b/nachrichten-manager/src/main/resources/bayernid/bspnachrichten-2.13.xsd
@@ -0,0 +1,343 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Service- und Portalplattform
+    AKDB München, Geschäftsfeld eGovernment
+
+    Copyright (c) AKDB
+
+-->
+<xsd:schema targetNamespace="http://www.akdb.de/egov/bsp/nachrichten"
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  xmlns:bsp="http://www.akdb.de/egov/bsp/nachrichten"
+  elementFormDefault="qualified">
+
+  <xsd:element name="BspNachricht">
+    <xsd:annotation>
+      <xsd:appinfo>
+        <title>Nachricht für die Kommunikation zwischen Bürgerservice-Portal
+          und externen Fachverfahren</title>
+      </xsd:appinfo>
+      <xsd:documentation>Einheitliches Nachrichtenschema für die
+        Kommunikation zwischen Bürgerservice-Portal und externem Verfahren.
+        Nachrichten vom Bürgerservice-Portal an den Postkorb eines
+        Verfahrens
+        oder Nachrichten von den Verfahren an das Bürgerservice-Portal müssen
+        gemäß diesem Schema aufgebaut sein.
+      </xsd:documentation>
+    </xsd:annotation>
+    <xsd:complexType>
+      <xsd:sequence>
+        <xsd:element name="NachrichtenKopf" type="bsp:NachrichtenKopfType"/>
+        <xsd:element name="NachrichtenInhalt" type="bsp:NachrichtenInhaltType"/>
+      </xsd:sequence>
+      <xsd:attribute name="version" use="required">
+        <xsd:annotation>
+          <xsd:documentation>Dieses Attribut kennzeichnet die
+            Nachrichten-Version, z. B. "1.0", "1.1".</xsd:documentation>
+        </xsd:annotation>
+        <xsd:simpleType>
+           <xsd:restriction base="xsd:string">
+             <xsd:enumeration value="1.1"/>
+             <xsd:enumeration value="1.2"/>
+             <xsd:enumeration value="1.3"/>
+             <xsd:enumeration value="1.4"/>
+             <xsd:enumeration value="1.5"/>
+           </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
+      <xsd:attribute name="fassung" use="required" >
+        <xsd:annotation>
+          <xsd:documentation>Dieses Attribut kennzeichnet das Datum, an dem
+            die diesen Schemata im Status final produziert wurde. Format:
+            YYYY-MM-DD.</xsd:documentation>
+        </xsd:annotation>
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="2017-03-15"/>
+            <xsd:enumeration value="2018-04-01"/>
+            <xsd:enumeration value="2018-11-01"/>
+            <xsd:enumeration value="2019-06-28"/>
+            <xsd:enumeration value="2020-03-15"/>
+          </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
+      <xsd:attribute name="produkt" type="xsd:string" use="optional">
+        <xsd:annotation>
+          <xsd:documentation>In diesem Attribut ist der Name des Produktes
+            (der Software) einzutragen, mit dem diese Nachricht erstellt
+            worden ist. z.B. BSP, PWS</xsd:documentation>
+        </xsd:annotation>
+      </xsd:attribute>
+      <xsd:attribute name="produkthersteller" type="xsd:string" use="optional"/>
+      <xsd:attribute name="produktversion" type="xsd:string" use="optional"/>
+    </xsd:complexType>
+  </xsd:element>
+
+  <xsd:element name="BspQuittung">
+    <xsd:annotation>
+      <xsd:appinfo>
+        <title>Quittung über den Empfang einer BSO-Nachricht</title>
+      </xsd:appinfo>
+      <xsd:documentation>Zu einer empfangenen BSP-Nachricht wird eine
+                Quittung geliefert, die bestätigt, dass die Nachricht übernommen wurde
+                oder aufgrund eines technischen oder fachlichen Fehlers abgewiesen wurde.
+      </xsd:documentation>
+    </xsd:annotation>
+    <xsd:complexType>
+      <xsd:sequence>
+        <xsd:element name="AnnahmeErfolgreich" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
+          <xsd:element name="ErgebnisStatus" type="bsp:SchluesseltabelleType" minOccurs="1" maxOccurs="1">
+            <xsd:annotation>
+              <xsd:documentation>Schluesseltabelle 9006 (0 (erfolgreich angenommen), 99 (sonstiger technischer Fehler), ...)</xsd:documentation>
+            </xsd:annotation>
+          </xsd:element>
+        <xsd:element name="ErgaenzendeHinweise" type="xsd:string" minOccurs="0" maxOccurs="1"/>
+      </xsd:sequence>
+      <xsd:attribute name="version" use="required">
+        <xsd:annotation>
+          <xsd:documentation>Dieses Attribut kennzeichnet die
+            Nachrichten-Version, z. B. "1.0", "1.1".</xsd:documentation>
+        </xsd:annotation>
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="1.1"/>
+			<xsd:enumeration value="1.2"/>
+            <xsd:enumeration value="1.3"/>
+            <xsd:enumeration value="1.4"/>
+            <xsd:enumeration value="1.5"/>
+           </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
+      <xsd:attribute name="fassung" use="required">
+        <xsd:annotation>
+          <xsd:documentation>Dieses Attribut kennzeichnet das Datum, an dem
+            die diesen Schemata im Status final produziert wurde. Format:
+            YYYY-MM-DD.</xsd:documentation>
+        </xsd:annotation>
+        <xsd:simpleType>
+          <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="2017-03-15"/>
+            <xsd:enumeration value="2018-04-01"/>
+            <xsd:enumeration value="2018-11-01"/>
+            <xsd:enumeration value="2019-06-28"/>
+            <xsd:enumeration value="2020-03-15"/>			
+          </xsd:restriction>
+        </xsd:simpleType>
+      </xsd:attribute>
+      <xsd:attribute name="produkt" type="xsd:string" use="optional">
+        <xsd:annotation>
+          <xsd:documentation>In diesem Attribut ist der Name des Produktes
+            (der Software) einzutragen, mit dem diese Nachricht erstellt
+            worden ist. z.B. BSP, PWS</xsd:documentation>
+        </xsd:annotation>
+      </xsd:attribute>
+      <xsd:attribute name="produkthersteller" type="xsd:string" use="optional"/>
+      <xsd:attribute name="produktversion" type="xsd:string" use="optional"/>
+    </xsd:complexType>
+  </xsd:element>
+
+  <xsd:complexType name="NachrichtenKopfType">
+    <xsd:sequence>
+      <xsd:element name="Identifikation.Nachricht" type="bsp:Identifikation.NachrichtType" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="Anwenderkennung" type="xsd:string" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation> Die Anwenderkennung stellt Informationen über die absendende Person
+          zur Verfügung und dient der Protokollierung.
+          Anhand dieser Kennung kann die absendende Person identifiziert werden.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Absender" type="bsp:AbsenderType" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="Empfaenger" type="bsp:EmpfaengerType"  maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="AntwortAuf" type="xsd:string" maxOccurs="1" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation>Eine Nachricht kann mit einer exisiterenden
+            Nachricht in Beziehung gebracht werden als Antwortnachricht oder
+            weitergeleitete Nachricht. Der Bezug erfolgt hierbei über die
+            NachrichtenId.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="WeiterleitungZu" type="xsd:string" minOccurs="0"/>
+      <xsd:element name="lesebestaetigungAntwortAdresse" type="xsd:string" minOccurs="0"/>
+    </xsd:sequence>
+  </xsd:complexType>
+  <xsd:complexType name="Identifikation.NachrichtType">
+    <xsd:sequence>
+      <xsd:element name="Ereignis" type="bsp:SchluesseltabelleType">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9001, Schluessel: BspNachricht
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Erstellungszeitpunkt" type="xsd:dateTime" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="NachrichtenId" type="xsd:string" maxOccurs="1" minOccurs="1">
+        <xsd:annotation>
+          <xsd:documentation>eine beliebige, eindeutige ID, die durch den
+            erstellenden Client generiert wird. Zusammen mit
+            Erstellungszeitpunkt und Absender kann eine Nachricht bsp-global
+            eindeutig identifiziert werden.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="AbsenderType">
+    <xsd:sequence>
+      <xsd:element name="PostkorbId" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Verfahren" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Dienst" type="bsp:NonEmptyString" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Mandant" type="bsp:NonEmptyString" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Gemeindeschluessel" type="bsp:SchluesseltabelleType" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation>Der amtliche Gemeindeschlüssel (AGS).
+            Als Tabellennummer ist hier die 36 (OSCI-XMeld-Schlüsseltabelle "Amtlicher Gemeindeschluessel") zu verwenden.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Name" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Anschrift" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Email" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Telefon" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Hyperlink" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+   </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="EmpfaengerType">
+    <xsd:sequence>
+      <xsd:element name="PostkorbId" type="xsd:string" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="Verfahren" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Dienst" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Mandant" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Gemeindeschluessel" type="bsp:SchluesseltabelleType" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation>Der amtliche Gemeindeschlüssel (AGS).
+            Als Tabellennummer ist hier die 36 (OSCI-XMeld-Schlüsseltabelle "Amtlicher Gemeindeschluessel") zu verwenden.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Name" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+      <xsd:element name="Anschrift" type="xsd:string" maxOccurs="1" minOccurs="0"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="NachrichtenInhaltType">
+    <xsd:sequence>
+      <xsd:element name="Betreff" type="bsp:NonEmptyString" maxOccurs="1"   minOccurs="1"/>
+      <xsd:element name="Kategorie" type="bsp:SchluesseltabelleType" minOccurs="0">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9002 (KAT_STATUS, KAT_INFOBSP, ...)
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:choice minOccurs="0">
+        <xsd:element name="StorkQaaLevel" type="bsp:StorkQaaLevel"/>
+        <xsd:element name="NpaGescheutzt" type="xsd:boolean" >
+          <!-- deprecated, wird durch StorkQaaLevel="STORK-QAA-Level-1" ersetzt -->
+          <xsd:annotation>
+            <xsd:documentation>
+              Diese Nachricht kann im BüsP-Postkorb nur nach
+              vorheriger Anmeldung mit dem nPA gelesen werden.
+            </xsd:documentation>
+          </xsd:annotation>
+        </xsd:element>
+      </xsd:choice>
+      <xsd:element name="ZuVorgang" type="bsp:ZuVorgangType" minOccurs="0"/>
+      <xsd:element name="FreiText" type="bsp:FreiTextType"/>
+      <xsd:element name="DataContainer" type="bsp:DataContainerType" minOccurs="0" maxOccurs="unbounded"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="ZuVorgangType">
+    <xsd:annotation>
+      <xsd:documentation>VorgangsName oder VorgangsId müssen angegeben
+        werden. Es können auch beide angegeben werden.</xsd:documentation>
+    </xsd:annotation>
+    <xsd:sequence minOccurs="0">
+      <xsd:element name="VorgangsName" type="xsd:string"/>
+      <xsd:element name="VorgangsId" type="xsd:string"/>
+      <xsd:element name="VorgangStatus" type="bsp:SchluesseltabelleType">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9003 (ST_ERHALTEN, ST_GELESEN,...)
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="FreiTextType">
+    <xsd:sequence>
+      <xsd:element name="Encoding" type="bsp:SchluesseltabelleType" maxOccurs="1" minOccurs="1">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9004 (text/plain, text/html, ...)
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+      <xsd:element name="Text" type="bsp:NonEmptyString" maxOccurs="1" minOccurs="1">
+        <xsd:annotation>
+          <xsd:documentation>
+            Wenn als Encoding text/plain festgelegt ist, so wird die Zeichensequenz "\n" als ein Zeilenvorschub interpretiert.
+            Das Backslash-Zeichen (\) wird mit einem weiteren Backslash-Zeichen entwertet.
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="DataContainerType">
+    <xsd:sequence minOccurs="0">
+      <xsd:element name="Inhalt" type="xsd:base64Binary" maxOccurs="1" minOccurs="1"/>
+      <xsd:element name="FileName" maxOccurs="1" minOccurs="0">
+          <xsd:simpleType>
+            <xsd:restriction base="xsd:string">
+              <xsd:maxLength value="255"/>
+            </xsd:restriction>
+          </xsd:simpleType>
+      </xsd:element>
+      <xsd:element name="FileType" type="bsp:SchluesseltabelleType" maxOccurs="1" minOccurs="1">
+        <xsd:annotation>
+          <xsd:documentation>Schluesseltabelle 9005 (application/pdf, text/html, ...)
+          </xsd:documentation>
+        </xsd:annotation>
+      </xsd:element>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="SchluesseltabelleType">
+    <xsd:annotation>
+      <xsd:documentation>Dieser Datentyp wird für Schlüsselwerte benötigt.
+        Mit dem Datentyp SchluesseltabelleType übermittelt man den Schlüssel
+        und die Nummer der Tabelle, in der das Schlüssel-Wert Paar definiert
+        worden ist.
+      </xsd:documentation>
+    </xsd:annotation>
+    <xsd:sequence>
+      <xsd:element name="Tabelle" type="xsd:string"/>
+      <xsd:element name="Schluessel" type="xsd:string"/>
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:simpleType name="StorkQaaLevel">
+    <xsd:restriction base="xsd:string">
+      <!-- since version 1.2 - deprecated -->
+      <xsd:enumeration value="LEVEL_1"/>
+      <xsd:enumeration value="LEVEL_2"/>
+      <xsd:enumeration value="LEVEL_3"/>
+      <xsd:enumeration value="LEVEL_4"/>
+      <!--  since version 1.3 -->
+      <xsd:enumeration value="STORK-QAA-Level-1"/>
+      <xsd:enumeration value="STORK-QAA-Level-2"/>
+      <xsd:enumeration value="STORK-QAA-Level-3"/>
+      <xsd:enumeration value="STORK-QAA-Level-4"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+  <xsd:simpleType name="NonEmptyString">
+    <xsd:restriction base="xsd:string">
+      <xsd:minLength value="1"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+</xsd:schema>
+
+
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeRemoteServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeRemoteServiceTest.java
similarity index 88%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeRemoteServiceTest.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeRemoteServiceTest.java
index 38571099bf37ba5037c0a7425cc3023161b05344..7771926a09161b5debb325dde629681bc0efbad8 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeRemoteServiceTest.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeRemoteServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.attributes;
+package de.ozgcloud.nachrichten.attributes;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -35,10 +35,10 @@ import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttributeValue;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcSetClientAttributeRequest;
+import de.ozgcloud.vorgang.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcAccessPermission;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttributeValue;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcSetClientAttributeRequest;
 
 class ClientAttributeRemoteServiceTest {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeServiceTest.java
similarity index 94%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeServiceTest.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeServiceTest.java
index 35e581995c7405a52ac1bd79177829e08bfac567..374967da33b61e9385dad9ee23098f954674e777 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeServiceTest.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.attributes;
+package de.ozgcloud.nachrichten.attributes;
 
 import static org.mockito.Mockito.*;
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/attributes/GrpcClientAttributeTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/GrpcClientAttributeTestFactory.java
similarity index 81%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/attributes/GrpcClientAttributeTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/GrpcClientAttributeTestFactory.java
index e804ea6cfb07631fe00abca632286717cb0c8f55..7593a73b2b0e0e84d0180e0bd3371ad0505539ec 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/attributes/GrpcClientAttributeTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/GrpcClientAttributeTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.attributes;
+package de.ozgcloud.nachrichten.attributes;
 
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttributeValue;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcAccessPermission;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttribute;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttributeValue;
 
 public class GrpcClientAttributeTestFactory {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/attributes/GrpcSetClientAttributeRequestTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/GrpcSetClientAttributeRequestTestFactory.java
similarity index 82%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/attributes/GrpcSetClientAttributeRequestTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/GrpcSetClientAttributeRequestTestFactory.java
index 3a932a0337b2aac6284689e79068d60be2af9576..f4a3c3007c6b5b47c530fa4898f400c0a6dfc39a 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/attributes/GrpcSetClientAttributeRequestTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/attributes/GrpcSetClientAttributeRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.attributes;
+package de.ozgcloud.nachrichten.attributes;
 
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcSetClientAttributeRequest;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcAccessPermission;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttribute;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcSetClientAttributeRequest;
 
 class GrpcSetClientAttributeRequestTestFactory {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/email/EMailServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/EMailServiceTest.java
similarity index 95%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/email/EMailServiceTest.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/EMailServiceTest.java
index 2ef4b812b6e1e691d30ce9379b016f12b35bd028..8da592d7ed496d183701e745d80174051773658c 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/email/EMailServiceTest.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/EMailServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,17 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
-import static de.itvsh.ozg.mail.email.MailSendRequestTestFactory.*;
+import static de.ozgcloud.nachrichten.email.MailSendRequestTestFactory.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
-import javax.activation.DataSource;
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
+import jakarta.activation.DataSource;
+import jakarta.mail.MessagingException;
+import jakarta.mail.internet.MimeMessage;
 
-import lombok.SneakyThrows;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -43,7 +42,7 @@ import org.springframework.mail.MailSendException;
 import org.springframework.mail.javamail.JavaMailSender;
 import org.springframework.mail.javamail.MimeMessageHelper;
 
-import java.util.Arrays;
+import lombok.SneakyThrows;
 
 class EMailServiceTest {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/email/EmailGrpcServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/EmailGrpcServiceTest.java
similarity index 96%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/email/EmailGrpcServiceTest.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/EmailGrpcServiceTest.java
index fca733942cad5aeff082191631a4a0e9e5751577..d8a8332020da794345301ce0526899e0d585ec9f 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/email/EmailGrpcServiceTest.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/EmailGrpcServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import io.grpc.stub.StreamObserver;
 import lombok.SneakyThrows;
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/email/GrpcNotificationRecipientsTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/GrpcNotificationRecipientsTestFactory.java
similarity index 93%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/email/GrpcNotificationRecipientsTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/GrpcNotificationRecipientsTestFactory.java
index d5fe98acee003d4de7b813608a9991acb4a716a3..223c85b719ff5064d5d9850464f2923309054139 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/email/GrpcNotificationRecipientsTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/GrpcNotificationRecipientsTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 public class GrpcNotificationRecipientsTestFactory {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/email/GrpcRecipientTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/GrpcRecipientTestFactory.java
similarity index 92%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/email/GrpcRecipientTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/GrpcRecipientTestFactory.java
index 6183610939a94790ef538b7e8c0e6b27de92a331..a9350ed4848d0972ed7a6a233e8412888a87b8c0 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/email/GrpcRecipientTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/GrpcRecipientTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 public class GrpcRecipientTestFactory {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/email/MailRecipientTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailRecipientTestFactory.java
similarity index 92%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/email/MailRecipientTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailRecipientTestFactory.java
index 83bed7ac5de89c2aa0409a4c2db94d0e5d11edef..476b56a7c6cb8a3ef0da04e0eb84b90951ff5f78 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/email/MailRecipientTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailRecipientTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 public class MailRecipientTestFactory {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSendErrorEventTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSendErrorEventTestFactory.java
similarity index 91%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSendErrorEventTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSendErrorEventTestFactory.java
index e737a4f046209331b7c019dc75212774740c6d2c..89ced29c02d8bd69a7ed99e68d93cc2fe8c0e8b0 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSendErrorEventTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSendErrorEventTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 public class MailSendErrorEventTestFactory {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSendRequestTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSendRequestTestFactory.java
similarity index 90%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSendRequestTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSendRequestTestFactory.java
index 9e2573785097d7cafded7b59dc1bbe6426200a24..fbb06c7280c8d7d7bbd9c90d8a16cf3bf3bef313 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSendRequestTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSendRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import java.util.UUID;
 
-import javax.mail.util.ByteArrayDataSource;
-
-import de.itvsh.ozg.mail.email.MailSendRequest.MailAttachment;
+import de.ozgcloud.nachrichten.email.MailSendRequest.MailAttachment;
+import jakarta.mail.util.ByteArrayDataSource;
 
 class MailSendRequestTestFactory {
 
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSentEventTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSentEventTestFactory.java
similarity index 91%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSentEventTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSentEventTestFactory.java
index 3a439b0f348ff0974a285ffce0cf4529e5786cce..b7a75c6d04ef2393a2410fbd480a14666435e016 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/email/MailSentEventTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/email/MailSentEventTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 public class MailSentEventTestFactory {
 
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachAddressTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachAddressTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..45fceb52dd52f978f23a9f71b2e5a64005759fd7
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachAddressTestFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.common.GrpcProperty;
+
+public class GrpcPostfachAddressTestFactory {
+
+	public static GrpcPostfachAddress create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcPostfachAddress.Builder createBuilder() {
+		return GrpcPostfachAddress.newBuilder()
+				.setType(PostfachAddressTestFactory.TYPE)
+				.setIdentifier(createIdentifier())
+				.setVersion(PostfachAddressTestFactory.VERSION)
+				.setServiceKontoType(PostfachTestFactory.POSTFACH_TYPE);
+	}
+
+	public static GrpcObject createIdentifier() {
+		return GrpcObject.newBuilder()
+				.addProperty(GrpcProperty.newBuilder()
+						.setName(PostfachNachricht.FIELD_POSTFACH_ID)
+						.addValue(PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE)
+						.build())
+				.build();
+	}
+}
\ No newline at end of file
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcPostfachMailTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachMailTestFactory.java
similarity index 73%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcPostfachMailTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachMailTestFactory.java
index 67ae8ce4fbc70027e09cb5bba60a6f2e09822dfd..fd40280f67f54fe8c79bc272c69811bda97c497a 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcPostfachMailTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcPostfachMailTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
-import static de.itvsh.ozg.mail.postfach.MessageTestFactory.*;
-import static de.itvsh.ozg.mail.postfach.PostfachMailTestFactory.*;
+import static de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory.*;
+import static de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory.*;
 
 public class GrpcPostfachMailTestFactory {
 
@@ -37,6 +37,7 @@ public class GrpcPostfachMailTestFactory {
 				.setId(ID)
 				.setVorgangId(VORGANG_ID)
 				.setPostfachId(POSTFACH_ID)
+				.setPostfachAddress(GrpcPostfachAddressTestFactory.create())
 				.setCreatedAt(CREATED_AT_STR)
 				.setCreatedBy(CREATED_BY)
 				.setSentAt(SENT_AT_STR)
@@ -44,8 +45,8 @@ public class GrpcPostfachMailTestFactory {
 				.setMessageCode(MESSAGE_CODE)
 				.setDirection(GrpcDirection.valueOf(DIRECTION.name()))
 				.setSubject(SUBJECT)
-				.setMailBody(MAIL_BODY)
-				.setReplyOption(REPLY_OPTION.name())
-				.addAllAttachment(PostfachMailTestFactory.ATTACHMENTS);
+				.setMailBody(PostfachNachrichtTestFactory.MAIL_BODY)
+				.setReplyOption(PostfachNachrichtTestFactory.REPLY_OPTION.name())
+				.addAllAttachment(PostfachNachrichtTestFactory.ATTACHMENTS);
 	}
 }
\ No newline at end of file
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcResendPostfachMailRequestTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcResendPostfachMailRequestTestFactory.java
similarity index 84%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcResendPostfachMailRequestTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcResendPostfachMailRequestTestFactory.java
index 4746b78629ba552aa6afc61a60e5174ec4c0abcb..12962e507fadeff76e1d6d0dde89f78b60c35744 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcResendPostfachMailRequestTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcResendPostfachMailRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import java.util.UUID;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcCallContext;
-import de.itvsh.ozg.pluto.grpc.command.GrpcUser;
+import de.ozgcloud.vorgang.grpc.command.GrpcCallContext;
+import de.ozgcloud.vorgang.grpc.command.GrpcUser;
 
 public class GrpcResendPostfachMailRequestTestFactory {
 
@@ -41,6 +41,6 @@ public class GrpcResendPostfachMailRequestTestFactory {
 		return GrpcResendPostfachMailRequest.newBuilder()
 				.setContext(GrpcCallContext.newBuilder().setUser(GrpcUser.newBuilder().setId(USER_ID).build()).build())
 				.setCommandId(COMMAND_ID)
-				.setPostfachMailId(PostfachMailTestFactory.ID);
+				.setPostfachMailId(PostfachNachrichtTestFactory.ID);
 	}
 }
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcSaveNachrichtDraftRequestTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcSaveNachrichtDraftRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..904c223e0be31a9870882dbf34bd12c50eba027a
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcSaveNachrichtDraftRequestTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+
+public class GrpcSaveNachrichtDraftRequestTestFactory {
+
+	static GrpcSaveNachrichtDraftRequest create() {
+		return createBuilder().build();
+	}
+
+	static GrpcSaveNachrichtDraftRequest.Builder createBuilder() {
+		return GrpcSaveNachrichtDraftRequest.newBuilder()
+				.setVorgangId(MessageTestFactory.VORGANG_ID);
+
+	}
+}
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcSendPostfachMailRequestTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcSendPostfachMailRequestTestFactory.java
similarity index 88%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcSendPostfachMailRequestTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcSendPostfachMailRequestTestFactory.java
index de307cc1f6d46a52e3f223b3509633efd3cef6eb..6635cfd6ecb67758f6310a406a15feb45c3b4171 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/GrpcSendPostfachMailRequestTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/GrpcSendPostfachMailRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import java.util.UUID;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcCallContext;
-import de.itvsh.ozg.pluto.grpc.command.GrpcUser;
+import de.ozgcloud.vorgang.grpc.command.GrpcCallContext;
+import de.ozgcloud.vorgang.grpc.command.GrpcUser;
 
 class GrpcSendPostfachMailRequestTestFactory {
 
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachAddressTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachAddressTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..572b41d8e42e75401ac97d5b61c31b259cdd4b45
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachAddressTestFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+
+public class PostfachAddressTestFactory {
+
+	public final static int TYPE = 1;
+	public static final String STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE = MessageTestFactory.POSTFACH_ID;
+	public final static StringBasedIdentifier IDENTIFIER = StringBasedIdentifier.builder().postfachId(STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE)
+			.build();
+	public static final String VERSION = "1.0";
+
+	public static PostfachAddress create() {
+		return createBuilder().build();
+	}
+
+	public static PostfachAddress.PostfachAddressBuilder createBuilder() {
+		return PostfachAddress.builder()
+				.type(TYPE)
+				.identifier(IDENTIFIER)
+				.version(VERSION)
+				.serviceKontoType(PostfachTestFactory.POSTFACH_TYPE);
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d26e95a78e852e6d2c3c0f678a0151325a82360
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction;
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+
+class PostfachEventListenerTest {
+
+	@InjectMocks
+	private PostfachEventListener listener;
+
+	@Mock
+	private PostfachService service;
+	@Mock
+	private Command command;
+
+	@Captor
+	private ArgumentCaptor<PostfachNachricht> nachrichtCaptor;
+
+	@DisplayName("Send postfach nachricht")
+	@Nested
+	class TestSendPostfachNachricht {
+
+		private static final String COMMAND_ID = UUID.randomUUID().toString();
+		private static final String USER_ID = PostfachNachrichtTestFactory.CREATED_BY;
+
+		@BeforeEach
+		void mockCommand() {
+			when(command.getId()).thenReturn(COMMAND_ID);
+			when(command.getCreatedBy()).thenReturn(USER_ID);
+			when(command.getVorgangId()).thenReturn(MessageTestFactory.VORGANG_ID);
+			when(command.getRelationId()).thenReturn(MessageTestFactory.VORGANG_ID);
+			when(command.getBodyObject()).thenReturn(buildCommandBody());
+		}
+
+		@Test
+		void shouldCallService() {
+			listener.sendPostfachNachricht(new CommandCreatedEvent(command));
+
+			verify(service).sendMail(eq(COMMAND_ID), eq(USER_ID), nachrichtCaptor.capture());
+			assertThat(nachrichtCaptor.getValue())
+					.usingRecursiveComparison().ignoringFields("id", "createdAt", "messageCode", "messageId", "sentAt", "sentSuccessful")
+					.isEqualTo(PostfachNachrichtTestFactory.createBuilder().direction(Direction.OUT).build());
+		}
+
+		@Test
+		void shouldNotHaveIdForNewNachricht() {
+			listener.sendPostfachNachricht(new CommandCreatedEvent(command));
+
+			verify(service).sendMail(eq(COMMAND_ID), eq(USER_ID), nachrichtCaptor.capture());
+			assertThat(nachrichtCaptor.getValue().getId()).isNull();
+		}
+
+		@Test
+		void shouldHaveIdForSavedNachricht() {
+			when(command.getRelationId()).thenReturn(PostfachNachrichtTestFactory.ID);
+
+			listener.sendPostfachNachricht(new CommandCreatedEvent(command));
+
+			verify(service).sendMail(eq(COMMAND_ID), eq(USER_ID), nachrichtCaptor.capture());
+			assertThat(nachrichtCaptor.getValue().getId()).isEqualTo(PostfachNachrichtTestFactory.ID);
+		}
+
+		@DisplayName("with postfachAddress")
+		@Nested
+		class TestWithPostfachAddress {
+
+			@BeforeEach
+			void mockCommandBodyObject() {
+				var body = buildCommandBody();
+				body.remove(PostfachNachricht.FIELD_POSTFACH_ID);
+				when(command.getBodyObject()).thenReturn(body);
+			}
+
+			@Test
+			void shouldHandleEmptyPostfachId() {
+				var postfachMailToSend = sendPostfachNachricht();
+
+				assertThat(postfachMailToSend.getPostfachId()).isNull();
+			}
+		}
+
+		@DisplayName("with postfachId")
+		@Nested
+		class TestWithPostfachId {
+
+			@BeforeEach
+			void mockCommandBodyObject() {
+				var body = buildCommandBody();
+				body.remove(PostfachNachricht.POSTFACH_ADDRESS_FIELD);
+				when(command.getBodyObject()).thenReturn(body);
+			}
+
+			@Test
+			void shouldHandleEmptyPostfachAddress() {
+				var postfachMailToSend = sendPostfachNachricht();
+
+				assertThat(postfachMailToSend.getPostfachAddress()).isNull();
+			}
+		}
+
+		private PostfachNachricht sendPostfachNachricht() {
+			listener.sendPostfachNachricht(new CommandCreatedEvent(command));
+
+			verify(service).sendMail(eq(COMMAND_ID), eq(USER_ID), nachrichtCaptor.capture());
+
+			return nachrichtCaptor.getValue();
+		}
+
+		private Map<String, Object> buildCommandBody() {
+			var map = new HashMap<String, Object>();
+			map.putAll(Map.of(
+					PostfachNachricht.FIELD_VORGANG_ID, "fake",
+					PostfachNachricht.FIELD_POSTFACH_ID, MessageTestFactory.POSTFACH_ID,
+					PostfachNachricht.POSTFACH_ADDRESS_FIELD, //
+					Map.of(PostfachAddress.VERSION_FIELD, PostfachAddressTestFactory.VERSION,
+							PostfachAddress.TYPE_FIELD, PostfachAddressTestFactory.TYPE,
+							PostfachAddress.SERVICEKONTO_TYPE_FIELD, PostfachTestFactory.POSTFACH_TYPE,
+							PostfachAddress.IDENTIFIER_FIELD, //
+							Map.of(PostfachNachricht.FIELD_POSTFACH_ID, PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE)),
+					PostfachNachricht.FIELD_SUBJECT, MessageTestFactory.SUBJECT,
+					PostfachNachricht.FIELD_MAIL_BODY, PostfachNachrichtTestFactory.MAIL_BODY,
+					PostfachNachricht.FIELD_REPLY_OPTION, PostfachNachrichtTestFactory.REPLY_OPTION.name(),
+					PostfachNachricht.FIELD_ATTACHMENTS, PostfachNachrichtTestFactory.ATTACHMENTS));
+			return map;
+		}
+	}
+
+	@DisplayName("Get string list value")
+	@Nested
+	class TestGetStringListValue {
+
+		@Test
+		void shouldReturnMultipleValuesFieldAsStringList() {
+			var commandBodyMap = new HashMap<String, Object>();
+			commandBodyMap.put(PostfachNachricht.FIELD_ATTACHMENTS, List.of("1", "2"));
+
+			var list = listener.getStringListValue(commandBodyMap, PostfachNachricht.FIELD_ATTACHMENTS);
+
+			assertThat(list).contains("1").contains("2");
+		}
+
+		@Test
+		void shouldReturnSingleValueFieldAsStringList() {
+			var commandBodyMap = new HashMap<String, Object>();
+			commandBodyMap.put(PostfachNachricht.FIELD_ATTACHMENTS, List.of("1", "2"));
+
+			var list = listener.getStringListValue(commandBodyMap, PostfachNachricht.FIELD_ATTACHMENTS);
+
+			assertThat(list).contains("1").contains("2");
+		}
+
+		@Test
+		void shouldReturnEmptyFieldValueAsEmptyCollection() {
+			var commandBodyMap = new HashMap<String, Object>();
+			commandBodyMap.put(PostfachNachricht.FIELD_ATTACHMENTS, Collections.emptyList());
+
+			var list = listener.getStringListValue(commandBodyMap, PostfachNachricht.FIELD_ATTACHMENTS);
+
+			assertThat(list).isEmpty();
+		}
+
+		@Test
+		void shouldReturnEmptyFieldAsEmptyCollection() {
+			var commandBodyMap = new HashMap<String, Object>();
+
+			var list = listener.getStringListValue(commandBodyMap, PostfachNachricht.FIELD_ATTACHMENTS);
+
+			assertThat(list).isEmpty();
+		}
+	}
+}
\ No newline at end of file
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachGrpcServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachGrpcServiceTest.java
similarity index 60%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachGrpcServiceTest.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachGrpcServiceTest.java
index 649fc76329c43800a5264855410a6257e142d664..dae4307117a5bc17b5b562544f6dedf5842dc2d5 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachGrpcServiceTest.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachGrpcServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.stream.Stream;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -37,26 +39,69 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
 import io.grpc.stub.StreamObserver;
 
 class PostfachGrpcServiceTest {
 
-	@InjectMocks // NOSONAR
+	@InjectMocks
 	private PostfachGrpcService service;
+
 	@Mock
 	private PostfachService postfachService;
+	@Mock
+	private GrpcPostfachNachrichtMapper nachrichtMapper;
+	@Mock
+	private PostfachMapper postfachMapper;
 
 	@Spy
-	private PostfachMailMapper mapper = Mappers.getMapper(PostfachMailMapper.class);
+	private PostfachNachrichtMapper mapper = Mappers.getMapper(PostfachNachrichtMapper.class);
+
+	@Nested
+	class TestSaveNachrichtDraft {
+
+		@Mock
+		private StreamObserver<GrpcSaveNachrichtDraftResponse> responseObserver;
+
+		@BeforeEach
+		void init() {
+			when(nachrichtMapper.mapFromGrpc(any())).thenReturn(PostfachNachrichtTestFactory.create());
+		}
+
+		@Test
+		void shouldCallService() {
+			var nachricht = PostfachNachrichtTestFactory.create();
+			when(nachrichtMapper.mapFromGrpc(any())).thenReturn(nachricht);
+
+			service.saveNachrichtDraft(GrpcSaveNachrichtDraftRequestTestFactory.create(), responseObserver);
+
+			verify(postfachService).saveDraft(MessageTestFactory.VORGANG_ID, nachricht);
+		}
+
+		@Test
+		void shouldSendResponse() {
+			service.saveNachrichtDraft(GrpcSaveNachrichtDraftRequestTestFactory.create(), responseObserver);
+
+			verify(responseObserver).onNext(any());
+		}
+
+		@Test
+		void shouldCompleteCall() {
+			service.saveNachrichtDraft(GrpcSaveNachrichtDraftRequestTestFactory.create(), responseObserver);
+
+			verify(responseObserver).onCompleted();
+		}
+
+	}
 
 	@Nested
 	class TestSendMail {
 
-		@Mock // NOSONAR
+		@Mock
 		private StreamObserver<GrpcSendPostfachMailResponse> responseObserver;
 
-		@Captor // NOSONAR
-		private ArgumentCaptor<PostfachMail> mailCaptor;
+		@Captor
+		private ArgumentCaptor<PostfachNachricht> mailCaptor;
 
 		@Test
 		void shouldCallPostfachServiceWithCommandId() {
@@ -71,11 +116,11 @@ class PostfachGrpcServiceTest {
 
 			verify(postfachService).sendMail(anyString(), anyString(), mailCaptor.capture());
 			assertThat(mailCaptor.getValue()).usingRecursiveComparison()
-					.ignoringFields(PostfachMail.FIELD_MESSAGE_ID, PostfachMail.FIELD_CREATED_AT, PostfachMail.FIELD_CREATED_BY,
-							PostfachMail.FIELD_DIRECTION, PostfachMail.FIELD_SENT_SUCCESSFUL, PostfachMail.FIELD_SENT_AT,
-							PostfachMail.FIELD_MESSAGE_CODE,
-							PostfachMail.FIELD_ATTACHMENTS) // TODO remove this for sending attachments
-					.isEqualTo(PostfachMailTestFactory.create());
+					.ignoringFields(PostfachNachricht.FIELD_MESSAGE_ID, PostfachNachricht.FIELD_CREATED_AT, PostfachNachricht.FIELD_CREATED_BY,
+							PostfachNachricht.FIELD_DIRECTION, PostfachNachricht.FIELD_SENT_SUCCESSFUL, PostfachNachricht.FIELD_SENT_AT,
+							PostfachNachricht.FIELD_MESSAGE_CODE,
+							PostfachNachricht.FIELD_ATTACHMENTS) // TODO remove this for sending attachments
+					.isEqualTo(PostfachNachrichtTestFactory.create());
 		}
 
 		@Test
@@ -109,14 +154,14 @@ class PostfachGrpcServiceTest {
 
 		@BeforeEach
 		void init() {
-			request = GrpcFindPostfachMailRequest.newBuilder().setNachrichtId(PostfachMailTestFactory.ID).build();
+			request = GrpcFindPostfachMailRequest.newBuilder().setNachrichtId(PostfachNachrichtTestFactory.ID).build();
 		}
 
 		@Test
 		void shouldCallService() {
 			service.findPostfachMail(request, responseObserver);
 
-			verify(postfachService).findById(PostfachMailTestFactory.ID);
+			verify(postfachService).findById(PostfachNachrichtTestFactory.ID);
 		}
 
 		@Test
@@ -140,7 +185,7 @@ class PostfachGrpcServiceTest {
 		private static final String VORGANG_ID = "42";
 		private GrpcFindPostfachMailsRequest request;
 
-		@Mock // NOSONAR
+		@Mock
 		private StreamObserver<GrpcFindPostfachMailsResponse> responseObserver;
 
 		@BeforeEach
@@ -167,14 +212,14 @@ class PostfachGrpcServiceTest {
 	@Nested
 	class TestResendMail {
 
-		@Mock // NOSONAR
+		@Mock
 		private StreamObserver<GrpcResendPostfachMailResponse> responseObserver;
 
 		@Test
 		void shouldCallPostfachService() {
 			service.resendPostfachMail(GrpcResendPostfachMailRequestTestFactory.create(), responseObserver);
 
-			verify(postfachService).resendMail(GrpcResendPostfachMailRequestTestFactory.COMMAND_ID, PostfachMailTestFactory.ID);
+			verify(postfachService).resendMail(GrpcResendPostfachMailRequestTestFactory.COMMAND_ID, PostfachNachrichtTestFactory.ID);
 		}
 
 		@Test
@@ -197,7 +242,7 @@ class PostfachGrpcServiceTest {
 
 		private final GrpcIsPostfachConfiguredRequest request = GrpcIsPostfachConfiguredRequest.newBuilder().build();
 
-		@Mock // NOSONAR
+		@Mock
 		private StreamObserver<GrpcIsPostfachConfiguredResponse> responseObserver;
 
 		@Test
@@ -221,4 +266,66 @@ class PostfachGrpcServiceTest {
 			verify(responseObserver).onCompleted();
 		}
 	}
+
+	@Nested
+	class TestGetPostfachConfig {
+		private GrpcGetPostfachConfigRequest request = GrpcGetPostfachConfigRequest.newBuilder().build();
+
+		@Mock
+		private StreamObserver<GrpcGetPostfachConfigResponse> responseObserver;
+
+		@Test
+		void shouldSendResponse() {
+			service.getPostfachConfig(request, responseObserver);
+
+			verify(responseObserver).onNext(notNull());
+		}
+
+		@Test
+		void shouldCompleteCall() {
+			service.getPostfachConfig(request, responseObserver);
+
+			verify(responseObserver).onCompleted();
+		}
+
+		@Nested
+		class TestBuildGetPostfachConfigResponse {
+
+			@Test
+			void shouldReturnNotConfigured() {
+				var response = service.buildGetPostfachConfigResponse();
+
+				assertThat(response).isEqualTo(GrpcGetPostfachConfigResponse.newBuilder().setConfigured(false).build());
+			}
+
+			@Nested
+			class TestConfigured {
+
+				@Mock
+				private Postfach postfach;
+				@Mock
+				private GrpcPostfach grpcPostfach;
+
+				@BeforeEach
+				void setup() {
+					when(postfachService.getPostfachs()).thenReturn(Stream.of(postfach));
+					when(postfachMapper.toGrpc(postfach)).thenReturn(grpcPostfach);
+				}
+
+				@Test
+				void shouldReturnPostfachs() {
+					var response = service.buildGetPostfachConfigResponse();
+
+					assertThat(response.getConfigured()).isTrue();
+				}
+
+				@Test
+				void shouldSetPostfach() {
+					var response = service.buildGetPostfachConfigResponse();
+
+					assertThat(response.getPostfachList()).containsExactly(grpcPostfach);
+				}
+			}
+		}
+	}
 }
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachMapperTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..797ef5c4fc7ad26fe7f4ba4a8c5f70b9cede6f17
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachMapperTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+
+class PostfachMapperTest {
+
+	private PostfachMapper mapper = Mappers.getMapper(PostfachMapper.class);
+
+	@Test
+	void shouldMapType() {
+		var result = mapper.toGrpc(PostfachTestFactory.create());
+
+		assertThat(result.getType()).isEqualTo(PostfachTestFactory.POSTFACH_TYPE);
+	}
+
+	@Test
+	void shouldMapReplyAllowed() {
+		var result = mapper.toGrpc(PostfachTestFactory.create());
+
+		assertThat(result.getReplyAllowed()).isTrue();
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapperTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..06793b285502bae9b8fd6d4ecf37b832d3865506
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapperTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import lombok.SneakyThrows;
+
+class PostfachNachrichtMapperTest {
+
+	@InjectMocks
+	private PostfachNachrichtMapper mapper = Mappers.getMapper(PostfachNachrichtMapper.class);
+	@Mock
+	private GrpcObjectMapper grpcObjectMapper;
+
+	@DisplayName("From map")
+	@Nested
+	class TestFromMap {
+
+		@DisplayName("with existing postfachAddress")
+		@Nested
+		class TestWithExistingPostfachAddress {
+
+			@BeforeEach
+			void mockGrpcObjectMapper() {
+				when(grpcObjectMapper.fromMap(any())).thenReturn(GrpcPostfachAddressTestFactory.createIdentifier());
+			}
+
+			@Test
+			void shouldFillGrpcMail() {
+				var grpcMail = fromMap(PostfachNachrichtTestFactory.asMap());
+
+				assertThat(grpcMail).usingRecursiveComparison().isEqualTo(GrpcPostfachMailTestFactory.create());
+			}
+
+			@Test
+			void shouldCallGrpcObjectMapper() {
+				fromMap(getMapWithoutProperty(PostfachNachricht.FIELD_SENT_SUCCESSFUL));
+
+				verify(grpcObjectMapper).fromMap(any());
+			}
+
+			@Test
+			void shouldIgnoreSentSuccessful() {
+				var grpcMail = fromMap(getMapWithoutProperty(PostfachNachricht.FIELD_SENT_SUCCESSFUL));
+
+				assertThat(grpcMail.getSentSuccessful()).isFalse();
+			}
+
+			@Test
+			void shouldIgnoreSentAt() {
+				var grpcMail = fromMap(getMapWithoutProperty(PostfachNachricht.FIELD_SENT_AT));
+
+				assertThat(grpcMail.getSentAt()).isEmpty();
+			}
+
+			@ParameterizedTest
+			@ValueSource(strings = PostfachNachricht.FIELD_POSTFACH_ID)
+			void shouldMapDefaultOnNonExistingValues(String fieldName) {
+				var mapped = fromMap(getMapWithoutProperty(fieldName));
+
+				var fieldValue = getAttributeFromGrpcObject(mapped, fieldName);
+				assertThat((String) fieldValue).isEmpty();
+			}
+		}
+
+		@DisplayName("with missing postfachAddress")
+		@Nested
+		class TestWithMissinPostfachAddress {
+
+			@Test
+			void shouldNotThrowException() {
+				assertDoesNotThrow(() -> fromMap(getMapWithoutProperty(PostfachNachricht.POSTFACH_ADDRESS_FIELD)));
+			}
+		}
+
+		private GrpcPostfachMail fromMap(Map<String, Object> map) {
+			return mapper.fromMap(map);
+		}
+	}
+
+	@DisplayName("From map to postfachMail")
+	@Nested
+	class TestFromMapToPostfachMail {
+
+		@Test
+		void shouldMap() {
+			var mail = fromMapToPostfachMail(PostfachNachrichtTestFactory.asMap());
+
+			assertThat(mail).usingRecursiveComparison().isEqualTo(PostfachNachrichtTestFactory.create());
+		}
+
+		@DisplayName("with missing postfachAddress")
+		@Nested
+		class TestWithMissinPostfachAddress {
+
+			@Test
+			void shouldMapAsNull() {
+				var mail = fromMapToPostfachMail(getMapWithoutProperty(PostfachNachricht.POSTFACH_ADDRESS_FIELD));
+
+				assertThat(mail.getPostfachAddress()).isNull();
+			}
+
+			@Test
+			void shouldNotThrowExceptionOnMissingPostfachAddress() {
+				assertDoesNotThrow(() -> fromMapToPostfachMail(getMapWithoutProperty(PostfachNachricht.POSTFACH_ADDRESS_FIELD)));
+			}
+		}
+
+		@ParameterizedTest
+		@ValueSource(strings = PostfachNachricht.FIELD_POSTFACH_ID)
+		void shouldMapDefaultOnNonExistingValues(String fieldName) {
+			var mapped = fromMapToPostfachMail(getMapWithoutProperty(fieldName));
+
+			var fieldValue = getAttributeFromObject(mapped, fieldName);
+			assertThat((String) fieldValue).isEmpty();
+		}
+
+		private PostfachNachricht fromMapToPostfachMail(Map<String, Object> map) {
+			return mapper.fromMapToPostfachMail(map);
+		}
+	}
+
+	@DisplayName("From grpc mail")
+	@Nested
+	class TestFromGrpcMail {
+
+		@Test
+		void shouldMapFields() {
+			var mapped = fromGrpcMail(GrpcPostfachMailTestFactory.create());
+
+			assertThat(mapped).usingRecursiveComparison()
+					.ignoringFields("createdAt", "createdBy", "direction", "messageId", "sentAt", "sentSuccessful", "memoizedHashCode")
+					.isEqualTo(PostfachNachrichtTestFactory.create());
+		}
+
+		@Test
+		void shouldHandleEmptyPostfachId() {
+			var postfachMailWithoutPostfachId = GrpcPostfachMailTestFactory.createBuilder().clearPostfachId().build();
+
+			assertDoesNotThrow(() -> fromGrpcMail(postfachMailWithoutPostfachId));
+		}
+
+		private PostfachNachricht fromGrpcMail(GrpcPostfachMail postfachMail) {
+			return mapper.fromGrpcMail(postfachMail);
+		}
+	}
+
+	private Map<String, Object> getMapWithoutProperty(String entryKey) {
+		var map = PostfachNachrichtTestFactory.asMap();
+		map.remove(entryKey);
+		return map;
+	}
+
+	private Object getAttributeFromGrpcObject(Object obj, String name) {
+		return getAttributeFrom(obj, name + "_");
+	}
+
+	@SneakyThrows
+	private Object getAttributeFromObject(Object obj, String name) {
+		return getAttributeFrom(obj, name);
+	}
+
+	@SneakyThrows
+	private Object getAttributeFrom(Object obj, String name) {
+		var clazz = obj.getClass();
+		var field = clazz.getDeclaredField(name);
+		field.setAccessible(true);
+
+		return field.get(obj);
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..09391f7d9ce130af9a63a13d267fb1d74f5ed2fb
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtTestFactory.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import static de.ozgcloud.nachrichten.postfach.PostfachNachricht.ReplyOption.*;
+import static de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory.*;
+
+import java.time.ZonedDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction;
+
+public class PostfachNachrichtTestFactory {
+
+	public static final String ID = UUID.randomUUID().toString();
+	public static final String CREATED_AT_STR = "2020-04-01T10:30:10Z";
+	public static final ZonedDateTime CREATED_AT = ZonedDateTime.parse(CREATED_AT_STR);
+	public static final String CREATED_BY = UUID.randomUUID().toString();
+	public static final String MAIL_BODY = "Body\nString";
+
+	public static final String SENT_AT_STR = "2020-04-01T11:30:10Z";
+	public static final ZonedDateTime SENT_AT = ZonedDateTime.parse(SENT_AT_STR);
+	public static final boolean SENT_SUCCESSFUL = true;
+	public static final String MESSAGE_CODE = PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE.getMessageCode();
+	public static final PostfachNachricht.ReplyOption REPLY_OPTION = MANDATORY;
+
+	public static final PostfachNachricht.Direction DIRECTION = Direction.IN;
+
+	public static final String ATTACHMENT_FILE_ID = "21";
+	public static final List<String> ATTACHMENTS = List.of(ATTACHMENT_FILE_ID);
+
+	public static PostfachNachricht create() {
+		return createBuilder().build();
+	}
+
+	public static PostfachNachricht.PostfachNachrichtBuilder createBuilder() {
+		return PostfachNachricht.builder()
+				.id(ID)
+				.postfachId(POSTFACH_ID)
+				.postfachAddress(PostfachAddressTestFactory.create())
+				.messageId(MESSAGE_ID)
+				.vorgangId(VORGANG_ID)
+				.direction(DIRECTION)
+				.createdAt(CREATED_AT)
+				.createdBy(CREATED_BY)
+				.sentAt(SENT_AT)
+				.sentSuccessful(SENT_SUCCESSFUL)
+				.messageCode(MESSAGE_CODE)
+				.replyOption(REPLY_OPTION)
+				.subject(SUBJECT)
+				.mailBody(MAIL_BODY)
+				.attachments(ATTACHMENTS);
+	}
+
+	public static Map<String, Object> asMap() {
+		var map = new HashMap<String, Object>();
+		map.put(PostfachNachricht.FIELD_ID, ID);
+		map.put(PostfachNachricht.FIELD_POSTFACH_ID, POSTFACH_ID);
+		map.put(PostfachNachricht.POSTFACH_ADDRESS_FIELD, getPostfachAddressAsMap());
+		map.put(PostfachNachricht.FIELD_MESSAGE_ID, MESSAGE_ID);
+		map.put(PostfachNachricht.FIELD_VORGANG_ID, VORGANG_ID);
+		map.put(PostfachNachricht.FIELD_DIRECTION, DIRECTION.name());
+		map.put(PostfachNachricht.FIELD_CREATED_AT, CREATED_AT_STR);
+		map.put(PostfachNachricht.FIELD_CREATED_BY, CREATED_BY);
+		map.put(PostfachNachricht.FIELD_SENT_AT, SENT_AT_STR);
+		map.put(PostfachNachricht.FIELD_SENT_SUCCESSFUL, SENT_SUCCESSFUL);
+		map.put(PostfachNachricht.FIELD_MESSAGE_CODE, MESSAGE_CODE);
+		map.put(PostfachNachricht.FIELD_REPLY_OPTION, REPLY_OPTION.name());
+		map.put(PostfachNachricht.FIELD_SUBJECT, SUBJECT);
+		map.put(PostfachNachricht.FIELD_MAIL_BODY, MAIL_BODY);
+		map.put(PostfachNachricht.FIELD_ATTACHMENTS, ATTACHMENTS);
+		return map;
+	}
+
+	private static Map<String, Object> getPostfachAddressAsMap() {
+		return Map.of(PostfachAddress.TYPE_FIELD, PostfachAddressTestFactory.TYPE,
+				PostfachAddress.VERSION_FIELD, PostfachAddressTestFactory.VERSION,
+				PostfachAddress.IDENTIFIER_FIELD, getPostfachAddressIdentifierAsMap(),
+				PostfachAddress.SERVICEKONTO_TYPE_FIELD, PostfachTestFactory.POSTFACH_TYPE);
+	}
+
+	private static Map<String, Object> getPostfachAddressIdentifierAsMap() {
+		return Map.of(PostfachNachricht.FIELD_POSTFACH_ID, PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE);
+	}
+}
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachSchedulerTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachSchedulerTest.java
similarity index 92%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachSchedulerTest.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachSchedulerTest.java
index 7aba40a44505daee3cd78a119eb373a96a9e9ce8..00948b1e6976ccd847155809c09746db759378f7 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/PostfachSchedulerTest.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachSchedulerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import static org.mockito.Mockito.*;
 
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..973c16929d498451d194a4047e7696f3d27058ab
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java
@@ -0,0 +1,811 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.stream.Stream;
+
+import org.apache.logging.log4j.Logger;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.mapstruct.factory.Mappers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.boot.logging.LogLevel;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.nachrichten.attributes.ClientAttributeService;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.ReplyOption;
+import de.ozgcloud.nachrichten.postfach.antragsraum.AntragsraumService;
+import de.ozgcloud.nachrichten.postfach.osi.MessageAttachmentService;
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+import de.ozgcloud.nachrichten.postfach.osi.OsiPostfachServerProcessException;
+import de.ozgcloud.nachrichten.postfach.osi.OsiPostfachServerProcessExceptionTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import nl.altindag.log.LogCaptor;
+
+class PostfachServiceTest {
+
+	@Spy
+	@InjectMocks
+	private PostfachService service;
+	@Mock
+	private PostfachRemoteService postfachRemoteService;
+
+	@Mock
+	private PersistPostfachNachrichtService persistingService;
+	@Spy
+	private PostfachNachrichtMapper mapper = Mappers.getMapper(PostfachNachrichtMapper.class);
+
+	@Mock
+	private ClientAttributeService clientAttributeService;
+	@Mock
+	private MessageAttachmentService messageAttachmentService;
+	@Mock
+	private ApplicationEventPublisher publisher;
+
+	@Mock
+	private CurrentUserService userService;
+	@Mock
+	private AntragsraumService antragsraumService;
+
+	static final String COMMAND_ID = UUID.randomUUID().toString();
+	static final String USER_ID = UUID.randomUUID().toString();
+
+	@Nested
+	class TestSaveDraft {
+
+		@Captor
+		private ArgumentCaptor<Optional<String>> userIdCaptor;
+		@Captor
+		private ArgumentCaptor<PostfachNachricht> nachrichtCaptor;
+
+		@BeforeEach
+		void init() {
+			doNothing().when(service).persistMail(any(), any());
+
+			when(userService.getUser()).thenReturn(CallContextUserTestFactory.create());
+		}
+
+		@Test
+		void shouldUseUserIdFromContext() {
+			service.saveDraft(MessageTestFactory.VORGANG_ID, PostfachNachrichtTestFactory.create());
+
+			verify(service).persistMail(userIdCaptor.capture(), any());
+			assertThat(userIdCaptor.getValue()).contains(CallContextUserTestFactory.ID);
+		}
+
+		@Test
+		void shouldPersistNachricht() {
+			service.saveDraft(MessageTestFactory.VORGANG_ID, PostfachNachrichtTestFactory.create());
+
+			verify(service).persistMail(any(), any());
+		}
+
+		@Test
+		void shouldAddVorgangId() {
+			service.saveDraft(MessageTestFactory.VORGANG_ID, PostfachNachrichtTestFactory.createBuilder().vorgangId(null).build());
+
+			verify(service).persistMail(any(), nachrichtCaptor.capture());
+			assertThat(nachrichtCaptor.getValue().getVorgangId()).isEqualTo(MessageTestFactory.VORGANG_ID);
+		}
+	}
+
+	@Nested
+	class TestSendMail {
+
+		@Test
+		void shouldCallDoSendMail() {
+			when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+			var mail = PostfachNachrichtTestFactory.create();
+
+			service.sendMail(COMMAND_ID, USER_ID, mail);
+
+			verify(service).doSendMail(mail);
+		}
+
+		@Test
+		void shouldCallPersistSentMail() {
+			when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+			var mail = PostfachNachrichtTestFactory.create();
+			doReturn(mail).when(service).addMailSentInformation(any(PostfachNachricht.class), any(SendPostfachNachrichtResponse.class));
+
+			service.sendMail(COMMAND_ID, USER_ID, PostfachNachrichtTestFactory.create());
+
+			verify(service).persistSentMail(USER_ID, mail);
+		}
+
+		@Test
+		void shouldAddMailSentInformation() {
+			var postfachMail = service.addMailSentInformation(PostfachNachrichtTestFactory.createBuilder().sentAt(null).sentSuccessful(null).build(),
+					SendPostfachNachrichtResponseTestFactory.create());
+
+			assertThat(postfachMail.getSentAt()).isNotNull();
+			assertThat(postfachMail.getSentSuccessful()).isEqualTo(SendPostfachNachrichtResponseTestFactory.SENT_SUCCESSFUL);
+			assertThat(postfachMail.getMessageCode()).isEqualTo(SendPostfachNachrichtResponseTestFactory.MESSAGE_CODE.getMessageCode());
+		}
+
+		@Test
+		void shouldHandleSendMail() {
+			when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+			var mail = PostfachNachrichtTestFactory.create();
+			service.sendMail(COMMAND_ID, USER_ID, mail);
+
+			verify(service).handleSendMail(COMMAND_ID, mail);
+		}
+
+		@Nested
+		class TestPersistSentMail {
+
+			@Captor
+			private ArgumentCaptor<PostfachNachricht> mailCaptor;
+
+			@Test
+			void shouldCallPersistingService() {
+				var mail = PostfachNachrichtTestFactory.create();
+
+				service.persistSentMail(USER_ID, mail);
+
+				verify(persistingService).persistNachricht(any(), notNull());
+			}
+
+			@Test
+			void shouldSetDirectionToIN() {
+				service.persistSentMail(USER_ID, PostfachNachrichtTestFactory.createBuilder().direction(null).build());
+
+				verify(persistingService).persistNachricht(any(), mailCaptor.capture());
+				assertThat(mailCaptor.getValue().getDirection()).isEqualTo(Direction.OUT);
+			}
+
+			@Test
+			void shouldSetCreatedAt() {
+				service.persistSentMail(USER_ID, PostfachNachrichtTestFactory.createBuilder().createdAt(null).build());
+
+				verify(persistingService).persistNachricht(any(), mailCaptor.capture());
+				assertThat(mailCaptor.getValue().getCreatedAt()).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS));
+			}
+
+			@Test
+			void shouldSetCreatedBy() {
+				service.persistSentMail(USER_ID, PostfachNachrichtTestFactory.createBuilder().createdBy(null).build());
+
+				verify(persistingService).persistNachricht(any(), mailCaptor.capture());
+				assertThat(mailCaptor.getValue().getCreatedBy()).isEqualTo(USER_ID);
+			}
+
+			@Test
+			void shouldSetUserId() {
+				var mail = PostfachNachrichtTestFactory.create();
+
+				service.persistSentMail(USER_ID, mail);
+
+				verify(persistingService).persistNachricht(eq(Optional.of(USER_ID)), any());
+			}
+
+			@Test
+			void shouldSetClientAttribute() {
+				service.persistSentMail(USER_ID, PostfachNachrichtTestFactory.create());
+
+				verify(clientAttributeService).setHasPostfachNachricht(MessageTestFactory.VORGANG_ID);
+			}
+
+			@Test
+			void shouldNOTSetNewNachricht() {
+				service.persistSentMail(USER_ID, PostfachNachrichtTestFactory.create());
+
+				verify(clientAttributeService, never()).setHasNewPostfachNachricht(any());
+			}
+		}
+
+		@Nested
+		class TestProcessForAntragsraum {
+
+			@Mock
+			private PostfachNachricht modifiedMail;
+
+			@Test
+			void shouldReturnEmpty() {
+				doReturn(false).when(service).isPostfachWithAntragsraum(any());
+
+				var result = service.processForAntragsraum(PostfachNachrichtTestFactory.create());
+
+				assertThat(result).isEmpty();
+			}
+
+			@Test
+			void shouldCallNotifyAntragsraum() {
+				doReturn(true).when(service).isPostfachWithAntragsraum(any());
+				var mail = PostfachNachrichtTestFactory.create();
+
+				service.processForAntragsraum(mail);
+
+				verify(antragsraumService).notifyAntragsraum(mail);
+			}
+
+			@Test
+			void shouldReturnAdjustedMail() {
+				doReturn(true).when(service).isPostfachWithAntragsraum(any());
+				doReturn(Optional.of(modifiedMail)).when(service).adjustMail(any());
+
+				var result = service.processForAntragsraum(PostfachNachrichtTestFactory.create());
+
+				assertThat(result).contains(modifiedMail);
+			}
+
+			@DisplayName("Is notify antragsraum")
+			@Nested
+			class TestIsNotifyAntragsraum {
+
+				@DisplayName("should return true if")
+				@ParameterizedTest(name = "replyOption is {0}")
+				@EnumSource(value = ReplyOption.class, names = { "FORBIDDEN" }, mode = EnumSource.Mode.EXCLUDE)
+				void shouldConfirm(ReplyOption replyOption) {
+					doReturn(true).when(service).isPostfachWithAntragsraum(any());
+
+					var result = service.isNotifyAntragsraum(replyOption);
+
+					assertThat(result).isTrue();
+				}
+
+				@DisplayName("should return false if reply is forbidden")
+				@Test
+				void shouldDeclineIfForbidden() {
+					var result = service.isNotifyAntragsraum(ReplyOption.FORBIDDEN);
+
+					assertThat(result).isFalse();
+				}
+
+				@DisplayName("should return false if antragsraum is not configured")
+				@Test
+				void shouldDeclineIfNotConfigured() {
+					doReturn(false).when(service).isPostfachWithAntragsraum(any());
+
+					var result = service.isNotifyAntragsraum(ReplyOption.POSSIBLE);
+
+					assertThat(result).isFalse();
+				}
+			}
+
+			@Nested
+			class TestAdjustMail {
+
+				@Mock
+				private PostfachNachricht mail;
+
+				@Nested
+				class TestReplaceBody {
+
+					@Test
+					void shouldReturnEmptyIfNoAntragsraum() {
+						doReturn(Optional.empty()).when(service).getAntragsraumService();
+
+						var result = adjustMail();
+
+						assertThat(result).isEmpty();
+					}
+
+					@Test
+					void shouldAdjustMailBody() {
+						when(mail.toBuilder()).thenReturn(PostfachNachrichtTestFactory.createBuilder());
+						var expectedMailBody = "Antragsraum Text";
+						when(antragsraumService.getUserNotificationText()).thenReturn(expectedMailBody);
+
+						var result = adjustMail();
+
+						assertThat(result).isPresent().get().extracting(PostfachNachricht::getMailBody).isEqualTo(expectedMailBody);
+					}
+				}
+
+				private Optional<PostfachNachricht> adjustMail() {
+					return service.adjustMail(mail);
+				}
+			}
+
+		}
+	}
+
+	@Nested
+	class TestFindById {
+		@Test
+		void shouldCallPersistingService() {
+			service.findById(PostfachNachrichtTestFactory.ID);
+
+			verify(persistingService).findById(PostfachNachrichtTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestFindByVorgang {
+
+		private static final String VORGANG_ID = UUID.randomUUID().toString();
+
+		@Test
+		void shouldCallPersistingService() {
+			service.findByVorgang(VORGANG_ID);
+
+			verify(persistingService).findByVorgangAsMap(VORGANG_ID);
+		}
+	}
+
+	@Nested
+	class TestFetchAndPersistReplies {
+
+		private static final PostfachNachricht nachricht = PostfachNachrichtTestFactory.create();
+
+		@BeforeEach
+		void initTest() {
+			lenient().when(postfachRemoteService.getAllMessages()).thenReturn(Stream.of(nachricht));
+		}
+
+		@Test
+		void shouldCallGetAllMessages() {
+			service.fetchAndPersistReplies();
+
+			verify(postfachRemoteService).getAllMessages();
+		}
+
+		@Test
+		void shouldCallPersistingService() {
+			service.fetchAndPersistReplies();
+
+			verify(persistingService).persistNachricht(eq(Optional.empty()), any());
+		}
+
+		@Test
+		void shouldCallDelete() {
+			service.fetchAndPersistReplies();
+
+			verify(postfachRemoteService).deleteMessage(MessageTestFactory.MESSAGE_ID);
+		}
+
+		@Test
+		void shouldSetNewPostfachNachricht() {
+			service.fetchAndPersistReplies();
+
+			verify(clientAttributeService).setHasNewPostfachNachricht(MessageTestFactory.VORGANG_ID);
+		}
+
+		@Test
+		void shouldCallClientAttributeService() {
+			service.fetchAndPersistReplies();
+
+			verify(clientAttributeService).setHasNewPostfachNachricht(MessageTestFactory.VORGANG_ID);
+		}
+
+		@Test
+		void shouldThrowNotConfiguredException() {
+			doReturn(false).when(service).isPostfachConfigured();
+
+			assertThatExceptionOfType(NotConfiguredException.class).isThrownBy(() -> service.fetchAndPersistReplies());
+			verify(postfachRemoteService, never()).getAllMessages();
+		}
+	}
+
+	@Nested
+	class TestPeristMail {
+		@Test
+		void shouldPersistMail() {
+			PostfachNachricht mail = PostfachNachrichtTestFactory.create();
+
+			service.persistMail(Optional.of(USER_ID), mail);
+
+			verify(persistingService).persistNachricht(eq(Optional.of(USER_ID)), same(mail));
+		}
+
+		@Test
+		void shouldSetHasPostfachNachricht() {
+			var mail = PostfachNachrichtTestFactory.create();
+
+			service.persistMail(Optional.of(USER_ID), mail);
+
+			verify(clientAttributeService).setHasPostfachNachricht(MessageTestFactory.VORGANG_ID);
+		}
+
+		@Test
+		@DisplayName("should NOT set hasPostfachNachricht if Nachricht is sent from system")
+		void shouldNOTSetHasNachrichtForSystemNachricht() {
+			var mail = PostfachNachrichtTestFactory.createBuilder().createdBy("system-123").build();
+
+			service.persistMail(Optional.of(USER_ID), mail);
+
+			verify(clientAttributeService, never()).setHasPostfachNachricht(MessageTestFactory.VORGANG_ID);
+		}
+	}
+
+	@Nested
+	class TestResendPostfachMail {
+
+		static final String COMMAND_ID = UUID.randomUUID().toString();
+		static final PostfachNachricht mail = PostfachNachrichtTestFactory.create();
+
+		@BeforeEach
+		void mockService() {
+			when(persistingService.getById(anyString())).thenReturn(PostfachNachrichtTestFactory.asMap());
+			doReturn(mail).when(mapper).fromMapToPostfachMail(anyMap());
+			when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+		}
+
+		@Test
+		void shouldCallPersistingServiceGetById() {
+			service.resendMail(COMMAND_ID, PostfachNachrichtTestFactory.ID);
+
+			verify(persistingService).getById(PostfachNachrichtTestFactory.ID);
+		}
+
+		@Test
+		void shouldMapFromMapToPostfachMail() {
+			service.resendMail(COMMAND_ID, PostfachNachrichtTestFactory.ID);
+
+			verify(mapper).fromMapToPostfachMail(PostfachNachrichtTestFactory.asMap());
+		}
+
+		@Test
+		void shouldSendMail() {
+			service.resendMail(COMMAND_ID, PostfachNachrichtTestFactory.ID);
+
+			verify(postfachRemoteService).sendMessage(any(PostfachNachricht.class));
+		}
+
+		@Test
+		void shouldPatchMail() {
+			service.resendMail(COMMAND_ID, PostfachNachrichtTestFactory.ID);
+
+			verify(persistingService).patch(anyString(), anyMap());
+		}
+
+		@Test
+		void shouldHandleSentMail() {
+			service.resendMail(COMMAND_ID, PostfachNachrichtTestFactory.ID);
+
+			verify(service).handleSendMail(COMMAND_ID, mail);
+		}
+	}
+
+	@Nested
+	class TestCreateResendPatchMap {
+
+		@Test
+		void shouldContainsSentAt() {
+			var map = service.createResendPatchMap(SendPostfachNachrichtResponseTestFactory.create());
+
+			assertThat(map).containsKey(PostfachNachricht.FIELD_SENT_AT);
+			assertThat(ZonedDateTime.parse(map.get(PostfachNachricht.FIELD_SENT_AT).toString())).isCloseTo(ZonedDateTime.now(),
+					within(2, ChronoUnit.SECONDS));
+		}
+
+		@Test
+		void shouldContainsSentSuccessful() {
+			var map = service.createResendPatchMap(SendPostfachNachrichtResponseTestFactory.create());
+
+			assertThat(map).containsEntry(PostfachNachricht.FIELD_SENT_SUCCESSFUL, true);
+		}
+
+		@Test
+		void shouldContainsMessageCode() {
+			var map = service.createResendPatchMap(SendPostfachNachrichtResponseTestFactory.create());
+
+			assertThat(map).containsEntry(PostfachNachricht.FIELD_MESSAGE_CODE,
+					SendPostfachNachrichtResponseTestFactory.MESSAGE_CODE.getMessageCode());
+		}
+	}
+
+	@DisplayName("Handle send mail")
+	@Nested
+	class TestHandleSendMail {
+
+		final String COMMAND_ID = UUID.randomUUID().toString();
+		final PostfachNachricht mail = PostfachNachrichtTestFactory.create();
+
+		@Test
+		void shouldDoSendMail() {
+			when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+
+			service.handleSendMail(COMMAND_ID, mail);
+
+			verify(service).doSendMail(mail);
+		}
+
+		@Nested
+		class TestSentSuccess {
+
+			@Captor
+			private ArgumentCaptor<PostfachMailSentEvent> eventCaptor;
+
+			@Mock
+			private PostfachNachricht modifiedMail;
+
+			@Test
+			void shouldDoSendMail() {
+				when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+
+				service.handleSendMail(COMMAND_ID, mail);
+
+				verify(service).doSendMail(mail);
+			}
+
+			@Test
+			void shouldPublishEvent() {
+				when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+
+				service.handleSendMail(COMMAND_ID, mail);
+
+				verify(publisher).publishEvent(eventCaptor.capture());
+				assertThat(eventCaptor.getValue().getSource()).isEqualTo(COMMAND_ID);
+			}
+
+			@Test
+			void shouldReturnResponse() {
+				when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+
+				var response = service.handleSendMail(COMMAND_ID, mail);
+
+				assertThat(response.isSentSuccessful()).isTrue();
+				assertThat(response.getMessageCode()).isEqualTo(PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE);
+			}
+
+			@Test
+			void shouldSendProcessedPostfachNachricht() {
+				doReturn(Optional.of(modifiedMail)).when(service).processForAntragsraum(any());
+
+				service.handleSendMail(COMMAND_ID, mail);
+
+				verify(service).doSendMail(modifiedMail);
+			}
+
+		}
+
+		@DisplayName("receive")
+		@Nested
+		class TestSentFailed {
+
+			@Captor
+			private ArgumentCaptor<PostfachMailSentFailedEvent> eventFailedCaptor;
+
+			@DisplayName("OsiPostfachException")
+			@Nested
+			class TestOnOsiPostfachException {
+
+				private final static String MESSAGE = "Osi Postfach throws an exception.";
+
+				@BeforeEach
+				void mockService() {
+					when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+					doThrow(new PostfachException(MESSAGE, PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE)).when(postfachRemoteService)
+							.sendMessage(any());
+				}
+
+				@Test
+				void shouldPublishEvent() {
+					service.handleSendMail(COMMAND_ID, mail);
+
+					verify(publisher).publishEvent(eventFailedCaptor.capture());
+					assertThat(eventFailedCaptor.getValue().getSource()).isEqualTo(COMMAND_ID);
+					assertThat(eventFailedCaptor.getValue().getErrorMessage()).startsWith(MESSAGE);
+				}
+
+				@Test
+				void shouldLogError() {
+					var logCaptor = LogCaptor.forClass(PostfachService.class);
+
+					service.handleSendMail(COMMAND_ID, mail);
+
+					verify(service).proceedWithErrorException(eq(COMMAND_ID), any(PostfachException.class));
+					assertThat(logCaptor.getLogEvents().get(0).getLevel()).isEqualTo(LogLevel.ERROR.name());
+					assertThat(logCaptor.getLogEvents().get(0).getMessage()).startsWith(MESSAGE);
+				}
+
+				@Test
+				void shouldReturnResponse() {
+					var response = service.handleSendMail(COMMAND_ID, mail);
+
+					assertThat(response.isSentSuccessful()).isFalse();
+					assertThat(response.getMessageCode()).isEqualTo(PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE);
+				}
+			}
+
+			@DisplayName("OsiPostfachServerProcessException")
+			@Nested
+			class TestOsiPostfachServerProcessException {
+
+				private final static String MESSAGE = "Postfach server returned false";
+
+				@Mock
+				private Logger logger;
+
+				@BeforeEach
+				void mockService() {
+					doThrow(OsiPostfachServerProcessExceptionTestFactory.create()).when(postfachRemoteService).sendMessage(any());
+					when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+				}
+
+				@Test
+				void shouldPublishEvent() {
+					service.handleSendMail(COMMAND_ID, mail);
+
+					verify(publisher).publishEvent(eventFailedCaptor.capture());
+					assertThat(eventFailedCaptor.getValue().getSource()).isEqualTo(COMMAND_ID);
+					assertThat(eventFailedCaptor.getValue().getErrorMessage()).startsWith(MESSAGE);
+				}
+
+				@Test
+				void shouldLogWarning() {
+					var logCaptor = LogCaptor.forClass(PostfachService.class);
+
+					service.handleSendMail(COMMAND_ID, mail);
+
+					verify(service).proceedwithWarnException(eq(COMMAND_ID), any(OsiPostfachServerProcessException.class));
+					assertThat(logCaptor.getLogEvents().get(0).getLevel()).isEqualTo(LogLevel.WARN.name());
+					assertThat(logCaptor.getLogEvents().get(0).getMessage()).startsWith(MESSAGE);
+				}
+
+				@Test
+				void shouldReturnResponse() {
+					var response = service.handleSendMail(COMMAND_ID, mail);
+
+					assertThat(response.isSentSuccessful()).isFalse();
+					assertThat(response.getMessageCode()).isEqualTo(PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE);
+				}
+			}
+		}
+
+	}
+
+	@Nested
+	class TestDoSendMail {
+		@Test
+		void shouldCallPostfachRemoteService() {
+			service.doSendMail(PostfachNachrichtTestFactory.create());
+
+			verify(postfachRemoteService).sendMessage(any());
+		}
+
+		@Nested
+		class WithoutRemoteService {
+			@InjectMocks
+			private PostfachService service;
+
+			@Test
+			void shouldThrowNotConfiguredException() {
+				var nachricht = PostfachNachrichtTestFactory.create();
+
+				assertThatExceptionOfType(NotConfiguredException.class).isThrownBy(() -> service.doSendMail(nachricht));
+
+				verify(postfachRemoteService, never()).sendMessage(any());
+			}
+		}
+
+	}
+
+	@Nested
+	class TestIsPostfachConfigured {
+
+		@Test
+		void shouldReturnTrue() {
+			assertThat(service.isPostfachConfigured()).isTrue();
+		}
+	}
+
+	@Nested
+	class TestGetPostfachs {
+
+		private Postfach postfach = PostfachTestFactory.create();
+
+		@Test
+		void shouldCallBuildPostfach() {
+			when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+
+			service.getPostfachs();
+
+			verify(service).buildPostfach(postfachRemoteService);
+		}
+
+		@Test
+		void shouldReturnPostfachs() {
+			doReturn(postfach).when(service).buildPostfach(any());
+
+			var result = service.getPostfachs();
+
+			assertThat(result).containsOnly(postfach);
+		}
+
+		@Test
+		void shouldReturnEmptyStream() {
+			doReturn(false).when(service).isPostfachConfigured();
+
+			var result = service.getPostfachs();
+
+			assertThat(result).isEmpty();
+		}
+
+		@Nested
+		class TestBuildPostfach {
+
+			@Test
+			void shouldSetPostfachType() {
+				when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE);
+
+				var result = service.buildPostfach(postfachRemoteService);
+
+				assertThat(result.getType()).isEqualTo(PostfachTestFactory.POSTFACH_TYPE);
+			}
+
+			@Test
+			void shouldSetIsReplyAllowed() {
+				doReturn(true).when(service).isReplyAllowed(any());
+
+				var result = service.buildPostfach(postfachRemoteService);
+
+				assertThat(result.isReplyAllowed()).isTrue();
+			}
+		}
+
+		@Nested
+		class TestIsReplyAllowed {
+
+			@Test
+			void shouldAllowWithAntragsraum() {
+				doReturn(true).when(service).isPostfachWithAntragsraum(postfachRemoteService);
+
+				var result = service.isReplyAllowed(postfachRemoteService);
+
+				assertThat(result).isTrue();
+			}
+
+			@Test
+			void shouldAllowWithPostfach() {
+				doReturn(false).when(service).isPostfachWithAntragsraum(postfachRemoteService);
+				when(postfachRemoteService.isReplyAllowed()).thenReturn(true);
+
+				var result = service.isReplyAllowed(postfachRemoteService);
+
+				assertThat(result).isTrue();
+			}
+
+			@Test
+			void shouldNotAllow() {
+				doReturn(false).when(service).isPostfachWithAntragsraum(postfachRemoteService);
+
+				var result = service.isReplyAllowed(postfachRemoteService);
+
+				assertThat(result).isFalse();
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..94c458ecb9bab39521c95d9259ae120467ab4a0d
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachTestFactory.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach;
+
+import de.ozgcloud.nachrichten.postfach.Postfach.PostfachBuilder;
+
+public class PostfachTestFactory {
+
+	public static final String POSTFACH_TYPE = "postfachType";
+
+	public static final boolean REPLY_ALLOWED = true;
+
+	public static Postfach create() {
+		return createBuilder().build();
+	}
+
+	public static PostfachBuilder createBuilder() {
+		return Postfach.builder()
+				.type(POSTFACH_TYPE)
+				.isReplyAllowed(REPLY_ALLOWED);
+	}
+}
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/SendPostfachNachrichtResponseTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/SendPostfachNachrichtResponseTestFactory.java
similarity index 86%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/SendPostfachNachrichtResponseTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/SendPostfachNachrichtResponseTestFactory.java
index 9ec6483a3c59fee6ac796c816d87ee4407c83c09..257b3082be7661eabec03ca50e9ffc37b4235ed7 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/SendPostfachNachrichtResponseTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/SendPostfachNachrichtResponseTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 public class SendPostfachNachrichtResponseTestFactory {
 
 	public static final boolean SENT_SUCCESSFUL = true;
-	public static final OsiPostfachMessageCode MESSAGE_CODE = OsiPostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE;
+	public static final PostfachMessageCode MESSAGE_CODE = PostfachMessageCode.SEND_SUCCESSFUL_MESSAGE_CODE;
 
 	public static SendPostfachNachrichtResponse create() {
 		return createBuilder().build();
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..539c689c39e8faba6a96d4ed4d4cadb4128ac033
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/AntragsraumServiceTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.nachrichten.NachrichtenManagerProperties;
+import de.ozgcloud.nachrichten.postfach.PostfachException;
+import de.ozgcloud.nachrichten.postfach.PostfachMessageCode;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+
+class AntragsraumServiceTest {
+
+	@Spy
+	@InjectMocks
+	private AntragsraumService service;
+
+	@Mock
+	private AntragsraumProperties properties;
+	@Mock
+	private NachrichtenManagerProperties nachrichtenManagerProperties;
+	@Mock
+	private InfomanagerRemoteService infomanagerRemoteService;
+
+	@Nested
+	class TestGetAntragsraumUrl {
+
+		private static final String URL = "url";
+
+		@Test
+		void shouldReturnUrl() {
+			when(properties.getUrl()).thenReturn(URL);
+
+			var url = service.getAntragsraumUrl();
+
+			assertThat(url).isEqualTo(URL);
+		}
+
+	}
+
+	@Nested
+	class TestNotifyAntragsraum {
+
+		private static final String NACHRICHTEN_MANAGER_URL = "nachrichtenManagerUrl";
+
+		private PostfachNachricht postfachNachricht = PostfachNachrichtTestFactory.create();
+
+		@Test
+		void shouldCallBuildInfomanagerNachricht() {
+			service.notifyAntragsraum(postfachNachricht);
+
+			verify(service).builInfomanagerNachricht(postfachNachricht);
+		}
+
+		@Test
+		void shouldCallInfoManagerRemoteService() {
+			var infomanagerNachricht = InfomanagerNachrichtTestFactory.create();
+			doReturn(infomanagerNachricht).when(service).builInfomanagerNachricht(any());
+
+			service.notifyAntragsraum(postfachNachricht);
+
+			verify(infomanagerRemoteService).sendNotification(infomanagerNachricht);
+		}
+
+		@Test
+		void shouldThrowPostfachException() {
+			var causeException = new RuntimeException();
+			when(infomanagerRemoteService.sendNotification(any())).thenThrow(causeException);
+
+			var exception = assertThrows(PostfachException.class, () -> service.notifyAntragsraum(postfachNachricht));
+			assertThat(exception.getMessageCode()).isEqualTo(PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE);
+		}
+
+		@Nested
+		class TestBuildInfomanagerNachricht {
+
+			@Test
+			void shouldSetNachrichtId() {
+				var infomanagerNachricht = buildInfomanagerNachricht();
+
+				assertThat(infomanagerNachricht.getNachrichtId()).isEqualTo(PostfachNachrichtTestFactory.ID);
+			}
+
+			@Test
+			void shouldSetVorgangId() {
+				var infomanagerNachricht = buildInfomanagerNachricht();
+
+				assertThat(infomanagerNachricht.getVorgangId()).isEqualTo(MessageTestFactory.VORGANG_ID);
+			}
+
+			@Test
+			void shouldSetPostfachId() {
+				var infomanagerNachricht = buildInfomanagerNachricht();
+
+				assertThat(infomanagerNachricht.getPostfachId()).isEqualTo(MessageTestFactory.POSTFACH_ID);
+			}
+
+			@Test
+			void shouldSetNachrichtenManagerUrl() {
+				when(nachrichtenManagerProperties.getUrl()).thenReturn(NACHRICHTEN_MANAGER_URL);
+
+				var infomanagerNachricht = buildInfomanagerNachricht();
+
+				assertThat(infomanagerNachricht.getNachrichtenManagerUrl()).isEqualTo(NACHRICHTEN_MANAGER_URL);
+			}
+
+			private InfomanagerNachricht buildInfomanagerNachricht() {
+				return service.builInfomanagerNachricht(postfachNachricht);
+			}
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachrichtTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachrichtTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..41631e8de11e2a35abf0cd42a1bb09785820a102
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerNachrichtTestFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.nachrichten.postfach.antragsraum.InfomanagerNachricht.InfomanagerNachrichtBuilder;
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+
+public class InfomanagerNachrichtTestFactory {
+
+	public static final String NACHRICHTEN_MANAGER_URL = "nachrichten-manager";
+	public static InfomanagerNachricht create() {
+		return createBuilder().build();
+	}
+
+	private static InfomanagerNachrichtBuilder createBuilder() {
+		return InfomanagerNachricht.builder()
+				.nachrichtId(PostfachNachrichtTestFactory.ID)
+				.vorgangId(MessageTestFactory.VORGANG_ID)
+				.postfachId(MessageTestFactory.POSTFACH_ID)
+				.nachrichtenManagerUrl(NACHRICHTEN_MANAGER_URL);
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerRemoteServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..60d5e66d280c395c5ff7f5807c1fcfaed92723d5
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/antragsraum/InfomanagerRemoteServiceTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.antragsraum;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.info.nachricht.GrpcNachricht;
+import de.ozgcloud.info.nachricht.GrpcNewNachrichtReply;
+import de.ozgcloud.info.nachricht.GrpcNewNachrichtRequest;
+import de.ozgcloud.info.nachricht.NachrichtServiceGrpc.NachrichtServiceBlockingStub;
+
+class InfomanagerRemoteServiceTest {
+
+	@Spy
+	@InjectMocks
+	private InfomanagerRemoteService service;
+
+	@Mock
+	private NachrichtServiceBlockingStub nachrichtServiceStub;
+	@Mock
+	private InfomanagerNachrichtMapper nachrichtMapper;
+
+	@Nested
+	class TestSendNotification {
+
+		private static final String INFO_MANAGER_STATUS = "status";
+
+		@Mock
+		private GrpcNewNachrichtRequest grpcRequest;
+		@Mock
+		private GrpcNewNachrichtReply grpcReply;
+
+		@BeforeEach
+		void setup() {
+			doReturn(grpcRequest).when(service).buildNachrichtRequest(any());
+			when(nachrichtServiceStub.saveNewNachricht(any())).thenReturn(grpcReply);
+		}
+
+		@Test
+		void shouldCallGrpcClient() {
+			sendNotification();
+
+			verify(nachrichtServiceStub).saveNewNachricht(grpcRequest);
+		}
+
+		@Test
+		void shouldReturnStatus() {
+			when(grpcReply.getStatus()).thenReturn(INFO_MANAGER_STATUS);
+
+			var status = sendNotification();
+
+			assertThat(status).isEqualTo(INFO_MANAGER_STATUS);
+		}
+
+		private String sendNotification() {
+			return service.sendNotification(InfomanagerNachrichtTestFactory.create());
+		}
+	}
+
+	@Nested
+	class TestBuildNachrichtRequest {
+
+		@Mock
+		private GrpcNachricht grpcNachricht;
+
+		@BeforeEach
+		void setup() {
+			when(nachrichtMapper.toGrpc(any())).thenReturn(grpcNachricht);
+		}
+
+		@Test
+		void shouldCallMapper() {
+			var nachricht = InfomanagerNachrichtTestFactory.create();
+
+			service.buildNachrichtRequest(nachricht);
+
+			verify(nachrichtMapper).toGrpc(nachricht);
+		}
+
+		@Test
+		void shouldSetNachricht() {
+			var grpcRequest = service.buildNachrichtRequest(InfomanagerNachrichtTestFactory.create());
+
+			assertThat(grpcRequest.getNachricht()).isEqualTo(grpcNachricht);
+		}
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/AbsenderTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/AbsenderTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc86790b3e84fa35ea3e6d48fad9695cf063d34c
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/AbsenderTestFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.Absender.AbsenderBuilder;
+
+public class AbsenderTestFactory {
+	public static final String POSTKORB_ID="28721c6f-b78f-4d5c-a048-19fd2fc429d2";
+	public static final String NAME="test name";
+	public static final String ANSCHRIFT="Niemalsgasse 5, 99999 Irgendwo Stadt";
+	public static final String DIENST="Stadtverwaltung";
+	public static final String MANDANT="Fürth";
+	public static final String GEMEINDE_SCHLUESSEL="09563000";
+
+	public static Absender create(){
+		return createBuilder().build();
+	}
+
+	public static AbsenderBuilder createBuilder(){
+		return Absender.builder()
+				.postkorbId(POSTKORB_ID)
+				.name(NAME)
+				.anschrift(ANSCHRIFT)
+				.dienst(DIENST)
+				.mandant(MANDANT)
+				.gemeindeSchluessel(GEMEINDE_SCHLUESSEL);
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/AbsenderTypeTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/AbsenderTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..9eb5b05111c28ccabebdf1726bb0a882230f16a9
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/AbsenderTypeTestFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.akdb.egov.bsp.nachrichten.AbsenderType;
+import lombok.val;
+
+public class AbsenderTypeTestFactory {
+	public static final String DIENST = "Stadtverwaltung";
+	public static final String MANDANT = "Fürth";
+
+	public static AbsenderType create() {
+		val absenderType = new AbsenderType();
+		absenderType.setDienst(DIENST);
+		absenderType.setMandant(MANDANT);
+		return absenderType;
+	}
+
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a92cda9e68d596cdb45e715041e8dc69614ee068
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentServiceTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static de.ozgcloud.nachrichten.postfach.bayernid.BayernIdAttachmentTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import com.mongodb.client.gridfs.model.GridFSFile;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.BinaryFileService;
+import de.ozgcloud.nachrichten.postfach.FileId;
+
+class BayernIdAttachmentServiceTest {
+
+	private static final FileId FILE_ID = FileId.from("42");
+
+	@InjectMocks
+	@Spy
+	private BayernIdAttachmentService bayernIdAttachmentService;
+
+	@Mock
+	private BinaryFileService fileService;
+
+	@Mock
+	private GridFSFile gridFsfile;
+
+	@Mock
+	private Document metadata;
+
+	@Nested
+	class TestLoadingAttachment {
+
+		@BeforeEach
+		void init() {
+			when(gridFsfile.getMetadata()).thenReturn(metadata);
+			when(fileService.getFile(any())).thenReturn(gridFsfile);
+		}
+
+		@Test
+		void shouldCallGetFile() {
+			when(fileService.getUploadedFileStream(any())).thenReturn(new ByteArrayInputStream(CONTENT));
+
+			bayernIdAttachmentService.getMessageAttachment(FILE_ID);
+
+			verify(fileService).getFile(FILE_ID);
+		}
+
+		@Test
+		void shouldCallGetAttachmentContent() {
+			when(fileService.getUploadedFileStream(any())).thenReturn(new ByteArrayInputStream(CONTENT));
+
+			bayernIdAttachmentService.getMessageAttachment(FILE_ID);
+
+			verify(bayernIdAttachmentService).getMessageAttachment(FILE_ID);
+		}
+
+		@Test
+		void shouldCallBuildBayernIdAttachment() {
+			var contentStream = getContentStream();
+			doReturn(contentStream).when(bayernIdAttachmentService).getAttachmentContentStream(any());
+
+			bayernIdAttachmentService.getMessageAttachment(FILE_ID);
+
+			verify(bayernIdAttachmentService).buildBayernIdAttachment(metadata, contentStream);
+		}
+
+	}
+
+	@Nested
+	class TestLoadAttachmentError {
+
+		@Test
+		@DisplayName("should throw TechnicalException if attachment not found")
+		void shouldThrowException() {
+			when(fileService.getFile(any())).thenReturn(null);
+
+			assertThrows(TechnicalException.class, () -> bayernIdAttachmentService.getMessageAttachment(FILE_ID));
+		}
+
+		@Test
+		@DisplayName("should throw TechnicalException if metadata is null")
+		void shouldThrowExceptionIfNoMetadata() {
+			when(fileService.getFile(any())).thenReturn(gridFsfile);
+			when(gridFsfile.getMetadata()).thenReturn(null);
+
+			assertThrows(TechnicalException.class, () -> bayernIdAttachmentService.getMessageAttachment(FILE_ID));
+		}
+	}
+
+	@Nested
+	class TestBuildBayernIdAttachment {
+
+		@BeforeEach
+		void setup() {
+			when(metadata.getString(BayernIdAttachmentService.NAME_KEY)).thenReturn(BayernIdAttachmentTestFactory.FILENAME);
+			when(metadata.getString(BayernIdAttachmentService.CONTENT_TYPE_KEY)).thenReturn(BayernIdAttachmentTestFactory.CONTENT_TYPE);
+		}
+
+		@Test
+		void shouldSetFileName() {
+			var attachment = buildBayernIdAttachment();
+
+			assertThat(attachment.getFileName()).isEqualTo(BayernIdAttachmentTestFactory.FILENAME);
+		}
+
+		@Test
+		void shouldSetContent() {
+			var attachment = buildBayernIdAttachment();
+
+			assertThat(attachment.getContent()).hasSameContentAs(new ByteArrayInputStream(CONTENT));
+		}
+
+		@Test
+		void shouldSetContentType() {
+			var attachment = buildBayernIdAttachment();
+
+			assertThat(attachment.getContentType()).isEqualTo(BayernIdAttachmentTestFactory.CONTENT_TYPE);
+		}
+
+		private BayernIdAttachment buildBayernIdAttachment() {
+			return bayernIdAttachmentService.buildBayernIdAttachment(metadata, getContentStream());
+		}
+	}
+
+	@Nested
+	class TestLoadingAttachmentContent {
+
+		@BeforeEach
+		void init() {
+			when(fileService.getUploadedFileStream(any()))
+					.thenReturn(new ByteArrayInputStream(CONTENT));
+		}
+
+		@Test
+		void shouldGetInputStream() {
+			InputStream input = bayernIdAttachmentService.getAttachmentContentStream(FILE_ID);
+
+			assertThat(input).hasSameContentAs(getContentStream());
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..428d41792b6631d40d0c0a24e68fd7222a78062f
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdAttachmentTestFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.BayernIdAttachment.BayernIdAttachmentBuilder;
+
+public class BayernIdAttachmentTestFactory {
+
+	public final static String FILENAME = "test.txt";
+	public final static String CONTENT_TYPE = "text/plain";
+	public static final byte[] CONTENT = "test".getBytes();
+	public static final long SIZE = 4L;
+
+	public static BayernIdAttachment create() {
+		return createBuilder().build();
+	}
+
+	public static BayernIdAttachmentBuilder createBuilder() {
+		return BayernIdAttachment.builder()
+				.fileName(FILENAME)
+				.content(new ByteArrayInputStream(CONTENT))
+				.contentType(CONTENT_TYPE);
+	}
+
+	public static InputStream getContentStream() {
+		return new ByteArrayInputStream(CONTENT);
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachNachrichtMapperTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachNachrichtMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2102d04c0f0971e65e47a139ddfb453e36aa56b1
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachNachrichtMapperTest.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.Spy;
+
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAttachmentMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcAttachments;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcBayernIdMessageMetadata;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+
+class BayernIdPostfachNachrichtMapperTest {
+
+	@Spy
+	private BayernIdPostfachNachrichtMapper mapper = Mappers.getMapper(BayernIdPostfachNachrichtMapper.class);
+
+	@Nested
+	class TestMapToSendBayernIdMessageMetadataRequest {
+
+		private static final PostfachNachricht NACHRICHT = PostfachNachrichtTestFactory.create();
+		private static final Absender ABSENDER = AbsenderTestFactory.create();
+
+		@Test
+		void shouldIgnoreAttachments() {
+			var request = mapper.toSendBayernIdMessageMetadataRequest(NACHRICHT, ABSENDER);
+
+			assertThat(request.getAttachments()).isEqualTo(GrpcAttachments.getDefaultInstance());
+		}
+
+		@Test
+		void shouldCallToBayernIdMessageMetadata() {
+			mapper.toSendBayernIdMessageMetadataRequest(NACHRICHT, ABSENDER);
+
+			verify(mapper).toBayernIdMessageMetadata(NACHRICHT, ABSENDER);
+		}
+
+		@Nested
+		class TestMapToBayernIdMessageMetadata {
+
+			@Test
+			void shouldSetMessageId() {
+				var metadata = toMessageMetadata();
+
+				assertThat(metadata.getMessageId()).isEqualTo(MessageTestFactory.MESSAGE_ID);
+			}
+
+			@Nested
+			class TestCreatedAt {
+
+				@Test
+				void shouldCallConvertZonedDateTime() {
+					toMessageMetadata();
+
+					verify(mapper).convertZonedDateTime(PostfachNachrichtTestFactory.CREATED_AT);
+				}
+
+				@Test
+				void shouldSetCreatedAt() {
+					doReturn(PostfachNachrichtTestFactory.CREATED_AT_STR).when(mapper).convertZonedDateTime(any());
+
+					var metadata = toMessageMetadata();
+
+					assertThat(metadata.getCreatedAt()).isEqualTo(PostfachNachrichtTestFactory.CREATED_AT_STR);
+				}
+			}
+
+			@Test
+			void shouldSetSubject() {
+				var metadata = toMessageMetadata();
+
+				assertThat(metadata.getSubject()).isEqualTo(MessageTestFactory.SUBJECT);
+			}
+
+			@Test
+			void shouldSetStorkQaaLevel() {
+				var metadata = toMessageMetadata();
+
+				assertThat(metadata.getStorkQaaLevel()).isEqualTo(BayernIdPostfachNachrichtMapper.MESSAGE_LEVEL);
+			}
+
+			@Test
+			void shouldSetVorgangId() {
+				var metadata = toMessageMetadata();
+
+				assertThat(metadata.getVorgangId()).isEqualTo(MessageTestFactory.VORGANG_ID);
+			}
+
+			@Test
+			void shouldSetText() {
+				var metadata = toMessageMetadata();
+
+				assertThat(metadata.getText()).isEqualTo(PostfachNachrichtTestFactory.MAIL_BODY);
+			}
+
+			@Nested
+			class TestMapAbsender {
+
+				@Test
+				void shouldSetName() {
+					var metadata = toMessageMetadata();
+
+					assertThat(metadata.getAbsender().getName()).isEqualTo(AbsenderTestFactory.NAME);
+				}
+
+				@Test
+				void shouldSetAnschrift() {
+					var metadata = toMessageMetadata();
+
+					assertThat(metadata.getAbsender().getAnschrift()).isEqualTo(AbsenderTestFactory.ANSCHRIFT);
+				}
+
+				@Test
+				void shouldSetDienst() {
+					var metadata = toMessageMetadata();
+
+					assertThat(metadata.getAbsender().getDienst()).isEqualTo(AbsenderTestFactory.DIENST);
+				}
+
+				@Test
+				void shouldSetMandant() {
+					var metadata = toMessageMetadata();
+
+					assertThat(metadata.getAbsender().getMandant()).isEqualTo(AbsenderTestFactory.MANDANT);
+				}
+
+				@Test
+				void shouldSetGemeindeschluessel() {
+					var metadata = toMessageMetadata();
+
+					assertThat(metadata.getAbsender().getGemeindeschluessel()).isEqualTo(AbsenderTestFactory.GEMEINDE_SCHLUESSEL);
+				}
+
+			}
+
+			@Nested
+			class TestMapToEmpfaenger {
+
+				@Test
+				void shouldSetPostkorbId() {
+					var metadata = toMessageMetadata();
+
+					assertThat(metadata.getEmpfaenger().getPostkorbId()).isEqualTo(MessageTestFactory.POSTFACH_ID);
+				}
+			}
+
+			private GrpcBayernIdMessageMetadata toMessageMetadata() {
+				return mapper.toBayernIdMessageMetadata(NACHRICHT, ABSENDER);
+			}
+		}
+	}
+
+	@Nested
+	class TestMapToSendBayernIdAttachmentsMetadata {
+
+		private static final BayernIdAttachment ATTACHMENT = BayernIdAttachmentTestFactory.create();
+
+		@Test
+		void shouldIgnoreMessageMetadata() {
+			var request = toMessageRequest();
+
+			assertThat(request.getMessageMetadata()).isEqualTo(GrpcBayernIdMessageMetadata.getDefaultInstance());
+		}
+
+		@Test
+		void shouldIgnoreContent() {
+			var request = toMessageRequest();
+
+			assertThat(request.getAttachments().getContent()).isEmpty();
+		}
+
+		@Test
+		void shouldCallToAttachmentsMetadata() {
+			toMessageRequest();
+
+			verify(mapper).toAttachmentMetadata(ATTACHMENT);
+		}
+
+		private GrpcSendBayernIdMessageRequest toMessageRequest() {
+			return mapper.toSendBayernIdAttachmentsMetadataRequest(ATTACHMENT);
+		}
+	}
+
+	@Nested
+	class TestMapToAttachmentMetadata {
+
+		@Test
+		void shouldSetFileName() {
+			var metadata = toMessageRequest();
+
+			assertThat(metadata.getFileName()).isEqualTo(BayernIdAttachmentTestFactory.FILENAME);
+		}
+
+		@Test
+		void shouldSetFileType() {
+			var metadata = toMessageRequest();
+
+			assertThat(metadata.getFileType()).isEqualTo(BayernIdAttachmentTestFactory.CONTENT_TYPE);
+		}
+
+		private GrpcAttachmentMetadata toMessageRequest() {
+			return mapper.toAttachmentMetadata(BayernIdAttachmentTestFactory.create());
+		}
+	}
+
+	@Nested
+	class TestMapToGregorianCalendar {
+
+		@Test
+		void shouldReturnGregorianCalendar() {
+			var expectedDateTiem = "2024-02-14T23:29:25.000+01:00";
+			var dateTiem = ZonedDateTime.of(2024, 2, 14, 23, 29, 25, 0, ZoneId.of("Europe/Berlin"));
+
+			var calendar = mapper.convertZonedDateTime(dateTiem);
+
+			assertThat(calendar).isEqualTo(expectedDateTiem);
+		}
+	}
+
+	@Nested
+	class TestMapFromSendBayernIdMessageResponse {
+
+		@Test
+		void shouldSetSuccess() {
+			var result = mapper.fromSendBayernIdMessageResponse(GrpcSendBayernIdMessageResponseTestFactory.create());
+
+			assertThat(result.isSuccess()).isTrue();
+		}
+
+		@Test
+		void shouldSetStatus() {
+			var result = mapper.fromSendBayernIdMessageResponse(GrpcSendBayernIdMessageResponseTestFactory.create());
+
+			assertThat(result.getStatus()).isEqualTo(GrpcSendBayernIdMessageResponseTestFactory.STATUS);
+		}
+
+		@Test
+		void shouldSetMessage(){
+			var result = mapper.fromSendBayernIdMessageResponse(GrpcSendBayernIdMessageResponseTestFactory.create());
+
+			assertThat(result.getMessage()).isEqualTo(GrpcSendBayernIdMessageResponseTestFactory.MESSAGE_TEXT);
+		}
+	}
+
+	@Nested
+	class TestSkipNulls {
+
+		@Test
+		void shouldNotSetNull() {
+			var bayernIdMessageMetadata = mapper.toBayernIdMessageMetadata(PostfachNachrichtTestFactory.createBuilder().messageId(null).build(),
+					AbsenderTestFactory.create());
+
+			assertThat(bayernIdMessageMetadata.getMessageId()).isEmpty();
+		}
+
+		@Test
+		void shouldReturnTrueIfNotNull() {
+			var result = mapper.nonNull("test");
+
+			assertThat(result).isTrue();
+		}
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachRemoteServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..fa21a6296d58ea8dd9c3fb17226dfac23a425569
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachRemoteServiceTest.java
@@ -0,0 +1,455 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.FileId;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.nachrichten.postfach.PostfachRuntimeException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.BayernIdProxyServiceGrpc;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+import io.grpc.stub.CallStreamObserver;
+import io.grpc.stub.StreamObserver;
+import lombok.SneakyThrows;
+
+class BayernIdPostfachRemoteServiceTest {
+
+	@Spy
+	@InjectMocks
+	private BayernIdPostfachRemoteService service;
+
+	@Mock
+	private BayernIdProxyServiceGrpc.BayernIdProxyServiceStub bayernIdProxyServiceStub;
+	@Mock
+	private BayernIdProperties properties;
+	@Mock
+	private BayernIdPostfachResponseHandler responseHandler;
+	@Mock
+	private BayernIdPostfachNachrichtMapper mapper;
+	@Mock
+	private BayernIdAttachmentService attachmentService;
+
+	@Nested
+	@DisplayName("Get all messages")
+	class TestGetAllMessages {
+
+		@Test
+		void shouldThrowUnsupportedOperationException() {
+			assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(service::getAllMessages);
+		}
+	}
+
+	@Nested
+	@DisplayName("Delete messages")
+	class TestDeleteMessages {
+
+		@Test
+		void shouldThrowUnsupportedOperationException() {
+			assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> service.deleteMessage(StringUtils.EMPTY));
+		}
+	}
+
+	@Nested
+	@DisplayName("Send message")
+	class TestSendMessage {
+
+		@Mock
+		private GrpcSendBayernIdMessageResponse grpcResponse;
+		@Mock
+		private MessageWithFilesSender messageWithFilesSender;
+		@Mock
+		private BayernIdResponse bayernIdResponse;
+
+		@Nested
+		class TestSend {
+
+			@BeforeEach
+			void setup() {
+				doReturn(grpcResponse).when(service).waitUntilTransferCompleted(any());
+			}
+
+			@Test
+			void shouldCallCreateMessageWithFileSender() {
+				sendMessage();
+
+				verify(service).createMessageWithFilesSender(any());
+			}
+
+			@Test
+			void shouldCallSend() {
+				doReturn(messageWithFilesSender).when(service).createMessageWithFilesSender(any());
+
+				sendMessage();
+
+				verify(messageWithFilesSender).send();
+			}
+
+			@Test
+			void shouldCallWaitForResults() {
+				var expectedSender = mock(MessageWithFilesSender.class);
+				when(messageWithFilesSender.send()).thenReturn(expectedSender);
+				doReturn(messageWithFilesSender).when(service).createMessageWithFilesSender(any());
+
+				sendMessage();
+
+				verify(service).waitUntilTransferCompleted(expectedSender);
+			}
+
+			@Test
+			void shouldCallMaapper() {
+				sendMessage();
+
+				verify(mapper).fromSendBayernIdMessageResponse(grpcResponse);
+			}
+
+			@Test
+			void shouldCallResponseHandler() {
+				when(mapper.fromSendBayernIdMessageResponse(any())).thenReturn(bayernIdResponse);
+
+				sendMessage();
+
+				verify(responseHandler).handleResponse(bayernIdResponse);
+			}
+		}
+
+		@Nested
+		class TestExceptionHandling {
+
+			@Test
+			void shouldHandleExceptionWhenSending() {
+				var thrownException = new RuntimeException("Test");
+				when(messageWithFilesSender.send()).thenThrow(thrownException);
+				doReturn(messageWithFilesSender).when(service).createMessageWithFilesSender(any());
+
+				assertThrows(PostfachRuntimeException.class, TestSendMessage.this::sendMessage);
+			}
+
+			@Test
+			void shouldHandleExceptionWhenWaiting() {
+				var thrownException = new RuntimeException("Test");
+				doThrow(thrownException).when(service).waitUntilTransferCompleted(any());
+
+				assertThrows(PostfachRuntimeException.class, TestSendMessage.this::sendMessage);
+			}
+
+			@Test
+			void shouldPassBayernIdServerException() {
+				doReturn(grpcResponse).when(service).waitUntilTransferCompleted(any());
+				var thrownException = new BayernIdServerException("Test");
+				doThrow(thrownException).when(responseHandler).handleResponse(any());
+
+				var resultException = assertThrows(BayernIdServerException.class, TestSendMessage.this::sendMessage);
+				assertThat(resultException).isEqualTo(thrownException);
+			}
+		}
+
+		private void sendMessage() {
+			service.sendMessage(PostfachNachrichtTestFactory.create());
+		}
+	}
+
+	@Nested
+	class TestCreateMessageWithFileSender {
+
+		@Mock
+		private Function<StreamObserver<GrpcSendBayernIdMessageResponse>, CallStreamObserver<GrpcSendBayernIdMessageRequest>> streamObserverBuilder;
+		@Mock
+		private GrpcSendBayernIdMessageRequest metadataRequest;
+		@Mock
+		private Function<String, BayernIdAttachment> attachmentBuilder;
+		@Mock
+		private Function<BayernIdAttachment, GrpcSendBayernIdMessageRequest> attachmentMetadataMapper;
+		@Mock
+		private BiFunction<byte[], Integer, GrpcSendBayernIdMessageRequest> chunkBuilder;
+
+		@Test
+		void shouldSetStreamObserverBuilder() {
+			doReturn(streamObserverBuilder).when(service).buildCallStreamObserverBuilder();
+
+			var sender = createMessageWithFilesSender();
+
+			assertThat(sender).extracting("reqObserverBuilder").isEqualTo(streamObserverBuilder);
+		}
+
+		@Test
+		void shouldCallMessageMetadataMapper() {
+			var absender = AbsenderTestFactory.create();
+			when(properties.getAbsender()).thenReturn(absender);
+			var nachricht = PostfachNachrichtTestFactory.create();
+
+			service.createMessageWithFilesSender(nachricht);
+
+			verify(mapper).toSendBayernIdMessageMetadataRequest(nachricht, absender);
+		}
+
+		@Test
+		void shouldSetMessageMetadata() {
+			when(mapper.toSendBayernIdMessageMetadataRequest(any(), any())).thenReturn(metadataRequest);
+
+			var sender = createMessageWithFilesSender();
+
+			assertThat(sender).extracting("messageMetadata").isEqualTo(metadataRequest);
+		}
+
+		@Test
+		void shouldSetAttachmentIds() {
+			var nachricht = PostfachNachrichtTestFactory.create();
+
+			var sender = createMessageWithFilesSender();
+
+			assertThat(sender).extracting("attachmentIds").isEqualTo(nachricht.getAttachments());
+		}
+
+		@Test
+		void shouldSetAttachmentBuilder() {
+			doReturn(attachmentBuilder).when(service).buildAttachmentBuilder();
+
+			var sender = createMessageWithFilesSender();
+
+			assertThat(sender).extracting("toAttachment").isEqualTo(attachmentBuilder);
+		}
+
+		@Test
+		void shouldSetAttachmentMetadataBuilder() {
+			doReturn(attachmentMetadataMapper).when(service).buildAttachmentMetadataMapper();
+
+			var sender = createMessageWithFilesSender();
+
+			assertThat(sender).extracting("attachmentMetadataMapper").isEqualTo(attachmentMetadataMapper);
+		}
+
+		@Test
+		void shouldSetChunkBuilder() {
+			doReturn(chunkBuilder).when(service).buildChunkRequest();
+
+			var sender = createMessageWithFilesSender();
+
+			assertThat(sender).extracting("chunkBuilder").isEqualTo(chunkBuilder);
+		}
+
+		private MessageWithFilesSender createMessageWithFilesSender() {
+			return service.createMessageWithFilesSender(PostfachNachrichtTestFactory.create());
+		}
+	}
+
+	@Nested
+	class TestBuildCallStreamObserverBuilder {
+
+		@Mock
+		private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+		@Mock
+		private StreamObserver<GrpcSendBayernIdMessageResponse> responseObserver;
+
+		@Test
+		void shouldCallSendMessageAsStream() {
+			service.buildCallStreamObserverBuilder().apply(responseObserver);
+
+			verify(bayernIdProxyServiceStub).sendMessageAsStream(responseObserver);
+		}
+
+		@Test
+		void shouldReturnRequestObserver() {
+			when(bayernIdProxyServiceStub.sendMessageAsStream(any())).thenReturn(requestObserver);
+
+			var result = service.buildCallStreamObserverBuilder().apply(responseObserver);
+
+			assertThat(result).isEqualTo(requestObserver);
+		}
+	}
+
+	@Nested
+	class TestBuildAttachmentBuilder {
+
+		@Captor
+		private ArgumentCaptor<FileId> attachmentIdCaptor;
+
+		@Test
+		void shouldCallGetMessageAttachment (){
+			var attachmentId = "test";
+
+			service.buildAttachmentBuilder().apply(attachmentId);
+
+			verify(attachmentService).getMessageAttachment(attachmentIdCaptor.capture());
+			assertThat(attachmentIdCaptor.getValue()).extracting(FileId::toString).isEqualTo(attachmentId);
+		}
+
+		@Test
+		void shouldReturnAttachment() {
+			var attachment = BayernIdAttachmentTestFactory.create();
+			when(attachmentService.getMessageAttachment(any())).thenReturn(attachment);
+
+			var result = service.buildAttachmentBuilder().apply(StringUtils.EMPTY);
+
+			assertThat(result).isEqualTo(attachment);
+		}
+	}
+
+	@Nested
+	class TestBuildChunkRequest {
+
+		@Captor
+		private ArgumentCaptor<byte[]> bytesCaptor;
+		@Captor
+		private ArgumentCaptor<Integer> lengthCaptor;
+
+		@Test
+		void shouldReturnRequest() {
+			var bytes = new byte[] { 1, 2, 3 };
+			var length = 3;
+
+			var result = service.buildChunkRequest().apply(bytes, length);
+
+			assertThat(result.getAttachments().getContent().toByteArray()).isEqualTo(bytes);
+		}
+	}
+
+	@Nested
+	class TestBuildAttachmentMetadataMapper {
+
+		private static final BayernIdAttachment ATTACHMENT = BayernIdAttachmentTestFactory.create();
+
+		@Mock
+		private GrpcSendBayernIdMessageRequest attachmentMetadataRequest;
+
+		@Test
+		void shouldCallMapper() {
+			service.buildAttachmentMetadataMapper().apply(ATTACHMENT);
+
+			verify(mapper).toSendBayernIdAttachmentsMetadataRequest(ATTACHMENT);
+		}
+
+		@Test
+		void shouldReturnResult() {
+			when(mapper.toSendBayernIdAttachmentsMetadataRequest(any())).thenReturn(attachmentMetadataRequest);
+
+			var result = service.buildAttachmentMetadataMapper().apply(ATTACHMENT);
+
+			assertThat(result).isEqualTo(attachmentMetadataRequest);
+		}
+	}
+
+	@Nested
+	class TestWaitUntilTransferCompleted {
+
+		@Mock
+		private MessageWithFilesSender sender;
+		@Mock
+		private GrpcSendBayernIdMessageResponse grpcResponse;
+		@Mock
+		private CompletableFuture<GrpcSendBayernIdMessageResponse> resultFuture;
+
+		@BeforeEach
+		void setup() {
+			doReturn(resultFuture).when(sender).getResultFuture();
+		}
+
+		@Test
+		void shouldCallGet() {
+			service.waitUntilTransferCompleted(sender);
+
+			verify(sender).getResultFuture();
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldReturnResult() {
+			when(resultFuture.get(anyLong(), any())).thenReturn(grpcResponse);
+
+			var result = service.waitUntilTransferCompleted(sender);
+
+			assertThat(result).isEqualTo(grpcResponse);
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldHandleInterruptedException() {
+			var interruptedException = new InterruptedException();
+
+			when(resultFuture.get(anyLong(), any())).thenThrow(interruptedException);
+
+			assertThrows(TechnicalException.class, () -> service.waitUntilTransferCompleted(sender));
+			verify(sender).cancelOnError(interruptedException);
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldHandleTimeout() {
+			when(resultFuture.get(anyLong(), any())).thenThrow(new TimeoutException());
+
+			assertThrows(TechnicalException.class, () -> service.waitUntilTransferCompleted(sender));
+			verify(sender).cancelOnTimeout();
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldHandleExecutionException() {
+			var executionException = new ExecutionException(new RuntimeException());
+			when(resultFuture.get(anyLong(), any())).thenThrow(executionException);
+
+			assertThrows(TechnicalException.class, () -> service.waitUntilTransferCompleted(sender));
+			verify(sender).cancelOnTimeout();
+		}
+
+	}
+
+	@Nested
+	class TestGetPostfach {
+
+		@Test
+		void shouldHasTyp() {
+			var postfachType = service.getPostfachType();
+
+			assertThat(postfachType).isEqualTo(BayernIdPostfachRemoteService.POSTFACH_TYPE);
+		}
+
+		@Test
+		void shouldSetReplyNotAllowed() {
+			var isReplyAllowed = service.isReplyAllowed();
+
+			assertThat(isReplyAllowed).isFalse();
+		}
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachResponseHandlerTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachResponseHandlerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e9fcf849c601f39a0b5707175288642da104829
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachResponseHandlerTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.mockito.InjectMocks;
+
+class BayernIdPostfachResponseHandlerTest {
+
+	@InjectMocks
+	private BayernIdPostfachResponseHandler handler;
+
+	@Nested
+	@DisplayName("Test successful Postfachserver response")
+	class TestSuccessfulPostfachServerResponse {
+
+		@Test
+		void shouldNotThrowAnyException() {
+			assertThatCode(() -> handler.handleResponse(BayernIdResponseTestFactory.create())).doesNotThrowAnyException();
+		}
+	}
+
+	@Nested
+	@DisplayName("Test faulty Postfachserver response ")
+	class TestFaultyPostfachserverResponse {
+
+		@DisplayName("Fehler im OK.KOMM-Schema")
+		@ParameterizedTest(name = "when response status: {0}")
+		@EnumSource(value = MailSendingResponseStatus.class, mode = EnumSource.Mode.EXCLUDE, names = { "SUCCESS" })
+		void shouldThrowPostfachBadRequestExceptionForSchluessel(MailSendingResponseStatus responseStatus) {
+			var bayernIdResponse = BayernIdResponseTestFactory.createBuilder().success(false).status(responseStatus.getSchluessel()).build();
+
+			var exception = Assertions.assertThrows(BayernIdServerException.class, () -> handler.handleResponse(bayernIdResponse));
+			assertThat(exception.getMessage()).startsWith("9006 / %s / %s".formatted(responseStatus.getSchluessel(), responseStatus.getMessage()));
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPropertiesITCase.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPropertiesITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0268ff1cf1ca65b26c1fac5ec226717f5be91c4
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPropertiesITCase.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+import de.ozgcloud.common.test.ITCase;
+
+@SpringBootTest(classes = { BayernIdProperties.class })
+@ITCase
+class BayernIdPropertiesITCase {
+
+	private static final String NAME = "test name";
+
+	@TestPropertySource(properties = {
+			"ozgcloud.bayernid.enabled=true",
+			"ozgcloud.bayernid.absender.postkorbId=28721c6f-b78f-4d5c-a048-19fd2fc429d2",
+			"ozgcloud.bayernid.absender.name=test name",
+			"ozgcloud.bayernid.absender.anschrift=Niemalsgasse 5, 99999 Irgendwo Stadt",
+			"ozgcloud.bayernid.absender.dienst=Stadtverwaltung",
+			"ozgcloud.bayernid.absender.mandant=Fürth",
+			"ozgcloud.bayernid.absender.gemeindeSchluessel=09563000",
+	})
+	@DisplayName("Test loading bayernid configuration")
+	@Nested
+	class TestLoadingConfiguration {
+
+		// TODO remove access data
+		private static final String POSTKORBID = "28721c6f-b78f-4d5c-a048-19fd2fc429d2";
+		private static final String DIENST = "Stadtverwaltung";
+		private static final String ANSCHRIFT = "Niemalsgasse 5, 99999 Irgendwo Stadt";
+		private static final String PASSWORD = "";
+		private static final String RESOURCE_PATH = "bayernid.p12";
+		private static final String MANDANT = "Fürth";
+		private static final String GEMEINDE_SCHLUESSEL = "09563000";
+
+		@Autowired
+		private BayernIdProperties properties;
+
+		@Test
+		void shouldHaveProperties() {
+			assertThat(properties).isNotNull();
+		}
+
+		@Test
+		void shouldHaveAbsender() {
+			assertThat(properties.getAbsender())
+					.isNotNull()
+					.usingRecursiveComparison()
+					.isEqualTo(Absender.builder()
+							.anschrift(ANSCHRIFT)
+							.dienst(DIENST)
+							.name(NAME)
+							.mandant(MANDANT)
+							.gemeindeSchluessel(GEMEINDE_SCHLUESSEL)
+							.postkorbId(POSTKORBID).build());
+		}
+
+	}
+
+	@TestPropertySource(properties = { "ozgcloud.other=test name" })
+	@DisplayName("Test loading application context without bayerid properties")
+	@Nested
+	class TestLoadingOtherConfiguration {
+
+		@Value("${ozgcloud.other}")
+		private String testValue;
+
+		@Autowired(required = false)
+		private BayernIdProperties properties;
+
+		@Test
+		void shouldLoadTestProperty() {
+			assertThat(testValue).isEqualTo(NAME);
+		}
+
+		@Test
+		void shouldNotLoadBayernIdProperties() {
+			assertThat(properties).isNull();
+		}
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdResponseTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..54f6a07de6ea71b2a031ee9c3720a6edc05c7560
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdResponseTestFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.akdb.egov.bsp.nachrichten.BspQuittung;
+import de.akdb.egov.bsp.nachrichten.SchluesseltabelleType;
+import de.ozgcloud.nachrichten.postfach.bayernid.BayernIdResponse.BayernIdResponseBuilder;
+
+public class BayernIdResponseTestFactory {
+	public static final String ERGAENZENE_HINWEISE = "ergaenzenderHinweis";
+
+	public static BayernIdResponse create() {
+		return createBuilder().build();
+	}
+
+	public static BayernIdResponseBuilder createBuilder() {
+		return BayernIdResponse.builder()
+				.success(true)
+				.status("0")
+				.message(ERGAENZENE_HINWEISE);
+	}
+
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BspNachrichtTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BspNachrichtTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..34b723da2babae4e8a6dbdc56e26d081aa5dbe94
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BspNachrichtTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.akdb.egov.bsp.nachrichten.BspNachricht;
+import de.akdb.egov.bsp.nachrichten.NachrichtenKopfType;
+import lombok.val;
+
+public class BspNachrichtTestFactory {
+	public static final NachrichtenKopfType NACHRICHTEN_KOPF_TYPE = NachrichtenKopfTypeTestFactory.create();
+
+	public static BspNachricht create() {
+		val bspNachricht = new BspNachricht();
+		bspNachricht.setNachrichtenKopf(NACHRICHTEN_KOPF_TYPE);
+		return bspNachricht;
+	}
+
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/EmpfaengerTypeTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/EmpfaengerTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0f8dd8f5b87b4729e03771b06780731e2db80c0
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/EmpfaengerTypeTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.util.UUID;
+
+import de.akdb.egov.bsp.nachrichten.EmpfaengerType;
+import lombok.val;
+
+public class EmpfaengerTypeTestFactory {
+	public static final String POSTKORB_ID = UUID.randomUUID().toString();
+
+	public static EmpfaengerType create() {
+		val empfaengerType = new EmpfaengerType();
+		empfaengerType.setPostkorbId(POSTKORB_ID);
+		return empfaengerType;
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/FileSenderTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/FileSenderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..75536d889d2d71675831d5ab35d0c116cfbce111
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/FileSenderTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.InputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.FileSender.StreamReader;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import io.grpc.stub.CallStreamObserver;
+import lombok.SneakyThrows;
+
+class FileSenderTest {
+
+	private FileSender fileSender;
+
+	@Mock
+	private BiFunction<byte[], Integer, GrpcSendBayernIdMessageRequest> chunkBuilder;
+	@Mock
+	private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+	@Mock
+	private GrpcSendBayernIdMessageRequest metadata;
+	@Mock
+	private InputStream inputStream;
+
+	@BeforeEach
+	void setup() {
+		fileSender = spy(new FileSender(chunkBuilder, requestObserver, metadata, inputStream));
+	}
+
+	@Nested
+	class TestSend {
+
+		@Test
+		void shouldCallSendMetadata() {
+			fileSender.send();
+
+			verify(fileSender).sendMetadata();
+		}
+
+		@Test
+		void shouldCallSendNextChunk() {
+			when(requestObserver.isReady()).thenReturn(true);
+			doAnswer(invocation -> {
+				((AtomicBoolean) ReflectionTestUtils.getField(fileSender, "done")).set(true);
+				return null;
+			}).when(fileSender).sendNextChunk();
+
+			fileSender.send();
+
+			verify(fileSender).sendNextChunk();
+		}
+
+		@Test
+		void shouldNotCallSendNextChunkWhenDone() {
+			((AtomicBoolean) ReflectionTestUtils.getField(fileSender, "done")).set(true);
+
+			fileSender.send();
+
+			verify(fileSender, never()).sendNextChunk();
+		}
+
+		@Test
+		void shouldNotCallSendNextChunkWhenNotReady() {
+			fileSender.send();
+
+			verify(fileSender, never()).sendNextChunk();
+		}
+	}
+
+	@Nested
+	class TestSendMetadata {
+
+		@Test
+		void shouldCallOnNextOnce() {
+			fileSender.sendMetadata();
+			fileSender.sendMetadata();
+
+			verify(requestObserver).onNext(metadata);
+		}
+
+	}
+
+	@Nested
+	class TestSendNextChunk {
+
+		@Test
+		void shouldCallSendChunk() {
+			var contentToSend = new byte[] { 1, 2, 3, 4, 5 };
+			setContent(contentToSend);
+
+			fileSender.sendNextChunk();
+
+			verify(fileSender).sendChunk(contentToSend, 5);
+		}
+
+		@Test
+		void shouldReturnContentLength() {
+			var contentToSend = new byte[] { 1, 2, 3, 4, 5 };
+			setContent(contentToSend);
+
+			var length = fileSender.sendNextChunk();
+
+			assertThat(length).isEqualTo(contentToSend.length);
+		}
+
+		@Test
+		void shouldCallEndTransfer() {
+			setContent(new byte[] {});
+
+			fileSender.sendNextChunk();
+
+			verify(fileSender).endTransfer();
+		}
+
+		@SneakyThrows
+		void setContent(byte[] contentToSend) {
+			var streamReader = getStreamReader();
+			ReflectionTestUtils.setField(streamReader, "buffer", contentToSend);
+			when(inputStream.read(any(), anyInt(), anyInt())).thenReturn(contentToSend.length);
+		}
+
+	}
+
+	@Nested
+	class TestEndTransfer {
+
+		@Mock
+		private StreamReader streamReader;
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(fileSender, "streamReader", streamReader);
+		}
+
+		@Test
+		void shouldSetDone() {
+			fileSender.endTransfer();
+
+			var done = (AtomicBoolean) ReflectionTestUtils.getField(fileSender, "done");
+			assertThat(done.get()).isTrue();
+		}
+
+		@Test
+		void shouldCloseStream() {
+			fileSender.endTransfer();
+
+			verify(streamReader).close();
+		}
+	}
+
+	@Nested
+	class TestSendChunk {
+
+		@Mock
+		private GrpcSendBayernIdMessageRequest chunkRequest;
+
+		private byte[] contentToSend = new byte[] { 1, 2, 3, 4, 5 };
+		private int length = 5;
+
+
+		@Test
+		void shouldCallChunkBuilder() {
+			fileSender.sendChunk(contentToSend, length);
+
+			verify(chunkBuilder).apply(contentToSend, length);
+		}
+
+		@Test
+		void shouldCallOnNext() {
+			when(chunkBuilder.apply(any(), anyInt())).thenReturn(chunkRequest);
+
+			fileSender.sendChunk(contentToSend, length);
+
+			verify(requestObserver).onNext(chunkRequest);
+		}
+
+	}
+
+	StreamReader getStreamReader() {
+		return (StreamReader) ReflectionTestUtils.getField(fileSender, "streamReader");
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/FreiTextTypeTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/FreiTextTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..91a86c3fb228b252b61bb5678fd2240f6260eed3
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/FreiTextTypeTestFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.akdb.egov.bsp.nachrichten.FreiTextType;
+import de.akdb.egov.bsp.nachrichten.SchluesseltabelleType;
+import lombok.val;
+
+public class FreiTextTypeTestFactory {
+	public static final String MESSAGE_TEXT = "Test Nachricht\n\nHallo";
+
+	public FreiTextType create() {
+		val freiText = new FreiTextType();
+		freiText.setText(MESSAGE_TEXT);
+		return freiText;
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/GrpcSendBayernIdMessageResponseTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/GrpcSendBayernIdMessageResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..3aa0719d3574451bd919d365e4dee250405bab2f
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/GrpcSendBayernIdMessageResponseTestFactory.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+
+public class GrpcSendBayernIdMessageResponseTestFactory {
+
+	public static final String STATUS = "code";
+	public static final String MESSAGE_TEXT = "messageText";
+
+	public static GrpcSendBayernIdMessageResponse create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcSendBayernIdMessageResponse.Builder createBuilder() {
+		return GrpcSendBayernIdMessageResponse.newBuilder()
+				.setSuccess(true)
+				.setStatus(STATUS)
+				.setMessage(MESSAGE_TEXT);
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/IdentifikationNachrichtTypeTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/IdentifikationNachrichtTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..66ff238c0e12da06f2cae313e6f78acff6bebd43
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/IdentifikationNachrichtTypeTestFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.UUID;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import de.akdb.egov.bsp.nachrichten.IdentifikationNachrichtType;
+import de.akdb.egov.bsp.nachrichten.SchluesseltabelleType;
+import lombok.val;
+
+class IdentifikationNachrichtTypeTestFactory {
+	public static final XMLGregorianCalendar ERSTELLUNGSZEITPUNKT = now();
+	public static final String NACHRICHTEN_ID = UUID.randomUUID().toString();
+
+	private static XMLGregorianCalendar now() {
+		try {
+			val c = new GregorianCalendar();
+			c.setTime(Date.from(Instant.now()));
+			return DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
+		} catch (DatatypeConfigurationException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	public static IdentifikationNachrichtType create() {
+		IdentifikationNachrichtType identifikationNachrichtType = new IdentifikationNachrichtType();
+		identifikationNachrichtType.setNachrichtenId(NACHRICHTEN_ID);
+		identifikationNachrichtType.setErstellungszeitpunkt(ERSTELLUNGSZEITPUNKT);
+		return identifikationNachrichtType;
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/MailSendingResponseStatusTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/MailSendingResponseStatusTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8d26d12e17c8f9c51856efe05c4b22ebe0ad078
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/MailSendingResponseStatusTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class MailSendingResponseStatusTest {
+
+	@Test
+	void shouldCreateSuccessResult() {
+		assertThat(MailSendingResponseStatus.SUCCESS.getSchluessel()).isEqualTo("0");
+	}
+
+	@Test
+	void shouldCreateFromSchluessel() {
+		assertThat(MailSendingResponseStatus.fromSchluessel("20")).isEqualTo(MailSendingResponseStatus.ERROR_IN_MESSAGE_SCHEMA);
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/MessageWithFilesSenderTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/MessageWithFilesSenderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1efd3e30ec8f02a80a7601b6920e6ce40ab2dcd8
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/MessageWithFilesSenderTest.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import de.ozgcloud.common.binaryfile.BinaryFileUploadStreamObserver;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageRequest;
+import de.ozgcloud.nachrichten.postfach.bayernid.proxy.GrpcSendBayernIdMessageResponse;
+import io.grpc.stub.CallStreamObserver;
+import io.grpc.stub.StreamObserver;
+
+class MessageWithFilesSenderTest {
+
+	private MessageWithFilesSender messageWithFilesSender;
+
+	@Mock
+	private Function<StreamObserver<GrpcSendBayernIdMessageResponse>, CallStreamObserver<GrpcSendBayernIdMessageRequest>> reqObserverBuilder;
+	@Mock
+	private GrpcSendBayernIdMessageRequest messageMetadata;
+	@Mock
+	private List<String> attachmentIds;
+	@Mock
+	private Function<String, BayernIdAttachment> toAttachment;
+	@Mock
+	private Function<BayernIdAttachment, GrpcSendBayernIdMessageRequest> attachmentMetadataMapper;
+	@Mock
+	private BiFunction<byte[], Integer, GrpcSendBayernIdMessageRequest> chunkBuilder;
+
+	@BeforeEach
+	void setup() {
+		messageWithFilesSender = spy(
+				MessageWithFilesSender.builder().reqObserverBuilder(reqObserverBuilder).messageMetadata(messageMetadata).toAttachment(toAttachment)
+						.attachmentMetadataMapper(attachmentMetadataMapper).chunkBuilder(chunkBuilder).build());
+	}
+
+	@Nested
+	class TestSend {
+
+		@Mock
+		private BinaryFileUploadStreamObserver<GrpcSendBayernIdMessageRequest, GrpcSendBayernIdMessageResponse> responseStreamObserver;
+		@Mock
+		private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+
+		@Test
+		void shouldReturnSameObject() {
+			var result = messageWithFilesSender.send();
+
+			assertThat(result).isSameAs(messageWithFilesSender);
+		}
+
+		@Test
+		void shouldCallRequestObserverBuilder() {
+			try (var createMock = Mockito.mockStatic(BinaryFileUploadStreamObserver.class)) {
+				createMock.when(() -> BinaryFileUploadStreamObserver.create(any(), any())).thenReturn(responseStreamObserver);
+
+				messageWithFilesSender.send();
+
+				verify(reqObserverBuilder).apply(responseStreamObserver);
+			}
+		}
+
+		@Test
+		void shouldSetRequestStreamObserver() {
+			when(reqObserverBuilder.apply(any())).thenReturn(requestObserver);
+
+			messageWithFilesSender.send();
+
+			assertThat(messageWithFilesSender).extracting("requestObserver").isSameAs(requestObserver);
+		}
+	}
+
+	@Nested
+	class TestSendNext {
+
+		@Mock
+		private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "requestObserver", requestObserver);
+		}
+
+		@Test
+		void shouldCheckIfDone() {
+			doNothing().when(messageWithFilesSender).waitForObserver();
+
+			messageWithFilesSender.sendNext();
+
+			verify(messageWithFilesSender).waitForObserver();
+		}
+
+		@Test
+		void shouldRetrunIfDone() {
+			((AtomicBoolean) ReflectionTestUtils.getField(messageWithFilesSender, "done")).set(true);
+
+			messageWithFilesSender.sendNext();
+
+			verify(messageWithFilesSender, never()).waitForObserver();
+		}
+
+		@Test
+		void shouldCallSendMetadata() {
+			doNothing().when(messageWithFilesSender).waitForObserver();
+
+			messageWithFilesSender.sendNext();
+
+			verify(messageWithFilesSender).sendMetadata();
+		}
+
+		@Test
+		void shouldCallSendAttachments() {
+			doNothing().when(messageWithFilesSender).waitForObserver();
+
+			messageWithFilesSender.sendNext();
+
+			verify(messageWithFilesSender).sendAttachments();
+		}
+	}
+
+	@Nested
+	class TestSendMetadata {
+
+		@Mock
+		private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "requestObserver", requestObserver);
+		}
+
+		@Test
+		void shouldCallOnNextOnce() {
+			messageWithFilesSender.sendMetadata();
+			messageWithFilesSender.sendMetadata();
+
+			verify(requestObserver).onNext(messageMetadata);
+		}
+
+	}
+
+	@Nested
+	class TestSendAttachments {
+
+		private String attachmentId = "id1";
+
+		@Mock
+		private FileSender fileSender;
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "attachmentIds", List.of(attachmentId));
+			doNothing().when(messageWithFilesSender).completeRequest();
+		}
+
+		@Test
+		void shouldCallCreateFileSenders() {
+			doReturn(fileSender).when(messageWithFilesSender).buildFileSender(any());
+
+			messageWithFilesSender.sendAttachments();
+
+			verify(messageWithFilesSender).createFileSenders();
+		}
+
+		@Test
+		void shouldNotRecreateFileSenders() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "fileSenders", List.of(fileSender));
+
+			messageWithFilesSender.sendAttachments();
+
+			verify(messageWithFilesSender, never()).createFileSenders();
+		}
+
+		@Test
+		void shouldCallSendOnFileSender() {
+			doReturn(fileSender).when(messageWithFilesSender).buildFileSender(any());
+
+			messageWithFilesSender.sendAttachments();
+
+			verify(fileSender).send();
+		}
+
+		@Test
+		void shouldCallCompleteRequest() {
+			doReturn(fileSender).when(messageWithFilesSender).buildFileSender(any());
+
+			messageWithFilesSender.sendAttachments();
+
+			verify(messageWithFilesSender).completeRequest();
+		}
+	}
+
+	@Nested
+	class TestCreateFileSenders {
+
+		private String attachmentId = "id1";
+
+		@Mock
+		private FileSender fileSender;
+
+		@BeforeEach
+		void setup() {
+			doReturn(fileSender).when(messageWithFilesSender).buildFileSender(any());
+			ReflectionTestUtils.setField(messageWithFilesSender, "attachmentIds", List.of(attachmentId));
+		}
+
+		@Test
+		void shouldCalToAttachment() {
+			messageWithFilesSender.createFileSenders();
+
+			verify(toAttachment).apply(attachmentId);
+		}
+
+		@Test
+		void shouldCallBuildFileSender() {
+			messageWithFilesSender.createFileSenders();
+
+			verify(messageWithFilesSender).buildFileSender(any());
+		}
+
+		@Test
+		void shouldReturnFileSenders() {
+			var result = messageWithFilesSender.createFileSenders();
+
+			assertThat(result).containsExactly(fileSender);
+		}
+	}
+
+	@Nested
+	class TestBuildFileSender {
+
+		private String attachmentId = "id1";
+
+		@Mock
+		private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+		@Mock
+		private GrpcSendBayernIdMessageRequest attachmentMetadata;
+
+		@Mock
+		private BayernIdAttachment attachment;
+		@Mock
+		private InputStream inputStream;
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "requestObserver", requestObserver);
+		}
+
+		@Test
+		void shouldSetChunkBuilder() {
+			var result = messageWithFilesSender.buildFileSender(attachment);
+
+			assertThat(result).extracting("chunkBuilder").isSameAs(chunkBuilder);
+		}
+
+		@Test
+		void shouldSetRequestObserver() {
+			var result = messageWithFilesSender.buildFileSender(attachment);
+
+			assertThat(result).extracting("requestObserver").isSameAs(requestObserver);
+		}
+
+		@Test
+		void shouldCallAttachmentMetadataMapper() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "attachmentMetadataMapper", attachmentMetadataMapper);
+
+			messageWithFilesSender.buildFileSender(attachment);
+
+			verify(attachmentMetadataMapper).apply(attachment);
+		}
+
+		@Test
+		void shouldSetAttachmentMetadata() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "attachmentMetadataMapper", attachmentMetadataMapper);
+			when(attachmentMetadataMapper.apply(any())).thenReturn(attachmentMetadata);
+
+			var result = messageWithFilesSender.buildFileSender(attachment);
+
+			assertThat(result).extracting("metadata").isSameAs(attachmentMetadata);
+		}
+
+		@Test
+		void shouldGetContent() {
+			messageWithFilesSender.buildFileSender(attachment);
+
+			verify(attachment).getContent();
+		}
+	}
+
+	@Nested
+	class TestCompleteRequest {
+
+		@Mock
+		private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "requestObserver", requestObserver);
+		}
+
+		@Test
+		void shouldSetDone() {
+			messageWithFilesSender.completeRequest();
+
+			var done = (AtomicBoolean) ReflectionTestUtils.getField(messageWithFilesSender, "done");
+			assertThat(done.get()).isTrue();
+		}
+
+		@Test
+		void shouldCallOnCompleted() {
+			messageWithFilesSender.completeRequest();
+
+			verify(requestObserver).onCompleted();
+		}
+	}
+
+	@Nested
+	class TestCancelOnTimeout {
+
+		@Mock
+		private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "requestObserver", requestObserver);
+		}
+
+		@Test
+		void shouldCallCancelOnRequestObserver() {
+			messageWithFilesSender.cancelOnTimeout();
+
+			verify(requestObserver).onError(any(TechnicalException.class));
+		}
+
+		@Test
+		void shouldCancelResultFuture() {
+			messageWithFilesSender.cancelOnTimeout();
+
+			assertThat(messageWithFilesSender.getResultFuture()).isCancelled();
+		}
+	}
+
+	@Nested
+	class TestCancelOnError {
+
+		@Mock
+		private CallStreamObserver<GrpcSendBayernIdMessageRequest> requestObserver;
+
+		@BeforeEach
+		void setup() {
+			ReflectionTestUtils.setField(messageWithFilesSender, "requestObserver", requestObserver);
+		}
+
+		@Test
+		void shouldCallCancelOnRequestObserver() {
+			var exception = new RuntimeException("test");
+			messageWithFilesSender.cancelOnError(exception);
+
+			verify(requestObserver).onError(exception);
+		}
+
+		@Test
+		void shouldCancelResultFuture() {
+			messageWithFilesSender.cancelOnError(new TechnicalException("test"));
+
+			assertThat(messageWithFilesSender.getResultFuture()).isCancelled();
+		}
+	}
+}
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/NachrichtenInhaltTypeTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/NachrichtenInhaltTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e1b28a6f846885fd6357798ffffabecebe8a190
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/NachrichtenInhaltTypeTestFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.akdb.egov.bsp.nachrichten.NachrichtenInhaltType;
+import lombok.val;
+
+public class NachrichtenInhaltTypeTestFactory {
+	public static final String BETREFF = "Test Nachricht";
+
+	public NachrichtenInhaltType create() {
+		val nachrichtenInhalt = new NachrichtenInhaltType();
+		nachrichtenInhalt.setBetreff(BETREFF);
+		return nachrichtenInhalt;
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/NachrichtenKopfTypeTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/NachrichtenKopfTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..11cc84fa96f575c89b5e830882453671b7e6805a
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/NachrichtenKopfTypeTestFactory.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import de.akdb.egov.bsp.nachrichten.AbsenderType;
+import de.akdb.egov.bsp.nachrichten.EmpfaengerType;
+import de.akdb.egov.bsp.nachrichten.IdentifikationNachrichtType;
+import de.akdb.egov.bsp.nachrichten.NachrichtenKopfType;
+import lombok.val;
+
+public class NachrichtenKopfTypeTestFactory {
+	public static final IdentifikationNachrichtType IDENTIFIKATION_NACHRICHT_TYPE = IdentifikationNachrichtTypeTestFactory.create();
+	public static final AbsenderType ABSENDER_TYPE = AbsenderTypeTestFactory.create();
+	public static final EmpfaengerType EMPFAENGER_TYPE = EmpfaengerTypeTestFactory.create();
+
+	public static NachrichtenKopfType create() {
+		val nachrichtenKopfType = new NachrichtenKopfType();
+		nachrichtenKopfType.setIdentifikationNachricht(IDENTIFIKATION_NACHRICHT_TYPE);
+		nachrichtenKopfType.setAbsender(ABSENDER_TYPE);
+		nachrichtenKopfType.setEmpfaenger(EMPFAENGER_TYPE);
+		return nachrichtenKopfType;
+	}
+
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/SendBspNachrichtNativeOutputTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/SendBspNachrichtNativeOutputTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..fdda90d823d0b527aa3baed3dfbe41cfe7417f55
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/SendBspNachrichtNativeOutputTestFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import akdb.bsp.postkorb.komm.webservice.SendBspNachrichtNativeOutput;
+import lombok.val;
+
+public class SendBspNachrichtNativeOutputTestFactory {
+
+	public static final String BSP_QUITTUNG = "quittung";
+
+	public static SendBspNachrichtNativeOutput create() {
+		val result = new SendBspNachrichtNativeOutput();
+		result.setBspQuittung(BSP_QUITTUNG);
+		return result;
+	}
+}
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/ZuVorgangTypeTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/ZuVorgangTypeTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f6b4ec1902f72bd1039f271fc732ef5468abfb5
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/ZuVorgangTypeTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import java.util.UUID;
+
+import de.akdb.egov.bsp.nachrichten.ZuVorgangType;
+import lombok.val;
+
+public class ZuVorgangTypeTestFactory {
+	public static final String VORGANG_ID = UUID.randomUUID().toString();
+
+	public static ZuVorgangType create() {
+		val vorgang = new ZuVorgangType();
+		vorgang.setVorgangsId(VORGANG_ID);
+		return vorgang;
+	}
+}
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/AttachmentServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentServiceTest.java
similarity index 71%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/AttachmentServiceTest.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentServiceTest.java
index 7cd2df66e30b1b0aa4bec866ae5cac71458ba47e..cc6ac5b2fc051721b0c384a81603cbc75c52dd9b 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/AttachmentServiceTest.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -44,11 +44,14 @@ import org.mockito.Mock;
 
 import com.mongodb.client.gridfs.model.GridFSFile;
 
-class AttachmentServiceTest {
+import de.ozgcloud.nachrichten.postfach.BinaryFileService;
+import de.ozgcloud.nachrichten.postfach.FileId;
+
+class MessageAttachmentServiceTest {
 	private static final FileId FILE_ID = FileId.from("42");
 
 	@InjectMocks
-	private AttachmentService attachmentService;
+	private MessageAttachmentService messageAttachmentService;
 
 	@Mock
 	private BinaryFileService fileService;
@@ -71,17 +74,18 @@ class AttachmentServiceTest {
 
 		@Test
 		void shouldHaveAttachmentWithFileName() {
-			MessageAttachment attachment = attachmentService.getMessageAttachment(FILE_ID);
+			MessageAttachment attachment = messageAttachmentService.getMessageAttachment(FILE_ID);
 
 			assertThat(attachment.getFileName()).isEqualTo(MessageAttachmentTestFactory.FILENAME);
 		}
 
 		@Test
 		void shouldHaveAttachmentContent() {
-			MessageAttachment attachment = attachmentService.getMessageAttachment(FILE_ID);
+			MessageAttachment attachment = messageAttachmentService.getMessageAttachment(FILE_ID);
 
 			assertThat(attachment.getContent()).isEqualTo(MessageAttachmentTestFactory.CONTENT);
 		}
+
 	}
 
 	@Nested
@@ -94,16 +98,34 @@ class AttachmentServiceTest {
 
 		@Test
 		void shouldGetInputStream() {
-			InputStream input = attachmentService.getAttachmentContentStream(FILE_ID);
+			InputStream input = messageAttachmentService.getAttachmentContentStream(FILE_ID);
 
 			assertThat(input).isNotNull();
 		}
 
 		@Test
 		void shouldGetContent() throws IOException {
-			String input = attachmentService.getAttachmentContent(FILE_ID);
+			String input = messageAttachmentService.getAttachmentContent(FILE_ID);
 
 			assertThat(input).isEqualTo(MessageAttachmentTestFactory.CONTENT);
 		}
 	}
+
+	@Nested
+	class TestMapAttachmentFile {
+
+		@Test
+		void shouldMapFileName() {
+			var attachmentFile = messageAttachmentService.mapAttachmentFile(MessageAttachmentTestFactory.create());
+
+			assertThat(attachmentFile.getName()).isEqualTo(MessageAttachmentTestFactory.FILENAME);
+		}
+
+		@Test
+		void shouldMapContent() {
+			var attachmentFile = messageAttachmentService.mapAttachmentFile(MessageAttachmentTestFactory.create());
+
+			assertThat(attachmentFile.getContent()).hasContent(MessageAttachmentTestFactory.CONTENT);
+		}
+	}
 }
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/MessageAttachmentTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentTestFactory.java
similarity index 87%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/MessageAttachmentTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentTestFactory.java
index 97e9b5756be2423056984c95ab1ee772adb5b626..42bb7d14a78c59f85d6b805d8d5657444645d0ba 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/MessageAttachmentTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageAttachmentTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 public class MessageAttachmentTestFactory {
 
@@ -35,8 +35,6 @@ public class MessageAttachmentTestFactory {
 	}
 
 	public static MessageAttachment.MessageAttachmentBuilder createBuilder() {
-		return MessageAttachment.builder()
-				.fileName(FILENAME)
-				.content(CONTENT);
+		return MessageAttachment.builder().fileName(FILENAME).content(CONTENT);
 	}
 }
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageJsonReplyTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageJsonReplyTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ddffcdbc2844a754f5931c7c5efb2a065191485a
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageJsonReplyTestFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.osi;
+
+public class MessageJsonReplyTestFactory {
+
+	private static final String REPLY_JSON_TMPL = """
+						[{
+			  "messageId": "%s",
+			  "nameIdentifier": "%s",
+			  "body": "%s",
+			  "isHtml": false,
+			  "replyAction": %d,
+			  "subject": "%s",
+			  "sequenceNumber": "%s",
+			  "eidasLevel": 1,
+			  "isObligatory": true,
+			  "attachments": [{
+			  	"fileName": "%s",
+			  	"content": "%s"
+			  }]
+			}]""";
+
+	public static String buildReplyJson() {
+		return buildReplyJson(MessageTestFactory.create(), MessageAttachmentTestFactory.create());
+	}
+
+	public static String buildReplyJson(Message msg, MessageAttachment attachement) {
+		return String.format(REPLY_JSON_TMPL,
+				msg.getMessageId(),
+				msg.getPostfachId(),
+				msg.getMailBody(),
+				msg.getReplyOption().toValue(),
+				msg.getSubject(),
+				msg.getVorgangId(),
+				attachement.getFileName(),
+				attachement.getContent());
+	}
+}
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/MessageTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageTestFactory.java
similarity index 88%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/MessageTestFactory.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageTestFactory.java
index 25077cd084eb14b40bb4654146518182cb33c6cd..097b45ecec296ac207dfe57c7c930e99ceffcbcb 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/MessageTestFactory.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/MessageTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import java.util.List;
 import java.util.UUID;
 
-import de.itvsh.ozg.mail.postfach.Message.EidasLevel;
-import de.itvsh.ozg.mail.postfach.Message.ReplyOption;
+import de.ozgcloud.nachrichten.postfach.osi.Message.EidasLevel;
 
 public class MessageTestFactory {
 
@@ -35,7 +34,7 @@ public class MessageTestFactory {
 	public static final String POSTFACH_ID = UUID.randomUUID().toString();
 	public static final String VORGANG_ID = UUID.randomUUID().toString();
 
-	public static final String MAIL_BODY = "BodyString";
+	public static final String MAIL_BODY = "Body<br>String";
 	public static final boolean IS_HTML = false;
 	public static final ReplyOption REPLY_OPTION = ReplyOption.MANDATORY;
 	public static final String SUBJECT = "Test Subject";
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachMessageMapperTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachMessageMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..85e811d13d854daa74297cbeff8232003f11ed4f
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachMessageMapperTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.osi;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.nachrichten.postfach.FileId;
+import de.ozgcloud.nachrichten.postfach.PostfachAddressTestFactory;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+
+class OsiPostfachMessageMapperTest {
+
+	@InjectMocks
+	private OsiPostfachMessageMapper mapper = Mappers.getMapper(OsiPostfachMessageMapper.class);
+	@Mock
+	private MessageAttachmentService messageAttachmentService;
+	@Mock
+	private GrpcObjectMapper grpcObjectMapper;
+
+	@DisplayName("To mail")
+	@Nested
+	class TestToNachricht {
+
+		@Test
+		void shouldSetDirection() {
+			var mail = mapper.toPostfachNachricht(MessageTestFactory.create());
+
+			assertThat(mail.getDirection()).isEqualTo(Direction.IN);
+		}
+
+		@Test
+		void shouldSetCreatedAt() {
+			var mail = mapper.toPostfachNachricht(MessageTestFactory.create());
+
+			assertThat(mail.getCreatedAt()).isNotNull().isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS));
+		}
+
+		@Test
+		void shouldIgnoreSentInformation() {
+			var mail = mapper.toPostfachNachricht(MessageTestFactory.create());
+
+			assertThat(mail.getSentAt()).isNull();
+			assertThat(mail.getSentSuccessful()).isNull();
+		}
+
+		@Test
+		void shouldPersistAttachment() {
+			mapper.toPostfachNachricht(MessageTestFactory.create());
+
+			verify(messageAttachmentService).persistAttachment(MessageTestFactory.VORGANG_ID, MessageTestFactory.ATTACHMENTS.get(0));
+		}
+
+		@Test
+		void shouldSetPostfachAddress() {
+			var expectedPostfachAddress = PostfachAddressTestFactory.createBuilder().serviceKontoType(OsiPostfachRemoteService.POSTFACH_TYPE).build();
+
+			var mail = toMail();
+
+			assertThat(mail.getPostfachAddress()).usingRecursiveComparison().isEqualTo(expectedPostfachAddress);
+		}
+
+		@Test
+		void shouldPreserveNewLineInBody() {
+			var bodyText = "line\nline";
+			var mail = mapper.toPostfachNachricht(MessageTestFactory.createBuilder().mailBody(bodyText).build());
+
+			assertThat(mail.getMailBody()).isEqualTo(bodyText);
+		}
+
+		@Test
+		void shouldRecodeAND() {
+			var mail = mapper.toPostfachNachricht(MessageTestFactory.createBuilder().mailBody("this&amp;that").build());
+
+			assertThat(mail.getMailBody()).isEqualTo("this&that");
+		}
+
+		private PostfachNachricht toMail() {
+			return mapper.toPostfachNachricht(MessageTestFactory.create());
+		}
+	}
+
+	@DisplayName("To osi message")
+	@Nested
+	class TestToOsiMessage {
+
+		@Test
+		void shouldCallAttachmentService() {
+			var fileId = FileId.from("42");
+
+			toOsiMessage(PostfachNachrichtTestFactory.createBuilder().attachments(List.of(fileId.toString())).build());
+
+			verify(messageAttachmentService).getMessageAttachment(fileId);
+		}
+
+		@Test
+		void shouldMapFields() {
+			var message = toOsiMessage(PostfachNachrichtTestFactory.create());
+
+			assertThat(message.getSubject()).isEqualTo(MessageTestFactory.SUBJECT);
+			assertThat(message.getAttachments()).hasSize(1);
+		}
+
+		@Test
+		void shouldMapMailBody() {
+			var message = toOsiMessage(PostfachNachrichtTestFactory.create());
+
+			assertThat(message.getMailBody()).isEqualTo(MessageTestFactory.MAIL_BODY);
+		}
+
+		@Test
+		void shouldReplaceNewLineToHtml() {
+			var bodyText = "line\nline&";
+			var message = toOsiMessage(PostfachNachrichtTestFactory.createBuilder().mailBody(bodyText).build());
+
+			assertThat(message.getMailBody()).isEqualTo("line<br>line&");
+		}
+
+		@DisplayName("build postfachId")
+		@Nested
+		class TestToPostfachId {
+
+			@DisplayName("by existing postfachAddress")
+			@Nested
+			class TestWithExistingPostfachAddress {
+
+				@Test
+				void shouldMapPostfachAddressToPostfachId() {
+					var message = toOsiMessage(PostfachNachrichtTestFactory.create());
+
+					assertThat(message.getPostfachId()).isEqualTo(PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE);
+				}
+			}
+
+			@DisplayName("by postfachId if postfachAddress not exists")
+			@Nested
+			class TestWithoutPostfachAddress {
+
+				@Test
+				void shouldMapPostfachAddressToPostfachId() {
+					var message = toOsiMessage(PostfachNachrichtTestFactory.createBuilder().postfachAddress(null).build());
+
+					assertThat(message.getPostfachId()).isEqualTo(MessageTestFactory.POSTFACH_ID);
+				}
+			}
+		}
+
+		private Message toOsiMessage(PostfachNachricht postfachNachricht) {
+			return mapper.toOsiMessage(postfachNachricht);
+		}
+	}
+
+	@DisplayName("To HTML body")
+	@Nested
+	class TestToHTMLBody {
+
+		@Test
+		void shouldNotContainNewlines() {
+			var body = mapper.replaceNewlines(MessageTestFactory.MAIL_BODY);
+
+			assertThat(body).doesNotContain("\n");
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachServiceTest.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteServiceTest.java
similarity index 65%
rename from mail-service/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachServiceTest.java
rename to nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteServiceTest.java
index 7d82d4f554e79aa9663788c0f16d387ce1f39194..d0a26660e41653608fc51a15cf574b3c55e81e7d 100644
--- a/mail-service/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachServiceTest.java
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,70 +21,57 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
-import static de.itvsh.ozg.mail.postfach.MessageTestFactory.*;
+import static de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
 import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
 import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
 
-import java.util.List;
+import java.util.stream.Collectors;
 
 import org.assertj.core.api.InstanceOfAssertFactories;
+import org.assertj.core.util.Arrays;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
-import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.test.util.ReflectionTestUtils;
 import org.springframework.test.web.client.ExpectedCount;
 import org.springframework.test.web.client.MockRestServiceServer;
 import org.springframework.test.web.client.ResponseActions;
 import org.springframework.web.client.RestTemplate;
 
-class OsiPostfachServiceTest {
+import de.ozgcloud.nachrichten.postfach.NotConfiguredException;
+import de.ozgcloud.nachrichten.postfach.PostfachBadRequestException;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
 
-	public static final String HEADER_API_KEY = "apikey";
-	public static final String HEADER_API_REALM = "realm";
+class OsiPostfachRemoteServiceTest {
 
 	private static final String TEST_URL = "https://testUrl.local";
 	private static final String TEST_API_KEY = "dummyApiKey";
 	private static final String TEST_API_REALM = "dummyApiRealm";
 
-	private static final String REPLY_JSON_TMPL = """
-						[{
-			  "messageId": "%s",
-			  "nameIdentifier": "%s",
-			  "body": "%s",
-			  "isHtml": false,
-			  "replyAction": %d,
-			  "subject": "%s",
-			  "sequenceNumber": "%s",
-			  "eidasLevel": 1,
-			  "isObligatory": true,
-			  "attachments": [{
-			  	"fileName": "%s",
-			  	"content": "%s"
-			  }]
-			}]""";
-
 	@InjectMocks
-	private OsiPostfachService service;
+	private OsiPostfachRemoteService service;
 
 	@Mock
-	private AttachmentService attachmentService;
+	private OsiPostfachMessageMapper mapper;
 
 	@Spy
 	private RestTemplate restTemplate;
+
 	@Spy
 	private OsiPostfachProperties properties = new OsiPostfachProperties();
 	{
@@ -117,9 +104,11 @@ class OsiPostfachServiceTest {
 
 		@Test
 		void shouldFillMessage() {
+			when(mapper.toPostfachNachricht(any())).thenReturn(PostfachNachrichtTestFactory.create());
+
 			var messages = service.getAllMessages();
 
-			assertThat(messages).hasSize(1).first().usingRecursiveComparison().isEqualTo(MessageTestFactory.create());
+			assertThat(messages).hasSize(1).first().usingRecursiveComparison().isEqualTo(PostfachNachrichtTestFactory.create());
 		}
 
 		@Test
@@ -131,16 +120,31 @@ class OsiPostfachServiceTest {
 
 		@Test
 		void shouldHaveAttachment() {
-			var messages = service.getAllMessages();
+			var messages = Arrays.array(MessageTestFactory.create());
+			doReturn(ResponseEntity.ok().body(messages)).when(restTemplate).exchange(TEST_URL, HttpMethod.GET, null, Message[].class);
+			when(mapper.toPostfachNachricht(messages[0])).thenReturn(PostfachNachrichtTestFactory.create());
+
+			var postfachNachrichten = service.getAllMessages();
 
-			assertThat(messages).hasSize(1).first().extracting(Message::getAttachments, InstanceOfAssertFactories.LIST).hasSize(1)
-					.usingRecursiveComparison().isEqualTo(List.of(MessageAttachmentTestFactory.create()));
+			assertThat(postfachNachrichten).hasSize(1).first()
+					.extracting(PostfachNachricht::getAttachments, InstanceOfAssertFactories.LIST)
+					.hasSize(1)
+					.usingRecursiveComparison().isEqualTo(PostfachNachrichtTestFactory.ATTACHMENTS);
+		}
+
+		@Test
+		void shouldCallMapper() {
+			prepareMockServer();
+
+			service.getAllMessages().collect(Collectors.toList());
+
+			verify(mapper).toPostfachNachricht(any());
 		}
 
 		private void prepareMockServer() {
 			mockServer.expect(ExpectedCount.once(), requestTo(TEST_URL))
 					.andExpect(method(HttpMethod.GET))
-					.andRespond(withSuccess(buildReplyJson(), MediaType.APPLICATION_JSON));
+					.andRespond(withSuccess(MessageJsonReplyTestFactory.buildReplyJson(), MediaType.APPLICATION_JSON));
 		}
 
 	}
@@ -148,10 +152,7 @@ class OsiPostfachServiceTest {
 	@Nested
 	class TestSendMessage {
 
-		@Captor
-		private ArgumentCaptor<HttpEntity<Message>> httpEntityCaptor;
-
-		private Message message = MessageTestFactory.create();
+		private PostfachNachricht message = PostfachNachrichtTestFactory.create();
 
 		@Test
 		void shouldCallRestTemplateExchange() {
@@ -191,7 +192,16 @@ class OsiPostfachServiceTest {
 		void shouldThrowBadRequestExceptionOnHttpClientError() {
 			prepareMockServer().andRespond(withStatus(HttpStatus.BAD_REQUEST));
 
-			assertThrows(OsiPostfachBadRequestException.class, () -> service.sendMessage(message));
+			assertThrows(PostfachBadRequestException.class, () -> service.sendMessage(message));
+		}
+
+		@Test
+		void shouldCallMapper() {
+			prepareMockServer();
+
+			service.sendMessage(message);
+
+			verify(mapper).toOsiMessage(any());
 		}
 
 		@Nested
@@ -219,37 +229,52 @@ class OsiPostfachServiceTest {
 
 			@Test
 			void shouldHaveVorgangIdAsSequenceNumber() {
+				var postfachNachricht = PostfachNachrichtTestFactory.create();
+				when(mapper.toOsiMessage(postfachNachricht)).thenReturn(MessageTestFactory.create());
+
 				prepareMockServer().andExpect(jsonPath("$.sequenceNumber").value(VORGANG_ID));
 
-				service.sendMessage(MessageTestFactory.create());
+				service.sendMessage(postfachNachricht);
 			}
 
 			@Test
 			void shouldHavePostfachIdAsNameIdentifier() {
+				var postfachNachricht = PostfachNachrichtTestFactory.create();
+				when(mapper.toOsiMessage(postfachNachricht)).thenReturn(MessageTestFactory.create());
+
 				prepareMockServer().andExpect(jsonPath("$.nameIdentifier").value(POSTFACH_ID));
 
-				service.sendMessage(MessageTestFactory.create());
+				service.sendMessage(postfachNachricht);
 			}
 
 			@Test
 			void shouldHaveSubject() {
+				var postfachNachricht = PostfachNachrichtTestFactory.create();
+				when(mapper.toOsiMessage(postfachNachricht)).thenReturn(MessageTestFactory.create());
+
 				prepareMockServer().andExpect(jsonPath("$.subject").value(SUBJECT));
 
-				service.sendMessage(MessageTestFactory.create());
+				service.sendMessage(postfachNachricht);
 			}
 
 			@Test
 			void shouldHaveMailBodyAsBody() {
+				var postfachNachricht = PostfachNachrichtTestFactory.create();
+				when(mapper.toOsiMessage(postfachNachricht)).thenReturn(MessageTestFactory.create());
+
 				prepareMockServer().andExpect(jsonPath("$.body").value(MAIL_BODY));
 
-				service.sendMessage(MessageTestFactory.create());
+				service.sendMessage(postfachNachricht);
 			}
 
 			@Test
 			void shouldHaveNumericReplyOptionAsReplyAction() {
+				var postfachNachricht = PostfachNachrichtTestFactory.create();
+				when(mapper.toOsiMessage(postfachNachricht)).thenReturn(MessageTestFactory.create());
+
 				prepareMockServer().andExpect(jsonPath("$.replyAction").value(REPLY_OPTION.toValue()));
 
-				service.sendMessage(MessageTestFactory.create());
+				service.sendMessage(postfachNachricht);
 			}
 		}
 
@@ -292,19 +317,21 @@ class OsiPostfachServiceTest {
 		}
 	}
 
-	static String buildReplyJson() {
-		return buildReplyJson(MessageTestFactory.create(), MessageAttachmentTestFactory.create());
-	}
+	@Nested
+	class TestGetPostfach {
+
+		@Test
+		void shouldHasTyp() {
+			var postfachType = service.getPostfachType();
+
+			assertThat(postfachType).isEqualTo(OsiPostfachRemoteService.POSTFACH_TYPE);
+		}
+
+		@Test
+		void shouldAllowReplys(){
+			var isReplyAllowed = service.isReplyAllowed();
 
-	static String buildReplyJson(Message msg, MessageAttachment attachement) {
-		return String.format(REPLY_JSON_TMPL,
-				msg.getMessageId(),
-				msg.getPostfachId(),
-				msg.getMailBody(),
-				msg.getReplyOption().toValue(),
-				msg.getSubject(),
-				msg.getVorgangId(),
-				attachement.getFileName(),
-				attachement.getContent());
+			assertThat(isReplyAllowed).isTrue();
+		}
 	}
 }
\ No newline at end of file
diff --git a/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachServerProcessExceptionTestFactory.java b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachServerProcessExceptionTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..94411f5e5e6dc22618c6097f8fe268e07f175491
--- /dev/null
+++ b/nachrichten-manager/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachServerProcessExceptionTestFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.osi;
+
+public class OsiPostfachServerProcessExceptionTestFactory {
+
+	public static OsiPostfachServerProcessException create() {
+		return new OsiPostfachServerProcessException();
+	}
+
+}
diff --git a/nachrichten-manager/src/test/resources/BspQuittung.xml b/nachrichten-manager/src/test/resources/BspQuittung.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5ef6f03ba16cb71ca6fc4ad8aac9e2c8e5847c21
--- /dev/null
+++ b/nachrichten-manager/src/test/resources/BspQuittung.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<ns2:BspQuittung
+	xmlns:ns2="http://www.akdb.de/egov/bsp/nachrichten"
+	xmlns:ns3="urn:akdb:bsp:postkorb:komm:webservice">
+	<ns2:AnnahmeErfolgreich>true</ns2:AnnahmeErfolgreich>
+</ns2:BspQuittung>
diff --git a/nachrichten-manager/src/test/resources/BspQuittungError.xml b/nachrichten-manager/src/test/resources/BspQuittungError.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e54e673e0523cc2d18e38ff90e6778d71740ceaa
--- /dev/null
+++ b/nachrichten-manager/src/test/resources/BspQuittungError.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<ns2:BspQuittung
+	xmlns:ns2="http://www.akdb.de/egov/bsp/nachrichten"
+	xmlns:ns3="urn:akdb:bsp:postkorb:komm:webservice">
+	<ns2:AnnahmeErfolgreich>false</ns2:AnnahmeErfolgreich>
+	<ns2:ErgebnisStatus>
+		<ns2:Tabelle>9006</ns2:Tabelle>
+		<ns2:Schluessel>1</ns2:Schluessel>
+	</ns2:ErgebnisStatus>
+	<ns2:ErgaenzendeHinweise>Test error</ns2:ErgaenzendeHinweise>
+</ns2:BspQuittung>
diff --git a/pluto-utils/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/nachrichten-manager/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
similarity index 100%
rename from pluto-utils/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
rename to nachrichten-manager/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
diff --git a/nachrichten-manager/src/test/resources/bayernid.p12 b/nachrichten-manager/src/test/resources/bayernid.p12
new file mode 100644
index 0000000000000000000000000000000000000000..fa82ce9007cc50831496073cdb03d8b6a92b5ee4
Binary files /dev/null and b/nachrichten-manager/src/test/resources/bayernid.p12 differ
diff --git a/pluto-utils/src/test/resources/junit-platform.properties b/nachrichten-manager/src/test/resources/junit-platform.properties
similarity index 100%
rename from pluto-utils/src/test/resources/junit-platform.properties
rename to nachrichten-manager/src/test/resources/junit-platform.properties
diff --git a/nachrichten-manager/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/nachrichten-manager/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000000000000000000000000000000000..ca6ee9cea8ec189a088d50559325d4e84ff8ad09
--- /dev/null
+++ b/nachrichten-manager/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline
\ No newline at end of file
diff --git a/notification-manager/lombok.config b/notification-manager/lombok.config
index e2cecc9355b20d3ec85afca7daa6c78e6b2082ee..81661f0fd9c5f6e2f40f39aa9ee13f7017fc2726 100644
--- a/notification-manager/lombok.config
+++ b/notification-manager/lombok.config
@@ -1,28 +1,30 @@
-#   Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
-#   Ministerpräsidenten des Landes Schleswig-Holstein
-#   Staatskanzlei
-#   Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 #
-#   Lizenziert unter der EUPL, Version 1.2 oder - sobald
-#   diese von der Europäischen Kommission genehmigt wurden -
-#   Folgeversionen der EUPL ("Lizenz");
-#   Sie dürfen dieses Werk ausschließlich gemäß
-#   dieser Lizenz nutzen.
-#   Eine Kopie der Lizenz finden Sie hier:
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
 #
-#   https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
 #
-#   Sofern nicht durch anwendbare Rechtsvorschriften
-#   gefordert oder in schriftlicher Form vereinbart, wird
-#   die unter der Lizenz verbreitete Software "so wie sie
-#   ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-#   ausdrücklich oder stillschweigend - verbreitet.
-#   Die sprachspezifischen Genehmigungen und Beschränkungen
-#   unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 lombok.log.fieldName=LOG
 lombok.log.slf4j.flagUsage = ERROR
 lombok.log.log4j.flagUsage = ERROR
 lombok.data.flagUsage = ERROR
 lombok.nonNull.exceptionType = IllegalArgumentException
-lombok.addLombokGeneratedAnnotation = true
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
diff --git a/notification-manager/pom.xml b/notification-manager/pom.xml
index 3584bdc1c584f9c33eba34a5c1ecdb06b043fc81..f83ba66250f3ac4e3d9f1056d194def074b8e1e5 100644
--- a/notification-manager/pom.xml
+++ b/notification-manager/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -24,38 +24,44 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
-		<groupId>de.itvsh.kop.common</groupId>
-		<artifactId>kop-common-parent</artifactId>
-		<version>1.2.1</version>
-		<relativePath />
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-parent</artifactId>
+		<version>3.0.1</version>
+		<relativePath/>
 	</parent>
 
-	<groupId>de.itvsh.kop.notification</groupId>
+	<groupId>de.ozgcloud.notification</groupId>
 	<artifactId>notification-manager</artifactId>
-	<name>KOP Notification Manager</name>
-	<version>1.0.0</version>
+	<version>2.4.0</version>
+	<name>OZG-Cloud Notification Manager</name>
 
 	<properties>
-		<user-manager-interface.version>1.0.0</user-manager-interface.version>
+		<user-manager-interface.version>2.1.0</user-manager-interface.version>
+		<ozgcloud.license.version>1.6.0</ozgcloud.license.version>
 	</properties>
 
 	<dependencies>
 		<dependency>
-			<groupId>de.itvsh.ozg.pluto</groupId>
-			<artifactId>pluto-interface</artifactId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-interface</artifactId>
 			<version>${project.version}</version>
 		</dependency>
 		<dependency>
-			<groupId>de.itvsh.ozg.pluto</groupId>
-			<artifactId>pluto-utils</artifactId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-utils</artifactId>
 			<version>${project.version}</version>
 		</dependency>
 		<dependency>
-			<groupId>de.itvsh.kop.user</groupId>
+			<groupId>de.ozgcloud.command</groupId>
+			<artifactId>command-manager</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		
+		<dependency>
+			<groupId>de.ozgcloud.user</groupId>
 			<artifactId>user-manager-interface</artifactId>
 			<version>${user-manager-interface.version}</version>
 			<exclusions>
@@ -99,8 +105,8 @@
 
 		<!-- Test -->
 		<dependency>
-			<groupId>de.itvsh.ozg.pluto</groupId>
-			<artifactId>pluto-utils</artifactId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-utils</artifactId>
 			<version>${project.version}</version>
 			<type>test-jar</type>
 			<scope>test</scope>
@@ -121,6 +127,33 @@
 				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-surefire-plugin</artifactId>
 			</plugin>
+
+			<plugin>
+				<groupId>com.mycila</groupId>
+				<artifactId>license-maven-plugin</artifactId>
+				<configuration>
+					<mapping>
+						<config>SCRIPT_STYLE</config>
+					</mapping>
+					<licenseSets>
+						<licenseSet>
+							<header>license/eupl_v1_2_de/header.txt</header>
+							<excludes>
+								<exclude>**/README</exclude>
+								<exclude>src/test/resources/**</exclude>
+								<exclude>src/main/resources/**</exclude>
+							</excludes>
+						</licenseSet>
+					</licenseSets>
+				</configuration>
+				<dependencies>
+					<dependency>
+						<groupId>de.ozgcloud.common</groupId>
+						<artifactId>ozgcloud-common-license</artifactId>
+						<version>${ozgcloud.license.version}</version>
+					</dependency>
+				</dependencies>
+			</plugin>
 		</plugins>
 	</build>
-</project>
\ No newline at end of file
+</project>
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationEventListener.java b/notification-manager/src/main/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationEventListener.java
deleted file mode 100644
index ae86bb4e8755ea6b7bc519aeb41094e54dc7e58d..0000000000000000000000000000000000000000
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationEventListener.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.kop.notification.antragsteller;
-
-import java.util.function.Predicate;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Component;
-
-import de.itvsh.kop.notification.vorgang.Vorgang;
-import de.itvsh.kop.notification.vorgang.VorgangId;
-import de.itvsh.kop.notification.vorgang.VorgangService;
-import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
-
-@Component
-public class AntragstellerNotificationEventListener {
-
-	static final String FS_FORMENGINE_NAME = "FormSolutions";
-	private static final Predicate<Vorgang> SHOULD_SEND_NOTIFICATION = vorgang -> StringUtils.isNoneBlank(vorgang.getPostfachId())
-			&& StringUtils.equals(vorgang.getFormEngineName(), FS_FORMENGINE_NAME);
-
-	@Autowired
-	private AntragstellerNotificationService service;
-	@Autowired
-	private VorgangService vorgangService;
-
-	@EventListener
-	public void onVorgangCreated(VorgangCreatedEvent event) {
-		var vorgang = vorgangService.getVorgang(VorgangId.from(event.getSource()));
-
-		sendIfRequired(vorgang);
-	}
-
-	private void sendIfRequired(Vorgang vorgang) {
-		if (SHOULD_SEND_NOTIFICATION.test(vorgang)) {
-			service.sendNotification(vorgang);
-		}
-	}
-}
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/NotificationManagerCallContextAttachingInterceptor.java b/notification-manager/src/main/java/de/ozgcloud/notification/NotificationManagerCallContextAttachingInterceptor.java
similarity index 90%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/NotificationManagerCallContextAttachingInterceptor.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/NotificationManagerCallContextAttachingInterceptor.java
index a2148826cd87ac0ebd38655448b7fb2b99ec0692..0bdfa2d0f581f00ad62096e764f8e86e22dde329 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/NotificationManagerCallContextAttachingInterceptor.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/NotificationManagerCallContextAttachingInterceptor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification;
+package de.ozgcloud.notification;
+
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
 
 import java.util.UUID;
 
@@ -31,7 +33,6 @@ import io.grpc.ClientCall;
 import io.grpc.ClientInterceptor;
 import io.grpc.ForwardingClientCall.SimpleForwardingClientCall;
 import io.grpc.Metadata;
-import io.grpc.Metadata.Key;
 import io.grpc.MethodDescriptor;
 
 public class NotificationManagerCallContextAttachingInterceptor implements ClientInterceptor {
@@ -40,7 +41,7 @@ public class NotificationManagerCallContextAttachingInterceptor implements Clien
 	static final String KEY_CLIENT_NAME = "CLIENT_NAME-bin";
 	static final String KEY_REQUEST_ID = "REQUEST_ID-bin";
 
-	public static final String NOTIFICATION_MANAGER_CLIENT_NAME = "KopNotificationManager";
+	public static final String NOTIFICATION_MANAGER_CLIENT_NAME = "OzgCloud_NotificationManager";
 	static final String NOTIFICATION_MANAGER_SENDER_USER_ID = "system-notification_manager-new_vorgang";
 
 	// <A> = Request, <B> = Response
@@ -78,9 +79,4 @@ public class NotificationManagerCallContextAttachingInterceptor implements Clien
 
 	}
 
-	// TODO move to common grpc utils
-	public static Key<byte[]> createKeyOf(String key) {
-		return Key.of(key, Metadata.BINARY_BYTE_MARSHALLER);
-	}
-
 }
diff --git a/notification-manager/src/main/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationEventListener.java b/notification-manager/src/main/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationEventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..7ef8213e2a6701fc37f4e798e945c74b0b04ede8
--- /dev/null
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationEventListener.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.antragsteller;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.notification.postfach.PostfachService;
+import de.ozgcloud.notification.vorgang.Vorgang;
+import de.ozgcloud.notification.vorgang.VorgangId;
+import de.ozgcloud.notification.vorgang.VorgangService;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Log4j2
+public class AntragstellerNotificationEventListener {
+
+	static final String FS_FORMENGINE_NAME = "FormSolutions";
+	static final String POSTFACH_NOT_CONFIGURED_MESSAGE = "Postfach is not configured. Antragsteller notifications will not be sent.";
+	private static final Predicate<Vorgang> EXISTS_POSTFACH_ID = vorgang -> StringUtils.isNoneBlank(vorgang.getPostfachId());
+	private static final Predicate<Vorgang> EXISTS_POSTFACH_ADDRESS = vorgang -> Objects.nonNull(vorgang.getPostfachAddress());
+	private static final Predicate<Vorgang> IS_FORMSOLUTIONS_FORM_ENGINE = vorgang -> StringUtils.equals(vorgang.getFormEngineName(),
+			FS_FORMENGINE_NAME);
+	private static final Predicate<Vorgang> SHOULD_SEND_NOTIFICATION = vorgang -> //
+			(EXISTS_POSTFACH_ID.test(vorgang) || EXISTS_POSTFACH_ADDRESS.test(vorgang)) && IS_FORMSOLUTIONS_FORM_ENGINE.test(vorgang);
+
+	@Autowired
+	private AntragstellerNotificationService service;
+	@Autowired
+	private VorgangService vorgangService;
+	@Autowired
+	private PostfachService postfachService;
+
+	private Optional<Boolean> isPostfachConfigured = Optional.empty();
+
+	@EventListener
+	public void onVorgangCreated(VorgangCreatedEvent event) {
+		if (isPostfachConfigured()) {
+			sendIfRequired(vorgangService.getVorgang(VorgangId.from(event.getSource())));
+		} else {
+			LOG.debug(POSTFACH_NOT_CONFIGURED_MESSAGE);
+		}
+	}
+
+	boolean isPostfachConfigured() {
+		return isPostfachConfigured.orElseGet(this::fetchIsPostfachConfigured);
+	}
+
+	synchronized boolean fetchIsPostfachConfigured() {
+		return isPostfachConfigured.orElseGet(() -> {
+			var isConfigured = postfachService.isPostfachConfigured();
+			if (!isConfigured) {
+				LOG.warn(POSTFACH_NOT_CONFIGURED_MESSAGE);
+			}
+			isPostfachConfigured = Optional.of(isConfigured);
+			return isConfigured;
+		});
+	}
+
+	private void sendIfRequired(Vorgang vorgang) {
+		if (SHOULD_SEND_NOTIFICATION.test(vorgang)) {
+			service.sendNotification(vorgang);
+		}
+	}
+}
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationService.java b/notification-manager/src/main/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationService.java
similarity index 87%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationService.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationService.java
index 82004c8373cf4b6cb19df3c247174829421298aa..8f6bbb460f938a64cd5e80c9f18063416feadc43 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationService.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.antragsteller;
+package de.ozgcloud.notification.antragsteller;
 
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
@@ -33,10 +33,10 @@ import org.apache.commons.io.IOUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.kop.notification.command.CommandService;
-import de.itvsh.kop.notification.postfach.PostfachNachricht;
-import de.itvsh.kop.notification.vorgang.Vorgang;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.notification.command.CommandService;
+import de.ozgcloud.notification.postfach.PostfachNachricht;
+import de.ozgcloud.notification.vorgang.Vorgang;
 
 @Service
 class AntragstellerNotificationService {
@@ -58,6 +58,7 @@ class AntragstellerNotificationService {
 		return PostfachNachricht.builder()
 				.vorgangId(vorgang.getId())
 				.postfachId(vorgang.getPostfachId())
+				.postfachAddress(vorgang.getPostfachAddress())
 				.mailBody(formatMessage(vorgang))
 				.subject(formatSubject(vorgang))
 				.build();
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/command/Command.java b/notification-manager/src/main/java/de/ozgcloud/notification/command/Command.java
similarity index 88%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/command/Command.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/command/Command.java
index a72e987eccac9ce9ca53610b386ee189fd8ac3aa..502bd85910b9c5d4536ac1251dde47a7ea1148cc 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/command/Command.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/command/Command.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
 import java.util.Map;
 
-import de.itvsh.kop.notification.vorgang.VorgangId;
+import de.ozgcloud.notification.vorgang.VorgangId;
 import lombok.Builder;
 import lombok.Getter;
 
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandBody.java b/notification-manager/src/main/java/de/ozgcloud/notification/command/CommandBody.java
similarity index 89%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandBody.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/command/CommandBody.java
index e4df3750bdceb7b885ad0f6c90b623a85fba1b3d..45446d171759dccf82d86456d4869e1ae2da4a7f 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandBody.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/command/CommandBody.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
 public interface CommandBody {
 
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandMapper.java b/notification-manager/src/main/java/de/ozgcloud/notification/command/CommandMapper.java
similarity index 83%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandMapper.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/command/CommandMapper.java
index 558c91252b72bd06691b4a08aa55885696b78ff0..935f7102f04f3d6b0cff0098275170ce58438f15 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandMapper.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/command/CommandMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
+
+import java.util.Optional;
 
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.notification.vorgang.VorgangId;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
 
 @Mapper(uses = GrpcObjectMapper.class)
 interface CommandMapper {
@@ -58,10 +61,9 @@ interface CommandMapper {
 	@Mapping(target = "orderString", source = "order")
 	GrpcCreateCommandRequest toGrpcRequest(Command command);
 
-	default String toString(de.itvsh.kop.notification.vorgang.VorgangId vorgangId) {
-		if (vorgangId == null) {
-			return null;
-		}
-		return vorgangId.toString();
+	default String toString(VorgangId vorgangId) {
+		return Optional.ofNullable(vorgangId)
+				.map(VorgangId::toString)
+				.orElse(null);
 	}
 }
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandRemoteService.java b/notification-manager/src/main/java/de/ozgcloud/notification/command/CommandRemoteService.java
similarity index 83%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandRemoteService.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/command/CommandRemoteService.java
index 47831f9ab41a5fefa9f2b53469795d7b95f79032..43288eef9d97788522eb2d0fba41c7a30706a62b 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandRemoteService.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/command/CommandRemoteService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.kop.notification.NotificationManagerCallContextAttachingInterceptor;
-import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
+import de.ozgcloud.vorgang.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
+import de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @Service
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandService.java b/notification-manager/src/main/java/de/ozgcloud/notification/command/CommandService.java
similarity index 57%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandService.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/command/CommandService.java
index f0658575e9de19d72ff26931cc993e600819351a..e7541a0f5f611bbc4ab9cbbb637000fb045c1b28 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/command/CommandService.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/command/CommandService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,24 +21,31 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.function.Predicate;
 
 import org.apache.commons.beanutils.BeanMap;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.kop.notification.command.Command.CommandOrder;
-import de.itvsh.kop.notification.postfach.PostfachNachricht;
+import de.ozgcloud.notification.command.Command.CommandOrder;
+import de.ozgcloud.notification.postfach.PostfachAddress;
+import de.ozgcloud.notification.postfach.PostfachAddressIdentifier;
+import de.ozgcloud.notification.postfach.PostfachNachricht;
+import de.ozgcloud.notification.postfach.StringBasedIdentifier;
 
 @Service("notificationCommandService")
 public class CommandService {
 
+	private static final Predicate<Entry<Object, Object>> IS_NOT_CLASS_KEY = entry -> !StringUtils.equals(entry.getKey().toString(), "class");
+
 	@Autowired
 	private CommandRemoteService commandRemoteService;
 
@@ -60,9 +67,26 @@ public class CommandService {
 
 		new BeanMap(nachricht).entrySet().stream()
 				.filter(entry -> Objects.nonNull(entry.getValue()))
-				.filter(entry -> !StringUtils.equals(entry.getKey().toString(), "class"))
-				.forEach(entry -> result.put(entry.getKey().toString(), entry.getValue()));
+				.filter(IS_NOT_CLASS_KEY)
+				.forEach(entry -> result.put(entry.getKey().toString(), getValue(entry.getValue())));
 
 		return Collections.unmodifiableMap(result);
 	}
-}
+	
+	private Object getValue(Object value) {
+		if (value instanceof PostfachAddress postfachAddress) {
+			return buildPostfachAddressMap(postfachAddress);
+		}
+		return value;
+	}
+	
+	private Map<String, Object> buildPostfachAddressMap(PostfachAddress postfachAddress){
+		 return Map.of(PostfachAddress.TYPE_FIELD, postfachAddress.getType(),
+				 			PostfachAddress.VERSION_FIELD, postfachAddress.getVersion(), 
+				 			PostfachAddress.IDENTIFIER_FIELD, buildPostfachAddressIdentifierMap(postfachAddress.getIdentifier()));
+	}
+	
+	private Map<String, Object> buildPostfachAddressIdentifierMap(PostfachAddressIdentifier identifier){
+		 return Map.of(StringBasedIdentifier.POSTFACH_ID_FIELD, ((StringBasedIdentifier) identifier).getPostfachId());
+	}
+}
\ No newline at end of file
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/email/EmailRecipientMapper.java b/notification-manager/src/main/java/de/ozgcloud/notification/email/EmailRecipientMapper.java
similarity index 83%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/email/EmailRecipientMapper.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/email/EmailRecipientMapper.java
index bbb8b70965a1af6ddc81c4a887c8bafd4f53c77f..5ed80350b5fca8184f808f3da4981f678c4dffea 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/email/EmailRecipientMapper.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/email/EmailRecipientMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.email;
+package de.ozgcloud.notification.email;
+
+import de.ozgcloud.nachrichten.email.GrpcRecipient;
+import de.ozgcloud.notification.user.Recipient;
 
-import de.itvsh.kop.notification.user.Recipient;
-import de.itvsh.ozg.mail.email.GrpcRecipient;
 import org.mapstruct.Mapper;
 
 @Mapper
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/email/EmailRemoteService.java b/notification-manager/src/main/java/de/ozgcloud/notification/email/EmailRemoteService.java
similarity index 71%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/email/EmailRemoteService.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/email/EmailRemoteService.java
index 010c5c1eb5746003f686b65b64af32d1e58f1613..1044ac7d6b038ff71d2416406efa73fcd449cc20 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/email/EmailRemoteService.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/email/EmailRemoteService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,16 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.email;
+package de.ozgcloud.notification.email;
+
+import java.util.List;
 
-import de.itvsh.ozg.mail.email.EmailServiceGrpc.EmailServiceBlockingStub;
-import de.itvsh.ozg.mail.email.GrpcRecipient;
-import de.itvsh.ozg.mail.email.GrpcSendEmailRequest;
-import net.devh.boot.grpc.client.inject.GrpcClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.List;
+import de.ozgcloud.nachrichten.email.EmailServiceGrpc.EmailServiceBlockingStub;
+import de.ozgcloud.nachrichten.email.GrpcRecipient;
+import de.ozgcloud.nachrichten.email.GrpcSendEmailRequest;
+import de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor;
+import lombok.NonNull;
+import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @Service
 public class EmailRemoteService {
@@ -41,9 +44,10 @@ public class EmailRemoteService {
 	@Autowired
 	private EmailRecipientMapper recipientMapper;
 
-	public void sendEmail(UserEmail email) {
+	public void sendEmail(@NonNull UserEmail email) {
 		var grpcEmailRecipients = email.recipients().stream().map(recipientMapper::toGrpc).toList();
-		emailServiceStub.sendEmail(buildRequest(grpcEmailRecipients, email.subject(), email.body()));
+		emailServiceStub.withInterceptors(new NotificationManagerCallContextAttachingInterceptor())
+				.sendEmail(buildRequest(grpcEmailRecipients, email.subject(), email.body()));
 	}
 
 	private GrpcSendEmailRequest buildRequest(List<GrpcRecipient> grpcRecipients, String subject, String body) {
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/email/UserEmail.java b/notification-manager/src/main/java/de/ozgcloud/notification/email/UserEmail.java
similarity index 87%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/email/UserEmail.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/email/UserEmail.java
index 4d37fbd94077f6234b64065db9cb098289a40b4e..302016dd719ec62d1571b738e679fdb425338375 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/email/UserEmail.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/email/UserEmail.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.email;
+package de.ozgcloud.notification.email;
 
-import de.itvsh.kop.notification.user.Recipient;
+import de.ozgcloud.notification.user.Recipient;
 import lombok.Builder;
 import lombok.Singular;
 
diff --git a/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachAddress.java b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachAddress.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fa6538753a178d31cd64a3272d573b72e650caa
--- /dev/null
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachAddress.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+public class PostfachAddress {
+
+	public static final String VERSION_FIELD = "version";
+	public static final String TYPE_FIELD = "type";
+	public static final String IDENTIFIER_FIELD = "identifier";
+
+	private String version;
+	private int type;
+	private PostfachAddressIdentifier identifier;
+}
\ No newline at end of file
diff --git a/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachAddressIdentifier.java b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachAddressIdentifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce49e9f021bb2df6679baa9430bf918384a4eb55
--- /dev/null
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachAddressIdentifier.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+public interface PostfachAddressIdentifier {
+
+}
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/postfach/PostfachNachricht.java b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachNachricht.java
similarity index 82%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/postfach/PostfachNachricht.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachNachricht.java
index eba61293acfc0d78acdd21dd626859f05a743425..b72d7bb0d196ce413c072b06cdbb961f5415c4df 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/postfach/PostfachNachricht.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachNachricht.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.postfach;
+package de.ozgcloud.notification.postfach;
 
-import de.itvsh.kop.notification.command.CommandBody;
-import de.itvsh.kop.notification.vorgang.VorgangId;
+import de.ozgcloud.notification.command.CommandBody;
+import de.ozgcloud.notification.vorgang.VorgangId;
 import lombok.Builder;
 import lombok.Getter;
 
@@ -34,6 +34,7 @@ public class PostfachNachricht implements CommandBody {
 
 	static final String FIELD_VORGANG_ID = "vorgangId";
 	static final String FIELD_POSTFACH_ID = "postfachId";
+	public static final String FIELD_POSTFACH_ADDRESS = "postfachAddress";
 	static final String FIELD_SUBJECT = "subject";
 	static final String FIELD_MESSAGE = "mailBody";
 
@@ -42,6 +43,7 @@ public class PostfachNachricht implements CommandBody {
 
 	private VorgangId vorgangId;
 	private String postfachId;
+	private PostfachAddress postfachAddress;
 
 	private String subject;
 	private String mailBody;
diff --git a/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachRemoteService.java b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..138735e107b6f19376de567983667c7689f0918b
--- /dev/null
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachRemoteService.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.nachrichten.postfach.GrpcIsPostfachConfiguredRequest;
+import de.ozgcloud.nachrichten.postfach.PostfachServiceGrpc.PostfachServiceBlockingStub;
+import de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Service
+class PostfachRemoteService {
+
+	@GrpcClient("pluto")
+	private PostfachServiceBlockingStub postfachServiceBlockingStub;
+
+	public boolean isPostfachConfigured() {
+		return getPostfachServiceStub().isPostfachConfigured(buildGrpcRequest()).getIsConfigured();
+	}
+
+	GrpcIsPostfachConfiguredRequest buildGrpcRequest() {
+		return GrpcIsPostfachConfiguredRequest.newBuilder().build();
+	}
+
+	PostfachServiceBlockingStub getPostfachServiceStub() {
+		return postfachServiceBlockingStub.withInterceptors(new NotificationManagerCallContextAttachingInterceptor());
+	}
+}
diff --git a/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachService.java b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachService.java
new file mode 100644
index 0000000000000000000000000000000000000000..08c6f8a0c73b74f4202aba489677b6adef6cb6b4
--- /dev/null
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/PostfachService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service("notificationPostfachService")
+public class PostfachService {
+
+	@Autowired
+	private PostfachRemoteService postfachRemoteService;
+
+	public boolean isPostfachConfigured() {
+		return postfachRemoteService.isPostfachConfigured();
+	}
+}
diff --git a/notification-manager/src/main/java/de/ozgcloud/notification/postfach/StringBasedIdentifier.java b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/StringBasedIdentifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f3df67481ec7f86d72c17dee7d16d751bb4ea6c
--- /dev/null
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/postfach/StringBasedIdentifier.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+public class StringBasedIdentifier implements PostfachAddressIdentifier {
+	
+	public static final String POSTFACH_ID_FIELD = "postfachId";
+
+	private String postfachId;
+
+}
\ No newline at end of file
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/user/Recipient.java b/notification-manager/src/main/java/de/ozgcloud/notification/user/Recipient.java
similarity index 90%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/user/Recipient.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/user/Recipient.java
index 9fd0df889db37c737cff5c0346a4eeeb4eada2b5..cacb5601803931145a3b6f79566590f80217cf2a 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/user/Recipient.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/user/Recipient.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
 import lombok.Builder;
 
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/user/UserNotificationEventListener.java b/notification-manager/src/main/java/de/ozgcloud/notification/user/UserNotificationEventListener.java
similarity index 71%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/user/UserNotificationEventListener.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/user/UserNotificationEventListener.java
index 4797dea5afcb9cb51a2be8af29c617ffdc5738dc..b0f7ac539e551acd758f74584d38eb3aa32936be 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/user/UserNotificationEventListener.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/user/UserNotificationEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,17 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
-
-import java.util.Objects;
+package de.ozgcloud.notification.user;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Component;
 
-import de.itvsh.kop.notification.vorgang.VorgangId;
-import de.itvsh.kop.notification.vorgang.VorgangService;
-import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.notification.vorgang.VorgangId;
+import de.ozgcloud.notification.vorgang.VorgangService;
 
 @Component
 public class UserNotificationEventListener {
@@ -44,10 +42,6 @@ public class UserNotificationEventListener {
 
 	@EventListener
 	public void onVorgangCreated(VorgangCreatedEvent event) {
-		var organisationsEinheitId = vorgangService.getVorgang(VorgangId.from(event.getSource())).getOrganisationseinheitenId();
-
-		if (Objects.nonNull(organisationsEinheitId)) {
-			userNotificationService.sendNotification(organisationsEinheitId);
-		}
+		userNotificationService.sendNotification(vorgangService.getVorgang(VorgangId.from(event.getSource())));
 	}
 }
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/user/UserNotificationService.java b/notification-manager/src/main/java/de/ozgcloud/notification/user/UserNotificationService.java
similarity index 62%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/user/UserNotificationService.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/user/UserNotificationService.java
index 5fa3983ea961980b0a10271c7c6f2bb1f0ff63b7..023c140d0071b886e5a9b95f4fb7578ad9515c07 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/user/UserNotificationService.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/user/UserNotificationService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
+
+import static java.util.Objects.*;
 
 import java.util.List;
 
@@ -29,14 +31,15 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.kop.notification.email.EmailRemoteService;
-import de.itvsh.kop.notification.email.UserEmail;
+import de.ozgcloud.notification.email.EmailRemoteService;
+import de.ozgcloud.notification.email.UserEmail;
+import de.ozgcloud.notification.vorgang.Vorgang;
 import lombok.NonNull;
 
 @Service
 public class UserNotificationService {
 
-	public static final String MAIL_SUBJECT = "Neuer Vorgang";
+	public static final String MAIL_SUBJECT_TEMPLATE = "Neuer Vorgang: %s";
 	public static final String MAIL_BODY = "Es ist ein neuer Vorgang im Allgemeinen Fachverfahren eingegangen.";
 
 	@Autowired
@@ -46,12 +49,14 @@ public class UserNotificationService {
 	private UserRemoteService userRemoteService;
 
 	@Async
-	public void sendNotification(@NonNull String organisationsEinheitId) {
-		var recipients = userRemoteService.getRecipients(organisationsEinheitId);
-		emailRemoteService.sendEmail(buildUserEmail(recipients));
+	public void sendNotification(@NonNull Vorgang vorgang) {
+		if (nonNull(vorgang.getOrganisationseinheitenId())) {
+			var recipients = userRemoteService.getRecipients(vorgang.getOrganisationseinheitenId());
+			emailRemoteService.sendEmail(buildUserEmail(recipients, MAIL_SUBJECT_TEMPLATE.formatted(vorgang.getVorgangName())));
+		}
 	}
 
-	private UserEmail buildUserEmail(List<Recipient> recipients) {
-		return UserEmail.builder().recipients(recipients).subject(MAIL_SUBJECT).body(MAIL_BODY).build();
+	UserEmail buildUserEmail(List<Recipient> recipients, String subject) {
+		return UserEmail.builder().recipients(recipients).subject(subject).body(MAIL_BODY).build();
 	}
 }
\ No newline at end of file
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/user/UserRecipientMapper.java b/notification-manager/src/main/java/de/ozgcloud/notification/user/UserRecipientMapper.java
similarity index 86%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/user/UserRecipientMapper.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/user/UserRecipientMapper.java
index f9dda8b66382f9a7943be97d50b698dcb3c95257..9587eb4104fdd9bcb6e8b07808f8d445ef7b32fd 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/user/UserRecipientMapper.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/user/UserRecipientMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
-import de.itvsh.kop.user.recipient.GrpcRecipient;
 import org.mapstruct.Mapper;
 
+import de.ozgcloud.user.recipient.GrpcRecipient;
+
 @Mapper
 interface UserRecipientMapper {
 
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/user/UserRemoteService.java b/notification-manager/src/main/java/de/ozgcloud/notification/user/UserRemoteService.java
similarity index 70%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/user/UserRemoteService.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/user/UserRemoteService.java
index 908f103c5765480a0db324fbf1bdcc881cb6feba..8123bc6aa4509026ec0ad74fd83a73407a6f9f7d 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/user/UserRemoteService.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/user/UserRemoteService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,27 +21,29 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
 import java.util.List;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.kop.user.grpc.recipient.GrpcFindRecipientRequest;
-import de.itvsh.kop.user.grpc.recipient.RecipientServiceGrpc;
+import de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor;
+import de.ozgcloud.user.grpc.recipient.GrpcFindRecipientRequest;
+import de.ozgcloud.user.grpc.recipient.RecipientServiceGrpc;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @Service
 public class UserRemoteService {
 
 	@GrpcClient("user-manager")
-	private RecipientServiceGrpc.RecipientServiceBlockingStub recipientService;
+	private RecipientServiceGrpc.RecipientServiceBlockingStub stub;
 	@Autowired
 	private UserRecipientMapper mapper;
 
 	public List<Recipient> getRecipients(String organisationseinheitId) {
 		var request = GrpcFindRecipientRequest.newBuilder().setOrganisationsEinheitId(organisationseinheitId).build();
-		return recipientService.findRecipientByOrganisationsEinheitId(request).getRecipientList().stream().map(mapper::fromGrpc).toList();
+		return stub.withInterceptors(new NotificationManagerCallContextAttachingInterceptor())
+				.findRecipientByOrganisationsEinheitId(request).getRecipientList().stream().map(mapper::fromGrpc).toList();
 	}
 }
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/Vorgang.java b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/Vorgang.java
similarity index 84%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/Vorgang.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/vorgang/Vorgang.java
index 90ad243bcd6ec051f56a3743922e45f533198066..879bd3eeca95cf9bd3d8ed0304ea8d39236f7c4c 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/Vorgang.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/Vorgang.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.notification.vorgang;
 
+import java.time.ZonedDateTime;
+
+import de.ozgcloud.notification.postfach.PostfachAddress;
 import lombok.Builder;
 import lombok.Getter;
 
-import java.time.ZonedDateTime;
-
 @Getter
-@Builder
+@Builder(toBuilder = true)
 public class Vorgang {
 
 	private VorgangId id;
@@ -42,4 +43,6 @@ public class Vorgang {
 	private String postfachId;
 	private String formEngineName;
 	private String organisationseinheitenId;
+
+	private PostfachAddress postfachAddress;
 }
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangId.java b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangId.java
similarity index 87%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangId.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangId.java
index caa49c9ebcbea553c384b064af40c6685cde42b9..c6594914633c445d08f26c0a4bbe0c411e8c6197 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangId.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangId.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.notification.vorgang;
 
-import de.itvsh.kop.common.datatype.StringBasedValue;
+import de.ozgcloud.common.datatype.StringBasedValue;
 import lombok.EqualsAndHashCode;
 
 @EqualsAndHashCode(callSuper = true)
diff --git a/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangMapper.java b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f138112777d85138fa7101e25919254c77330e4e
--- /dev/null
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangMapper.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.vorgang;
+
+import java.util.Optional;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.NullValueCheckStrategy;
+import org.mapstruct.NullValuePropertyMappingStrategy;
+
+import de.ozgcloud.notification.postfach.PostfachAddress;
+import de.ozgcloud.notification.postfach.PostfachAddressIdentifier;
+import de.ozgcloud.notification.postfach.StringBasedIdentifier;
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress;
+import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangHead;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangWithEingang;
+
+@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_NULL,
+		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
+interface VorgangMapper {
+
+	@Mapping(target = "postfachId", source = "eingang.antragsteller.postfachId")
+	@Mapping(target = "vorgangName", source = "name")
+	@Mapping(target = "vorgangNummer", source = "nummer")
+	@Mapping(target = "organisationseinheitenId", source = "eingang.zustaendigeStelle.organisationseinheitenId")
+	@Mapping(target = "postfachAddress", expression = "java(fromPostfachAddress(vorgang))")
+	Vorgang fromGrpc(GrpcVorgangWithEingang vorgang);
+	
+	default PostfachAddress fromPostfachAddress(GrpcVorgangWithEingang vorgang) {
+		return Optional.ofNullable(vorgang.getHeader())
+			.map(GrpcVorgangHead::getServiceKonto)
+			.map(GrpcServiceKonto::getPostfachAddressesList)
+			.filter(list -> !list.isEmpty())
+			.map(list -> list.get(0))
+			.map(this::buildPostfachAddress)
+			.orElse(null);
+	}
+	
+	private PostfachAddress buildPostfachAddress(GrpcPostfachAddress postfachAddress) {
+		return PostfachAddress.builder()
+				.type(postfachAddress.getType())
+				.version(postfachAddress.getVersion())
+				.identifier(buildIdentifier(postfachAddress.getIdentifier()))
+				.build();
+	}
+	
+	private PostfachAddressIdentifier buildIdentifier(GrpcObject identifier) {
+		var postfachId = identifier.getProperty(0).getValue(0);
+		return StringBasedIdentifier.builder().postfachId(postfachId).build();
+	}
+
+	default VorgangId fromString(String vorgangId) {
+		return Optional.ofNullable(vorgangId).map(VorgangId::from).orElse(null);
+	}
+}
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangRemoteService.java b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangRemoteService.java
similarity index 81%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangRemoteService.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangRemoteService.java
index 5822e8f63be48d1fd08d2941f52e2bc5c359016e..faee80477148a6c299690a5b399e48030d6118b6 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangRemoteService.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangRemoteService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,20 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.notification.vorgang;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.kop.notification.NotificationManagerCallContextAttachingInterceptor;
-import de.itvsh.ozg.pluto.vorgang.GrpcFindVorgangWithEingangRequest;
-import de.itvsh.ozg.pluto.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
+import de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @Service
 class VorgangRemoteService {
 
-	@GrpcClient("pluto")
+	@GrpcClient("vorgang-manager")
 	private VorgangServiceBlockingStub stub;
 
 	@Autowired
diff --git a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangService.java b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangService.java
similarity index 91%
rename from notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangService.java
rename to notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangService.java
index 03225a6927ef32c191a4b4a6d5d51f43ed2d974d..8b1d43ac0a79489add8a425962b13dbe33d85cfc 100644
--- a/notification-manager/src/main/java/de/itvsh/kop/notification/vorgang/VorgangService.java
+++ b/notification-manager/src/main/java/de/ozgcloud/notification/vorgang/VorgangService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.notification.vorgang;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
diff --git a/notification-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/notification-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000000000000000000000000000000000..08abec6c597ed602bc6a36d5de3111b9a0d66a74
--- /dev/null
+++ b/notification-manager/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,20 @@
+net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientMetricAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientHealthAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientSecurityAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientTraceAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcDiscoveryClientAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonTraceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcAdviceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcHealthServiceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataConsulConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataEurekaConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataNacosConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataZookeeperConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcReflectionServiceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerMetricAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerSecurityAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerTraceAutoConfiguration
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationEventListenerTest.java b/notification-manager/src/test/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationEventListenerTest.java
deleted file mode 100644
index bc377c0576b1b3327f3bdf03c6f37c9e77c2c8e4..0000000000000000000000000000000000000000
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationEventListenerTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.kop.notification.antragsteller;
-
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import de.itvsh.kop.notification.vorgang.Vorgang;
-import de.itvsh.kop.notification.vorgang.VorgangService;
-import de.itvsh.kop.notification.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
-
-class AntragstellerNotificationEventListenerTest {
-
-	@InjectMocks
-	private AntragstellerNotificationEventListener eventListener;
-
-	@Mock
-	private AntragstellerNotificationService service;
-	@Mock
-	private VorgangService vorgangService;
-
-	@Nested
-	class TestOnVorgangCreated {
-
-		private static final VorgangCreatedEvent EVENT = new VorgangCreatedEvent(VorgangTestFactory.ID.toString());
-		private static final Vorgang VORGANG = VorgangTestFactory.createBuilder()
-				.formEngineName(AntragstellerNotificationEventListener.FS_FORMENGINE_NAME).build();
-
-		@BeforeEach
-		void initMock() {
-			when(vorgangService.getVorgang(any())).thenReturn(VORGANG);
-		}
-
-		@Test
-		void shouldLoadVorgang() {
-			eventListener.onVorgangCreated(EVENT);
-
-			verify(vorgangService).getVorgang(VorgangTestFactory.ID);
-		}
-
-		@Test
-		void shouldCallService() {
-			eventListener.onVorgangCreated(EVENT);
-
-			verify(service).sendNotification(same(VORGANG));
-		}
-
-		@Test
-		void shouldNOTCallServiceOnMissingPostfach() {
-			when(vorgangService.getVorgang(any())).thenReturn(VorgangTestFactory.createBuilder().postfachId(null).build());
-
-			eventListener.onVorgangCreated(EVENT);
-
-			verify(service, never()).sendNotification(any());
-		}
-
-		@Test
-		void shouldOnlyCallServiceForFormSolutions() {
-			when(vorgangService.getVorgang(any())).thenReturn(VorgangTestFactory.createBuilder().formEngineName("other").build());
-
-			eventListener.onVorgangCreated(EVENT);
-
-			verify(service, never()).sendNotification(any());
-		}
-	}
-}
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/NotificationManagerCallContextAttachingInterceptorTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/NotificationManagerCallContextAttachingInterceptorTest.java
similarity index 92%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/NotificationManagerCallContextAttachingInterceptorTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/NotificationManagerCallContextAttachingInterceptorTest.java
index 8984cc70343723ff87045fb02039a2982240557f..bc97278ea9bb7ef30bd8b81e9fb094e6f16e23a7 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/NotificationManagerCallContextAttachingInterceptorTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/NotificationManagerCallContextAttachingInterceptorTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification;
+package de.ozgcloud.notification;
 
-import static de.itvsh.kop.notification.NotificationManagerCallContextAttachingInterceptor.*;
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
+import static de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationEventListenerTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationEventListenerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d8bd538aeb583929149b55ca1a70be191fa0920
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationEventListenerTest.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.antragsteller;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.stream.IntStream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.notification.postfach.PostfachService;
+import de.ozgcloud.notification.vorgang.Vorgang;
+import de.ozgcloud.notification.vorgang.VorgangService;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
+import lombok.SneakyThrows;
+
+class AntragstellerNotificationEventListenerTest {
+
+	@Spy
+	@InjectMocks
+	private AntragstellerNotificationEventListener eventListener;
+
+	@Mock
+	private AntragstellerNotificationService service;
+	@Mock
+	private VorgangService vorgangService;
+	@Mock
+	private PostfachService postfachService;
+
+	@DisplayName("On vorgang created")
+	@Nested
+	class TestOnVorgangCreated {
+
+		private static final VorgangCreatedEvent EVENT = new VorgangCreatedEvent(VorgangTestFactory.ID.toString());
+		private static final Vorgang VORGANG = VorgangTestFactory.createBuilder()
+				.formEngineName(AntragstellerNotificationEventListener.FS_FORMENGINE_NAME).build();
+
+		@Test
+		void shouldLoadVorgang() {
+			when(postfachService.isPostfachConfigured()).thenReturn(true);
+			when(vorgangService.getVorgang(any())).thenReturn(VORGANG);
+
+			onVorgangCreated();
+
+			verify(vorgangService).getVorgang(VorgangTestFactory.ID);
+		}
+
+		@DisplayName("should not send notification when postfach is not configured")
+		@Test
+		void shouldNotSend() {
+			when(postfachService.isPostfachConfigured()).thenReturn(false);
+
+			onVorgangCreated();
+
+			verify(vorgangService, never()).getVorgang(any());
+		}
+
+		@Nested
+		class TestIsPostfachConfigured {
+
+			@Test
+			void shouldCallFetchIsPostfachService() {
+				eventListener.isPostfachConfigured();
+
+				verify(eventListener).fetchIsPostfachConfigured();
+			}
+
+			@Test
+			void shouldNotCallFetchIsPostfachService() {
+				ReflectionTestUtils.setField(eventListener, "isPostfachConfigured", Optional.of(true));
+
+				eventListener.isPostfachConfigured();
+
+				verify(eventListener, never()).fetchIsPostfachConfigured();
+			}
+
+			@Test
+			void shouldReturnValue() {
+				when(postfachService.isPostfachConfigured()).thenReturn(true);
+
+				var isConfigured = eventListener.isPostfachConfigured();
+
+				assertThat(isConfigured).isTrue();
+			}
+
+		}
+
+		@Nested
+		class TestFetchIsPostfachConfigured {
+
+			@Test
+			void shouldCallRemoteService() {
+				eventListener.fetchIsPostfachConfigured();
+
+				verify(postfachService).isPostfachConfigured();
+			}
+
+			@Test
+			void shouldReturnValue() {
+				when(postfachService.isPostfachConfigured()).thenReturn(true);
+
+				var isConfigured = eventListener.fetchIsPostfachConfigured();
+
+				assertThat(isConfigured).isTrue();
+			}
+
+			@Test
+			void shouldCallIsPostfachConfiguredOnce() {
+				fetchIsPostfachConfigured();
+
+				verify(postfachService).isPostfachConfigured();
+			}
+
+			@SneakyThrows
+			private void fetchIsPostfachConfigured() {
+				var executorService = Executors.newFixedThreadPool(5);
+				var countDownLatch = new CountDownLatch(3);
+
+				IntStream.range(0, 3).forEach(i ->
+						executorService.submit(() -> {
+							eventListener.fetchIsPostfachConfigured();
+							countDownLatch.countDown();
+						})
+				);
+
+				countDownLatch.await();
+			}
+		}
+
+		@DisplayName("send if required")
+		@Nested
+		class TestSendIfRequirest {
+
+			@DisplayName("should not call service")
+			@Nested
+			class TestNotCallService {
+
+				@BeforeEach
+				void setup() {
+					when(postfachService.isPostfachConfigured()).thenReturn(true);
+				}
+
+				@Test
+				void onMissingPostfachIdAndPostfachAddress() {
+					when(vorgangService.getVorgang(any())).thenReturn(VORGANG.toBuilder().postfachId(null).postfachAddress(null).build());
+
+					onVorgangCreated();
+
+					verify(service, never()).sendNotification(any());
+				}
+
+				@Test
+				void forOtherThanFormSolutionsEngines() {
+					when(vorgangService.getVorgang(any())).thenReturn(VorgangTestFactory.createBuilder().formEngineName("other").build());
+
+					onVorgangCreated();
+
+					verify(service, never()).sendNotification(any());
+				}
+			}
+
+			@DisplayName("should call service")
+			@Nested
+			class TestCallService {
+
+				@BeforeEach
+				void setup() {
+					when(postfachService.isPostfachConfigured()).thenReturn(true);
+				}
+
+				@Test
+				void onExistingPostfachIdAndPostfachAddress() {
+					when(vorgangService.getVorgang(any())).thenReturn(VORGANG);
+
+					onVorgangCreated();
+
+					verify(service).sendNotification(same(VORGANG));
+				}
+
+				@Test
+				void onExistingPostfachIdAndMissingPostfachAddress() {
+					when(vorgangService.getVorgang(any())).thenReturn(VORGANG.toBuilder().postfachAddress(null).build());
+
+					onVorgangCreated();
+
+					verify(service).sendNotification(any());
+				}
+
+				@Test
+				void onMissingPostfachIdAndExistingPostfachAddress() {
+					when(vorgangService.getVorgang(any())).thenReturn(VORGANG.toBuilder().postfachId(null).build());
+
+					onVorgangCreated();
+
+					verify(service).sendNotification(any());
+				}
+			}
+		}
+
+		private void onVorgangCreated() {
+			eventListener.onVorgangCreated(EVENT);
+		}
+	}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationServiceTest.java
similarity index 82%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationServiceTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationServiceTest.java
index 122e14b2a98c45897440190b83dd410e20c97a44..6f12a55fe159fb0e90348285051e2d04ae299881 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/antragsteller/AntragstellerNotificationServiceTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/antragsteller/AntragstellerNotificationServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.antragsteller;
+package de.ozgcloud.notification.antragsteller;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.*;
 
 import java.time.ZonedDateTime;
 
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
@@ -37,10 +38,11 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.itvsh.kop.notification.command.CommandService;
-import de.itvsh.kop.notification.postfach.PostfachNachricht;
-import de.itvsh.kop.notification.postfach.PostfachNachrichtTestFactory;
-import de.itvsh.kop.notification.vorgang.VorgangTestFactory;
+import de.ozgcloud.notification.command.CommandService;
+import de.ozgcloud.notification.postfach.PostfachAddressTestFactory;
+import de.ozgcloud.notification.postfach.PostfachNachricht;
+import de.ozgcloud.notification.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
 
 class AntragstellerNotificationServiceTest {
 
@@ -53,6 +55,7 @@ class AntragstellerNotificationServiceTest {
 	@Captor
 	private ArgumentCaptor<PostfachNachricht> nachrichtCaptor;
 
+	@DisplayName("Send notification")
 	@Nested
 	class TestSendNotification {
 
@@ -96,6 +99,13 @@ class AntragstellerNotificationServiceTest {
 
 				assertThat(nachricht.getPostfachId()).isEqualTo(VorgangTestFactory.POSTFACH_ID);
 			}
+			
+			@Test
+			void shouldHavePostfachAddress() {
+				var nachricht = service.buildPostfachNachricht(VorgangTestFactory.create());
+
+				assertThat(nachricht.getPostfachAddress()).usingRecursiveComparison().isEqualTo(PostfachAddressTestFactory.create());
+			}
 		}
 
 		@Nested
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandMapperTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/command/CommandMapperTest.java
similarity index 70%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandMapperTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/command/CommandMapperTest.java
index d7c52cc0ce49ed4455654bf35d4d4cca2c78ac9f..d3e08ef7e6d7c5bb6a092ff0d81eb9f9c7e82f35 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandMapperTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/command/CommandMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,18 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
 import static org.assertj.core.api.Assertions.*;
 
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
-import de.itvsh.kop.notification.postfach.PostfachNachrichtTestFactory;
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.notification.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.notification.vorgang.VorgangId;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
 
 class CommandMapperTest {
 
@@ -41,8 +43,10 @@ class CommandMapperTest {
 	@Spy
 	private GrpcObjectMapper objectMapper = Mappers.getMapper(GrpcObjectMapper.class);
 
+	@DisplayName("To grpc")
 	@Nested
 	class TestToGrpc {
+		
 		@Test
 		void shouldMapPostfachNachrichtCommand() {
 			var mapped = mapper.toGrpcRequest(CommandTestFactory.createBuilder().body(PostfachNachrichtTestFactory.createAsMap()).build());
@@ -51,6 +55,24 @@ class CommandMapperTest {
 					.ignoringFields("bodyObj_", "memoizedHashCode")
 					.isEqualTo(GrpcCreateCommandRequestTestFactory.create());
 		}
+		
+		@DisplayName("to string")
+		@Nested
+		class TestToString {
+			
+			@Test
+			void shouldReturnValue() {
+				var vorgangId = mapper.toString(VorgangId.from("testId"));
+				
+				assertThat(vorgangId).isEqualTo("testId");
+			}
+			
+			@Test
+			void shouldReturnNull() {
+				var vorgangId = mapper.toString(null);
+				
+				assertThat(vorgangId).isNull();				
+			}
+		}
 	}
-
-}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandRemoteServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/command/CommandRemoteServiceTest.java
similarity index 90%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandRemoteServiceTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/command/CommandRemoteServiceTest.java
index 67e040e6b913bb561830109ecffc63ed196ae011..a1412ebe5bce1588c829807a617dce76308c98d3 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandRemoteServiceTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/command/CommandRemoteServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -33,7 +33,7 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
+import de.ozgcloud.vorgang.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
 
 class CommandRemoteServiceTest {
 
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/command/CommandServiceTest.java
similarity index 88%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandServiceTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/command/CommandServiceTest.java
index f130b47b3af1b9031ece9703fc8091605105fff6..201bb62785ab1a23c3c831ef3f8c4ccdd65d332a 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandServiceTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/command/CommandServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,19 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.itvsh.kop.notification.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.notification.postfach.PostfachNachrichtTestFactory;
 
 class CommandServiceTest {
 
@@ -43,6 +44,7 @@ class CommandServiceTest {
 	@Mock
 	private CommandRemoteService remoteService;
 
+	@DisplayName("Create send postfachNachricht command")
 	@Nested
 	class TestCreateSendPostfachNachrichtCommnad {
 		@Test
@@ -63,6 +65,7 @@ class CommandServiceTest {
 		}
 	}
 
+	@DisplayName("To map")
 	@Nested
 	class TestToMap {
 
@@ -80,5 +83,4 @@ class CommandServiceTest {
 			assertThat(map).doesNotContainKey("class");
 		}
 	}
-
-}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/command/CommandTestFactory.java
similarity index 84%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/command/CommandTestFactory.java
index a13ac1664a652c32bc0f8c8f70a34dc5e1262ab1..a775943a7d47927ec4d572c27d42f457b8983164 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/command/CommandTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/command/CommandTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,16 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
 import java.util.Map;
 import java.util.UUID;
 
-import de.itvsh.kop.notification.command.Command.CommandOrder;
-import de.itvsh.kop.notification.vorgang.VorgangTestFactory;
+import de.ozgcloud.notification.command.Command.CommandOrder;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
 
 public class CommandTestFactory {
 
+	public static final String ID = UUID.randomUUID().toString();
+
 	public static final String RELATION_ID = UUID.randomUUID().toString();
 	public static final CommandOrder ORDER = CommandOrder.SEND_POSTFACH_NACHRICHT;
 
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/command/GrpcCreateCommandRequestTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/command/GrpcCreateCommandRequestTestFactory.java
similarity index 82%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/command/GrpcCreateCommandRequestTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/command/GrpcCreateCommandRequestTestFactory.java
index b39c287483df0a8d186534d385d0c66f566e6e00..679063fc905f753a3c1af4b2b257d2fdfd27d2b2 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/command/GrpcCreateCommandRequestTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/command/GrpcCreateCommandRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.command;
+package de.ozgcloud.notification.command;
 
-import de.itvsh.kop.notification.vorgang.VorgangTestFactory;
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectTestFactory;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectTestFactory;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
 
 public class GrpcCreateCommandRequestTestFactory {
 
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/email/EmailRecipientMapperTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/email/EmailRecipientMapperTest.java
similarity index 89%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/email/EmailRecipientMapperTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/email/EmailRecipientMapperTest.java
index d42ad912fcd3f14fe22530e301b44aaa8fa4b2b1..a07d0da730f24c53ac2463c2cae605b11e8aa0eb 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/email/EmailRecipientMapperTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/email/EmailRecipientMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.email;
+package de.ozgcloud.notification.email;
 
-import de.itvsh.kop.notification.user.RecipientTestFactory;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 
 import static org.assertj.core.api.Assertions.*;
 
+import de.ozgcloud.notification.user.RecipientTestFactory;
+
 class EmailRecipientMapperTest {
 
 	private EmailRecipientMapper mapper = Mappers.getMapper(EmailRecipientMapper.class);
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/email/EmailRemoteServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/email/EmailRemoteServiceTest.java
similarity index 65%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/email/EmailRemoteServiceTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/email/EmailRemoteServiceTest.java
index 73a4bdd8e9af181d3df52fe99c0f0399b73c11a2..5e69a978eb0f8286485afd00080f083e734c4531 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/email/EmailRemoteServiceTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/email/EmailRemoteServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.email;
+package de.ozgcloud.notification.email;
 
-import de.itvsh.kop.notification.user.RecipientTestFactory;
-import de.itvsh.ozg.mail.email.EmailServiceGrpc.EmailServiceBlockingStub;
-import de.itvsh.ozg.mail.email.GrpcRecipient;
-import de.itvsh.ozg.mail.email.GrpcSendEmailRequest;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
@@ -34,10 +35,10 @@ import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import static org.assertj.core.api.Assertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
+import de.ozgcloud.nachrichten.email.EmailServiceGrpc.EmailServiceBlockingStub;
+import de.ozgcloud.nachrichten.email.GrpcRecipient;
+import de.ozgcloud.nachrichten.email.GrpcSendEmailRequest;
+import de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor;
 
 class EmailRemoteServiceTest {
 
@@ -58,41 +59,41 @@ class EmailRemoteServiceTest {
 
 		private final static GrpcRecipient GRPC_RECIPIENT = GrpcEmailRecipientTestFactory.create();
 
-		@Test
-		void shouldCallEmailServiceOnlyOnce() {
+		@BeforeEach
+		void initTest() {
 			when(recipientMapper.toGrpc(any())).thenReturn(GRPC_RECIPIENT);
-			var userEmail = UserEmailTestFactory.createBuilder().recipient(RecipientTestFactory.create()).build();
+			when(emailStub.withInterceptors(any())).thenReturn(emailStub);
+		}
 
-			remoteService.sendEmail(userEmail);
+		@Test
+		void shouldCallEmailServiceOnlyOnce() {
+			remoteService.sendEmail(UserEmailTestFactory.create());
 
 			verify(emailStub, times(1)).sendEmail(any());
 		}
 
 		@Test
 		void shouldNotifyAllRecipients() {
-			when(recipientMapper.toGrpc(any())).thenReturn(GRPC_RECIPIENT);
-			var userEmail = UserEmailTestFactory.createBuilder().recipient(RecipientTestFactory.create()).build();
-
-			remoteService.sendEmail(userEmail);
+			remoteService.sendEmail(UserEmailTestFactory.create());
 
 			verify(emailStub).sendEmail(requestCaptor.capture());
-			assertThat(requestCaptor.getValue().getRecipientsList()).hasSameSizeAs(userEmail.recipients());
+			assertThat(requestCaptor.getValue().getRecipientsList()).hasSameSizeAs(UserEmailTestFactory.RECIPIENTS);
 		}
 
 		@Test
 		void shouldConvertCorrectly() {
-			when(recipientMapper.toGrpc(any())).thenReturn(GRPC_RECIPIENT);
-
 			remoteService.sendEmail(UserEmailTestFactory.create());
 
 			verify(emailStub).sendEmail(requestCaptor.capture());
-			var emailRecipient = requestCaptor.getValue().getRecipients(0);
-			assertThat(emailRecipient).usingRecursiveComparison().isEqualTo(GRPC_RECIPIENT);
+			assertThat(requestCaptor.getValue().getRecipientsList()).first().usingRecursiveComparison().isEqualTo(GRPC_RECIPIENT);
 		}
 
 		@Test
-		void shouldFailWhenRecipientsAreNull() {
-			assertThrows(NullPointerException.class, () -> remoteService.sendEmail(null));
+		void shouldUseInterceptor() {
+			remoteService.sendEmail(UserEmailTestFactory.create());
+
+			verify(emailStub).withInterceptors(any(NotificationManagerCallContextAttachingInterceptor.class));
 		}
+
 	}
 }
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/email/GrpcEmailRecipientTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/email/GrpcEmailRecipientTestFactory.java
similarity index 84%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/email/GrpcEmailRecipientTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/email/GrpcEmailRecipientTestFactory.java
index 505fedce933f297290f4f0cd9f296a707b316d53..9bf28061e557f6185fe08a6fa273d56ba74dd542 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/email/GrpcEmailRecipientTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/email/GrpcEmailRecipientTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.email;
+package de.ozgcloud.notification.email;
 
-import de.itvsh.ozg.mail.email.GrpcRecipient;
+import de.ozgcloud.nachrichten.email.GrpcRecipient;
 
-import static de.itvsh.kop.notification.user.RecipientTestFactory.*;
+import static de.ozgcloud.notification.user.RecipientTestFactory.*;
 
 public class GrpcEmailRecipientTestFactory {
 
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/email/UserEmailTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/email/UserEmailTestFactory.java
similarity index 71%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/email/UserEmailTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/email/UserEmailTestFactory.java
index b1a8cc733224736a32999646fbe9bad4d130bb14..ea77432f7ee69e0ab6b33c86533e0af22f03a7db 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/email/UserEmailTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/email/UserEmailTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.email;
-
-import de.itvsh.kop.notification.email.UserEmail.UserEmailBuilder;
-import de.itvsh.kop.notification.user.Recipient;
-import de.itvsh.kop.notification.user.UserNotificationService;
-import de.itvsh.kop.notification.user.RecipientTestFactory;
+package de.ozgcloud.notification.email;
 
 import java.util.List;
 
+import de.ozgcloud.notification.email.UserEmail.UserEmailBuilder;
+import de.ozgcloud.notification.user.Recipient;
+import de.ozgcloud.notification.user.RecipientTestFactory;
+import de.ozgcloud.notification.user.UserNotificationService;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
+
 public class UserEmailTestFactory {
 
 	public static final List<Recipient> RECIPIENTS = List.of(RecipientTestFactory.create());
@@ -41,7 +42,7 @@ public class UserEmailTestFactory {
 	public static UserEmailBuilder createBuilder() {
 		return UserEmail.builder()
 				.recipients(RECIPIENTS)
-				.subject(UserNotificationService.MAIL_SUBJECT)
+				.subject(UserNotificationService.MAIL_SUBJECT_TEMPLATE.formatted(VorgangTestFactory.VORGANG_NAME))
 				.body(UserNotificationService.MAIL_BODY);
 	}
 }
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/postfach/GrpcPostfachAddressTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/GrpcPostfachAddressTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a1948d6415bdd26869b901f5806ffa09c57bc6a
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/GrpcPostfachAddressTestFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.common.GrpcProperty;
+import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress;
+
+public class GrpcPostfachAddressTestFactory {
+
+	public static GrpcPostfachAddress create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcPostfachAddress.Builder createBuilder() {
+		return GrpcPostfachAddress.newBuilder()
+				.setType(PostfachAddressTestFactory.TYPE)
+				.setIdentifier(createIdentifier())
+				.setVersion(PostfachAddressTestFactory.VERSION);
+	}
+	public static GrpcObject createIdentifier() {
+		return GrpcObject.newBuilder()
+				.addProperty(GrpcProperty.newBuilder()
+						.setName(StringBasedIdentifier.POSTFACH_ID_FIELD)
+						.addValue(PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE)
+						.build())
+				.build();
+	}
+}
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachAddressTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachAddressTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..da03e9618d253d82bd31753c721d46c76f241fa3
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachAddressTestFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+import java.util.UUID;
+
+public class PostfachAddressTestFactory {
+
+	public final static int TYPE = 1;
+	public static final String STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE = UUID.randomUUID().toString();
+	public final static StringBasedIdentifier IDENTIFIER = StringBasedIdentifier.builder().postfachId(STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE)
+			.build();
+	public static final String VERSION = "1.0";
+
+	public static PostfachAddress create() {
+		return createBuilder().build();
+	}
+
+	public static PostfachAddress.PostfachAddressBuilder createBuilder() {
+		return PostfachAddress.builder()
+				.type(TYPE)
+				.identifier(IDENTIFIER)
+				.version(VERSION);
+	}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/postfach/PostfachNachrichtTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachNachrichtTestFactory.java
similarity index 69%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/postfach/PostfachNachrichtTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachNachrichtTestFactory.java
index dfc94e781e7530ca846713d9c869af4cb8f87134..457b9df2ad9e32aab7522a0fad2654a3f4f2a202 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/postfach/PostfachNachrichtTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachNachrichtTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.postfach;
+package de.ozgcloud.notification.postfach;
 
 import java.util.Map;
 
-import de.itvsh.kop.notification.vorgang.VorgangTestFactory;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
 
 public class PostfachNachrichtTestFactory {
 
@@ -40,6 +40,7 @@ public class PostfachNachrichtTestFactory {
 		return PostfachNachricht.builder()
 				.vorgangId(VorgangTestFactory.ID)
 				.postfachId(VorgangTestFactory.POSTFACH_ID)
+				.postfachAddress(PostfachAddressTestFactory.create())
 				.mailBody(MESSAGE)
 				.subject(SUBJECT);
 	}
@@ -48,10 +49,19 @@ public class PostfachNachrichtTestFactory {
 		return Map.of(
 				PostfachNachricht.FIELD_VORGANG_ID, VorgangTestFactory.ID,
 				PostfachNachricht.FIELD_POSTFACH_ID, VorgangTestFactory.POSTFACH_ID,
+				PostfachNachricht.FIELD_POSTFACH_ADDRESS, createPostfachAddressMap(),
 				PostfachNachricht.FIELD_SUBJECT, SUBJECT,
 				PostfachNachricht.FIELD_MESSAGE, MESSAGE,
 				PostfachNachricht.FIELD_REPLY_OPTION, PostfachNachricht.DEFAULT_REPLY_OPTION);
-
 	}
-
-}
+	
+	public static final Map<String, Object> createPostfachAddressMap(){
+		return Map.of(PostfachAddress.TYPE_FIELD, PostfachAddressTestFactory.TYPE,
+				PostfachAddress.VERSION_FIELD, PostfachAddressTestFactory.VERSION,
+				PostfachAddress.IDENTIFIER_FIELD, createIdentifierMap());
+	}
+	
+	public static final Map<String, Object> createIdentifierMap(){
+		return Map.of(PostfachNachricht.FIELD_POSTFACH_ID, PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE);
+	}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachRemoteServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..121df7b505461913ae27b42bf656bce187ac2698
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachRemoteServiceTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.nachrichten.postfach.GrpcIsPostfachConfiguredResponse;
+import de.ozgcloud.nachrichten.postfach.PostfachServiceGrpc.PostfachServiceBlockingStub;
+
+class PostfachRemoteServiceTest {
+
+	@Spy
+	@InjectMocks
+	private PostfachRemoteService postfachRemoteService;
+
+	@Mock
+	private PostfachServiceBlockingStub blockingStub;
+
+	private static final GrpcIsPostfachConfiguredResponse GRPC_POSTFACH_RESPONSE = GrpcIsPostfachConfiguredResponse.newBuilder().build();
+
+	@BeforeEach
+	void setup() {
+		when(blockingStub.withInterceptors(any())).thenReturn(blockingStub);
+		when(blockingStub.isPostfachConfigured(any())).thenReturn(GRPC_POSTFACH_RESPONSE);
+	}
+
+	@Test
+	void shouldGetPostfachServiceStub() {
+		postfachRemoteService.isPostfachConfigured();
+
+		verify(postfachRemoteService).getPostfachServiceStub();
+	}
+
+	@Test
+	void shouldCallIsPostfachConfigured() {
+		postfachRemoteService.isPostfachConfigured();
+
+		verify(blockingStub).isPostfachConfigured(any());
+	}
+
+	@Test
+	void shouldReturnIsPostfachConfigured() {
+		var postfachResponse = GrpcIsPostfachConfiguredResponse.newBuilder().setIsConfigured(true).build();
+		when(blockingStub.isPostfachConfigured(any())).thenReturn(postfachResponse);
+
+		var isPostfachConfigured = postfachRemoteService.isPostfachConfigured();
+
+		assertTrue(isPostfachConfigured);
+	}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..828c2801d79bb4bd1f59d74f5c5116aea22000da
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/postfach/PostfachServiceTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.postfach;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+class PostfachServiceTest {
+
+	@InjectMocks
+	private PostfachService postfachService;
+	@Mock
+	private PostfachRemoteService postfachRemoteService;
+
+	@Test
+	void shouldCallRemoteService() {
+		postfachService.isPostfachConfigured();
+
+		verify(postfachRemoteService).isPostfachConfigured();
+	}
+
+	@Test
+	void shouldReturnRemoteServiceResult() {
+		when(postfachRemoteService.isPostfachConfigured()).thenReturn(true);
+
+		var result = postfachService.isPostfachConfigured();
+
+		assertTrue(result);
+	}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/user/GrpcFindRecipientRequestTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/user/GrpcFindRecipientRequestTestFactory.java
similarity index 85%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/user/GrpcFindRecipientRequestTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/user/GrpcFindRecipientRequestTestFactory.java
index 544f762696c2b54ab03b6fa8e5d045fbf8ef6ba0..d3ed41140d05b3cb51bd35507faa409d260c4167 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/user/GrpcFindRecipientRequestTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/user/GrpcFindRecipientRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
-import de.itvsh.kop.user.grpc.recipient.GrpcFindRecipientResponse;
-import de.itvsh.kop.user.recipient.GrpcRecipient;
+import de.ozgcloud.user.grpc.recipient.GrpcFindRecipientResponse;
+import de.ozgcloud.user.recipient.GrpcRecipient;
 
 public class GrpcFindRecipientRequestTestFactory {
 
@@ -37,4 +37,5 @@ public class GrpcFindRecipientRequestTestFactory {
 	public static GrpcFindRecipientResponse.Builder createBuilder() {
 		return GrpcFindRecipientResponse.newBuilder().addRecipient(GRPC_RECIPIENT);
 	}
+
 }
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/user/GrpcUserRecipientTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/user/GrpcUserRecipientTestFactory.java
similarity index 89%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/user/GrpcUserRecipientTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/user/GrpcUserRecipientTestFactory.java
index 6b9f9b0b8bb0c7b467ed959992d62cb1b2d7397c..44893eefadb925014fc923847b6d58ca6ad330eb 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/user/GrpcUserRecipientTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/user/GrpcUserRecipientTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
-import de.itvsh.kop.user.recipient.GrpcRecipient;
+import de.ozgcloud.user.recipient.GrpcRecipient;
 
 public class GrpcUserRecipientTestFactory {
 
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/user/RecipientTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/user/RecipientTestFactory.java
similarity index 88%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/user/RecipientTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/user/RecipientTestFactory.java
index 7e9a8906397b35272713acfcf73464c3f5b3e476..38d1da8f93a9f0a872059bbd8e4401d898bf432c 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/user/RecipientTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/user/RecipientTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
-import de.itvsh.kop.notification.user.Recipient.RecipientBuilder;
+import de.ozgcloud.notification.user.Recipient.RecipientBuilder;
 
 public class RecipientTestFactory {
 
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/user/UserNotificationEventListenerTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/user/UserNotificationEventListenerTest.java
similarity index 71%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/user/UserNotificationEventListenerTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/user/UserNotificationEventListenerTest.java
index 65992561673a4c3c992215ab7c298f6a52907d89..e7f3b622dca4d3596811c63130df9fda34889d9a 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/user/UserNotificationEventListenerTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/user/UserNotificationEventListenerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -33,10 +33,10 @@ import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.kop.notification.vorgang.VorgangId;
-import de.itvsh.kop.notification.vorgang.VorgangService;
-import de.itvsh.kop.notification.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.notification.vorgang.VorgangId;
+import de.ozgcloud.notification.vorgang.VorgangService;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
 
 class UserNotificationEventListenerTest {
 
@@ -72,27 +72,14 @@ class UserNotificationEventListenerTest {
 
 			@Test
 			void shouldNotifyWithOrganisationeinheitIds() {
-				userNotificationEventListener.onVorgangCreated(EVENT);
-
-				verify(userNotificationService).sendNotification(VorgangTestFactory.ORGANISATIONS_EINHEIT_ID);
-			}
-		}
-
-		@DisplayName("with missing orgaId")
-		@Nested
-		class TestWithoutOrgaId {
+				var vorgang = VorgangTestFactory.create();
+				when(vorgangService.getVorgang(any())).thenReturn(vorgang);
 
-			@BeforeEach
-			void initMock() {
-				when(vorgangService.getVorgang(any())).thenReturn(VorgangTestFactory.createBuilder().organisationseinheitenId(null).build());
-			}
-
-			@Test
-			void shouldNotCallNotificationService() {
 				userNotificationEventListener.onVorgangCreated(EVENT);
 
-				verifyNoInteractions(userNotificationService);
+				verify(userNotificationService).sendNotification(vorgang);
 			}
 		}
+
 	}
 }
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/user/UserNotificationServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/user/UserNotificationServiceTest.java
similarity index 63%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/user/UserNotificationServiceTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/user/UserNotificationServiceTest.java
index 0c2deb9aaa41387fd427e08d66e63ce00a81cf72..7ad5945327fd3d2300230b7f8b84272313fc7917 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/user/UserNotificationServiceTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/user/UserNotificationServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -35,14 +35,17 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 
-import de.itvsh.kop.notification.email.EmailRemoteService;
-import de.itvsh.kop.notification.email.UserEmail;
-import de.itvsh.kop.notification.email.UserEmailTestFactory;
-import de.itvsh.kop.notification.vorgang.VorgangTestFactory;
+import de.ozgcloud.notification.email.EmailRemoteService;
+import de.ozgcloud.notification.email.UserEmail;
+import de.ozgcloud.notification.email.UserEmailTestFactory;
+import de.ozgcloud.notification.vorgang.Vorgang;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
 
 class UserNotificationServiceTest {
 
+	@Spy
 	@InjectMocks
 	private UserNotificationService service;
 
@@ -67,16 +70,27 @@ class UserNotificationServiceTest {
 
 			@Test
 			void shouldGetRecipients() {
-				service.sendNotification(VorgangTestFactory.ORGANISATIONS_EINHEIT_ID);
+				service.sendNotification(VorgangTestFactory.create());
 
 				verify(userRemoteService).getRecipients(VorgangTestFactory.ORGANISATIONS_EINHEIT_ID);
 			}
 
 			@Test
 			void shouldSendEmail() {
-				service.sendNotification(VorgangTestFactory.ORGANISATIONS_EINHEIT_ID);
+				var email = UserEmailTestFactory.create();
+				doReturn(email).when(service).buildUserEmail(anyList(), anyString());
+
+				service.sendNotification(VorgangTestFactory.create());
+
+				verify(emailRemoteService).sendEmail(email);
+			}
+
+			@Test
+			void shouldSetSubject() {
+				service.sendNotification(VorgangTestFactory.create());
+
+				verify(service).buildUserEmail(anyList(), eq("Neuer Vorgang: " + VorgangTestFactory.VORGANG_NAME));
 
-				verify(emailRemoteService).sendEmail(UserEmailTestFactory.create());
 			}
 		}
 
@@ -84,26 +98,28 @@ class UserNotificationServiceTest {
 		@Nested
 		class TestWithInvalidOrgaId {
 
-			@Test
-			void shouldThrowIllegalArgumentException() {
-				assertThatThrownBy(() -> service.sendNotification(null))
-						.isInstanceOf(IllegalArgumentException.class)
-						.withFailMessage("organisationsEinheitId cannot be null.");
-			}
+			private Vorgang vorgang = VorgangTestFactory.createBuilder().organisationseinheitenId(null).build();
 
 			@Test
 			void shouldNotCallUserRemoteService() {
-				assertThatThrownBy(() -> service.sendNotification(null));
+				service.sendNotification(vorgang);
 
 				verify(userRemoteService, never()).getRecipients(anyString());
 			}
 
 			@Test
-			void shouldNotCallEmailRemoteSErvie() {
-				assertThatThrownBy(() -> service.sendNotification(null));
+			void shouldNotCallEmailRemoteServie() {
+				service.sendNotification(vorgang);
 
 				verify(emailRemoteService, never()).sendEmail(any(UserEmail.class));
 			}
 		}
+
+		@Test
+		void shouldThrowExceptionWhenVorgangNull() {
+			assertThatThrownBy(() -> service.sendNotification(null))
+					.withFailMessage("organisationsEinheitId cannot be null.")
+					.isInstanceOf(IllegalArgumentException.class);
+		}
 	}
 }
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/user/UserRecipientMapperTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/user/UserRecipientMapperTest.java
similarity index 93%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/user/UserRecipientMapperTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/user/UserRecipientMapperTest.java
index 28000bcb0b497996e22a84c299f5eda68737c14f..3ab993e986b79f7d0378fe26d849ff8acc18f9ea 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/user/UserRecipientMapperTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/user/UserRecipientMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.user;
+package de.ozgcloud.notification.user;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/user/UserRemoteServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/user/UserRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b441806c90bceb173a0e4520cec048a3c1595845
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/user/UserRemoteServiceTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.user;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor;
+import de.ozgcloud.notification.vorgang.VorgangTestFactory;
+import de.ozgcloud.user.grpc.recipient.RecipientServiceGrpc.RecipientServiceBlockingStub;
+
+class UserRemoteServiceTest {
+
+	@InjectMocks
+	private UserRemoteService remoteService;
+
+	@Mock
+	private RecipientServiceBlockingStub stub;
+	@Mock
+	private UserRecipientMapper mapper;
+
+	@Nested
+	class TestRequestRecipients {
+
+		@BeforeEach
+		void initTest() {
+			when(stub.findRecipientByOrganisationsEinheitId(any())).thenReturn(GrpcFindRecipientRequestTestFactory.create());
+			when(stub.withInterceptors(any())).thenReturn(stub);
+		}
+
+		@Test
+		void shouldCallMapper() {
+			remoteService.getRecipients(VorgangTestFactory.ORGANISATIONS_EINHEIT_ID);
+
+			verify(mapper).fromGrpc(GrpcFindRecipientRequestTestFactory.GRPC_RECIPIENT);
+		}
+
+		@Test
+		void shouldUseInterceptor() {
+			remoteService.getRecipients(VorgangTestFactory.ORGANISATIONS_EINHEIT_ID);
+
+			verify(stub).withInterceptors(any(NotificationManagerCallContextAttachingInterceptor.class));
+		}
+	}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcServiceKontoTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcServiceKontoTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ec7fef947e960f40c0fdd6c08fe0ab60e4c0ad1
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcServiceKontoTestFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.vorgang;
+
+import de.ozgcloud.notification.postfach.GrpcPostfachAddressTestFactory;
+import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto;
+
+public class GrpcServiceKontoTestFactory {
+
+	public final static String TYPE = "OSI";
+
+	public static GrpcServiceKonto create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcServiceKonto.Builder createBuilder() {
+		return GrpcServiceKonto.newBuilder()
+				.setType(TYPE)
+				.addPostfachAddresses(GrpcPostfachAddressTestFactory.create());
+	}
+}
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcVorgangHeadTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcVorgangHeadTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a215a89d071c4717ff662dfb1c1809f7ada2cc73
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcVorgangHeadTestFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.vorgang;
+
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangHead;
+
+public class GrpcVorgangHeadTestFactory {
+
+	public static GrpcVorgangHead create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcVorgangHead.Builder createBuilder() {
+		return GrpcVorgangHead.newBuilder()
+				.setServiceKonto(GrpcServiceKontoTestFactory.create());
+	}
+}
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/GrpcVorgangTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcVorgangTestFactory.java
similarity index 82%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/GrpcVorgangTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcVorgangTestFactory.java
index f2213c28a699438bea0f004653214fa3061c7d37..964cc783b512aedb12e470d8f38fe07fed2d31de 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/GrpcVorgangTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/GrpcVorgangTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.notification.vorgang;
 
-import de.itvsh.ozg.pluto.vorgang.GrpcAntragsteller;
-import de.itvsh.ozg.pluto.vorgang.GrpcEingang;
-import de.itvsh.ozg.pluto.vorgang.GrpcVorgangWithEingang;
-import de.itvsh.ozg.pluto.vorgang.GrpcZustaendigeStelle;
+import de.ozgcloud.vorgang.vorgang.GrpcAntragsteller;
+import de.ozgcloud.vorgang.vorgang.GrpcEingang;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangWithEingang;
+import de.ozgcloud.vorgang.vorgang.GrpcZustaendigeStelle;
 
 public class GrpcVorgangTestFactory {
 
@@ -41,6 +41,7 @@ public class GrpcVorgangTestFactory {
 				.setNummer(VorgangTestFactory.VORGANG_NUMMER)
 				.setCreatedAt(VorgangTestFactory.CREATED_AT_STR)
 				.setFormEngineName(VorgangTestFactory.FORM_ENGINE_NAME)
+				.setHeader(GrpcVorgangHeadTestFactory.create())
 				.setEingang(GrpcEingang.newBuilder()
 						.setAntragsteller(GrpcAntragsteller.newBuilder()
 								.setPostfachId(VorgangTestFactory.POSTFACH_ID)
diff --git a/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangMapperTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..060b5d66cfe5d28270c45b1950fe3af6d9980ca0
--- /dev/null
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangMapperTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.notification.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+
+import de.ozgcloud.notification.postfach.PostfachAddressTestFactory;
+
+class VorgangMapperTest {
+
+	private final VorgangMapper mapper = Mappers.getMapper(VorgangMapper.class);
+
+	@DisplayName("From grpc")
+	@Nested
+	class TestFromGrpc {
+
+		@Test
+		void shouldMapVorgang() {
+			var mapped = fromGrpc();
+
+			assertThat(mapped).usingRecursiveComparison().ignoringFields("postfachAddress").isEqualTo(VorgangTestFactory.create());
+		}
+		
+		@DisplayName("postfachAddress")
+		@Nested
+		class TestPostfachAddress {
+			
+			@Test
+			void shouldMapIfServiceKontoExists() {
+				var mapped = fromGrpc();
+
+				assertThat(mapped.getPostfachAddress()).usingRecursiveComparison().isEqualTo(PostfachAddressTestFactory.create());
+			}
+			
+			@Test
+			void shouldBeEmptyIfServiceKontoNotExists() {
+				var mapped = mapper.fromGrpc(GrpcVorgangTestFactory.createBuilder().clearHeader().build());
+
+				assertThat(mapped.getPostfachAddress()).isNull();
+			}
+		}
+
+		private Vorgang fromGrpc() {
+			return mapper.fromGrpc(GrpcVorgangTestFactory.create());
+		}
+	}
+}
\ No newline at end of file
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangRemoteServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangRemoteServiceTest.java
similarity index 85%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangRemoteServiceTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangRemoteServiceTest.java
index c78106714ba67860c576a773aedc37eb8e423f1f..0d978983aae3409de2bbe4700ff07a254a817ad4 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangRemoteServiceTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangRemoteServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.notification.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -35,11 +35,11 @@ import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.kop.notification.NotificationManagerCallContextAttachingInterceptor;
-import de.itvsh.ozg.pluto.vorgang.GrpcFindVorgangWithEingangRequest;
-import de.itvsh.ozg.pluto.vorgang.GrpcFindVorgangWithEingangResponse;
-import de.itvsh.ozg.pluto.vorgang.GrpcVorgangWithEingang;
-import de.itvsh.ozg.pluto.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
+import de.ozgcloud.notification.NotificationManagerCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangRequest;
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangResponse;
+import de.ozgcloud.vorgang.vorgang.GrpcVorgangWithEingang;
+import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
 
 class VorgangRemoteServiceTest {
 
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangServiceTest.java b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangServiceTest.java
similarity index 94%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangServiceTest.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangServiceTest.java
index 68ee393ce873ad46147b84d4ff27aef1a4d6bfd5..9ef693cb25fa0e7f83e1f3f469a677c48448fa63 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangServiceTest.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.notification.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
diff --git a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangTestFactory.java b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangTestFactory.java
similarity index 89%
rename from notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangTestFactory.java
rename to notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangTestFactory.java
index c27f0f145d42efd872cefab223e4e11454aa1414..2492b431d9b64d356e3859f141fc5348b844135f 100644
--- a/notification-manager/src/test/java/de/itvsh/kop/notification/vorgang/VorgangTestFactory.java
+++ b/notification-manager/src/test/java/de/ozgcloud/notification/vorgang/VorgangTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.notification.vorgang;
+package de.ozgcloud.notification.vorgang;
 
 import java.time.ZonedDateTime;
 import java.util.UUID;
 
+import de.ozgcloud.notification.postfach.PostfachAddressTestFactory;
+
 public class VorgangTestFactory {
 
 	public static final VorgangId ID = VorgangId.from(UUID.randomUUID().toString());
@@ -50,6 +52,7 @@ public class VorgangTestFactory {
 				.vorgangNummer(VORGANG_NUMMER)
 				.createdAt(CREATED_AT)
 				.postfachId(POSTFACH_ID)
+				.postfachAddress(PostfachAddressTestFactory.create())
 				.formEngineName(FORM_ENGINE_NAME)
 				.organisationseinheitenId(ORGANISATIONS_EINHEIT_ID);
 	}
diff --git a/pluto-interface/lombok.config b/pluto-interface/lombok.config
deleted file mode 100644
index e2cecc9355b20d3ec85afca7daa6c78e6b2082ee..0000000000000000000000000000000000000000
--- a/pluto-interface/lombok.config
+++ /dev/null
@@ -1,28 +0,0 @@
-#   Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
-#   Ministerpräsidenten des Landes Schleswig-Holstein
-#   Staatskanzlei
-#   Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-#
-#   Lizenziert unter der EUPL, Version 1.2 oder - sobald
-#   diese von der Europäischen Kommission genehmigt wurden -
-#   Folgeversionen der EUPL ("Lizenz");
-#   Sie dürfen dieses Werk ausschließlich gemäß
-#   dieser Lizenz nutzen.
-#   Eine Kopie der Lizenz finden Sie hier:
-#
-#   https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-#
-#   Sofern nicht durch anwendbare Rechtsvorschriften
-#   gefordert oder in schriftlicher Form vereinbart, wird
-#   die unter der Lizenz verbreitete Software "so wie sie
-#   ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-#   ausdrücklich oder stillschweigend - verbreitet.
-#   Die sprachspezifischen Genehmigungen und Beschränkungen
-#   unter der Lizenz sind dem Lizenztext zu entnehmen.
-
-lombok.log.fieldName=LOG
-lombok.log.slf4j.flagUsage = ERROR
-lombok.log.log4j.flagUsage = ERROR
-lombok.data.flagUsage = ERROR
-lombok.nonNull.exceptionType = IllegalArgumentException
-lombok.addLombokGeneratedAnnotation = true
diff --git a/pluto-interface/src/main/protobuf/vorgangmodel.proto b/pluto-interface/src/main/protobuf/vorgangmodel.proto
deleted file mode 100644
index b8e5ce422526c189c2f108561b1f2527fb4522dd..0000000000000000000000000000000000000000
--- a/pluto-interface/src/main/protobuf/vorgangmodel.proto
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-syntax = "proto3";
-
-package de.itvsh.ozg.pluto.vorgang;
-
-import "clientattribute.model.proto";
-
-option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.vorgang";
-option java_outer_classname = "VorgangModelProto";
-
-message GrpcVorgangHeader {
-	string id = 1;
-	int64 version = 2;
-	string status = 3;
-	string name = 4;
-	string createdAt = 5;
-	string aktenzeichen = 6;
-	string assignedTo = 7;
-	string nummer = 8;
-	repeated de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute clientAttributes = 9;
-	string formEngineName = 15;
-}
-
-message GrpcVorgangWithEingang {
-	string id = 1;
-	int64 version = 2;
-	string status = 3;
-	string name = 4;
-	string createdAt = 5;
-	string aktenzeichen = 6;
-	string assignedTo = 7;
-	string nummer = 8;
-	repeated de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute clientAttributes = 9;
-	
-	GrpcEingang eingang = 10;
-	string formEngineName = 15;
-}
-
-message GrpcEingang {
-	string id = 1;
-	
-	GrpcEingangHeader header = 2;
-	GrpcAntragsteller antragsteller = 3;
-	GrpcZustaendigeStelle zustaendigeStelle = 4;
-	
-	GrpcFormData formData = 10;
-	
-	int32 numberOfAttachments = 11;
-	int32 numberOfRepresentations = 12;
-	
-	repeated GrpcIncomingFileGroup attachments = 20;
-	repeated GrpcIncomingFile representations = 21;
-}
-
-message GrpcIncomingFileGroup {
-    string name = 1;
-    repeated GrpcIncomingFile files = 2;
-}
-
-message GrpcIncomingFile {
-	string id = 1;
-	string vendorId = 2;
-	string name = 3;
-	string contentType = 4;
-	int64 size = 5;
-	bytes content = 6;
-}
-
-message GrpcEingangHeader {
-	string requestId = 1;
-	string createdAt = 2;
-	string formId = 3;
-	string formName = 4;
-	string sender = 5;
-	string customer = 6 [deprecated=true];
-	string customerId = 7 [deprecated=true];
-	string client = 8 [deprecated=true];
-	string clientId = 9 [deprecated=true];
-	string formEngineName = 10;
-}
-
-message GrpcAntragsteller {
-	string anrede = 1;
-	string nachname = 2;
-	string vorname = 3;
-	string geburtsdatum = 4;
-	string geburtsort = 5;
-	string geburtsname = 6;
-	string email = 7;
-	string telefon = 8;
-	string strasse = 9;
-	string hausnummer = 10;
-	string plz = 11;
-	string ort = 12;
-	string postfachId = 13;
-	
-	GrpcFormData otherData = 30;
-}
-
-message GrpcFormData {
-	repeated GrpcFormField field = 1;
-	repeated GrpcSubForm form = 2;
-}
-
-message GrpcFormField {
-	string name = 1;
-	string value = 2;
-}
-
-message GrpcSubForm {
-	string title = 1;
-	repeated GrpcFormField field = 2;
-	repeated GrpcSubForm subForm = 3;
-}
-
-message GrpcZustaendigeStelle {
-    string organisationseinheitenId = 1;
-    string email = 2;
-    string bezeichnung = 3;
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListener.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListener.java
deleted file mode 100644
index 00a7f8f4c37ec7b4f1cc2e23de95faad2c29781d..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListener.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.attached_item;
-
-import java.util.function.Predicate;
-
-import javax.validation.ValidationException;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Component;
-
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEvent;
-import de.itvsh.ozg.pluto.command.Order;
-
-@Component
-class VorgangAttachedItemEventListener {
-
-	private static final String IS_CREATE_ITEM_ORDER_CONDITION = "{T(de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemEventListener).IS_CREATE_ITEM_ORDER.test(event.getSource())}";
-	private static final String IS_UPDATE_ITEM_ORDER_CONDITION = "{T(de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemEventListener).IS_UPDATE_ITEM_ORDER.test(event.getSource())}";
-	private static final String IS_PATCH_ITEM_ORDER_CONDITION = "{T(de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemEventListener).IS_PATCH_ITEM_ORDER.test(event.getSource())}";
-
-	public static final Predicate<Command> IS_CREATE_ITEM_ORDER = command -> Order.CREATE_ATTACHED_ITEM.isMeant(command.getOrder());
-	public static final Predicate<Command> IS_UPDATE_ITEM_ORDER = command -> Order.UPDATE_ATTACHED_ITEM.isMeant(command.getOrder());
-	public static final Predicate<Command> IS_PATCH_ITEM_ORDER = command -> Order.PATCH_ATTACHED_ITEM.isMeant(command.getOrder());
-
-	@Autowired
-	private VorgangAttachedItemService service;
-	@Autowired
-	private VorgangAttachedItemMapper mapper;
-
-	@EventListener(condition = IS_CREATE_ITEM_ORDER_CONDITION)
-	public void createItem(CommandCreatedEvent event) {
-		var command = event.getSource();
-		validateCreateCommand(command);
-
-		var item = mapper.fill(command.getBodyObject());
-		service.create(command.getId(), item.toBuilder().id(null).version(0).build());
-	}
-
-	private void validateCreateCommand(Command command) {
-		if (!StringUtils.equals(command.getRelationId(), command.getVorgangId())) {
-			throw new ValidationException("Command invalid creation command: vorgangId and relationId must be equals");
-		}
-
-	}
-
-	@EventListener(condition = IS_UPDATE_ITEM_ORDER_CONDITION)
-	public void updateItem(CommandCreatedEvent event) {
-		var command = event.getSource();
-		var item = mapper.fill(command.getBodyObject())
-				.toBuilder().id(command.getRelationId()).version(command.getRelationVersion()).build();
-
-		service.update(command.getId(), item);
-	}
-
-	@EventListener(condition = IS_PATCH_ITEM_ORDER_CONDITION)
-	public void patchItem(CommandCreatedEvent event) {
-		var command = event.getSource();
-		var item = mapper.fill(command.getBodyObject());
-
-		service.patch(command, item.getItem());
-	}
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandService.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandService.java
deleted file mode 100644
index 061a09052379830d31bc3a9a0b4232e120650df6..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandService.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.command;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.net.URLConnection;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.Base64;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.stream.Stream;
-
-import javax.activation.MimetypesFileTypeMap;
-
-import org.apache.http.entity.ContentType;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.ozg.mail.postfach.MessageAttachment;
-import de.itvsh.ozg.mail.postfach.PersistPostfachMailService;
-import de.itvsh.ozg.mail.postfach.PostfachMail;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemMapper;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemService;
-import de.itvsh.ozg.pluto.files.FileService;
-import de.itvsh.ozg.pluto.files.OzgFile;
-import de.itvsh.ozg.pluto.files.UploadedFilesReference;
-import lombok.extern.log4j.Log4j2;
-
-/**
- * @deprecated Temporally replacement for using GRPC Api by MailService
- */
-@Deprecated
-@Service
-@Log4j2
-class PersistPostfachMailByCommandService implements PersistPostfachMailService {
-
-	static final String CLIENT = "MailService";
-	static final String ITEM_NAME = "PostfachMail";
-	static final String ATTACHMENT_NAME = "PostfachAttachment";
-
-	@Autowired
-	private CommandService service;
-	@Autowired
-	private VorgangAttachedItemService attachedItemService;
-	@Autowired
-	private FileService fileService;
-
-	@Override
-	public void persistMail(Optional<String> userId, PostfachMail mail) {
-		service.createCommand(CreateCommandRequest.builder()
-				.callContext(buildCallContext(userId))
-				.vorgangId(mail.getVorgangId())
-				.relationId(mail.getVorgangId()).relationVersion(-1L)
-				.order(Order.CREATE_ATTACHED_ITEM.name())
-				.bodyObject(buildItem(mail))
-				.build());
-	}
-
-	private CallContext buildCallContext(Optional<String> userId) {
-		var builder = CallContext.builder();
-		userId.map(id -> User.builder().id(id).build()).ifPresent(builder::user);
-
-		return builder.build();
-	}
-
-	private Map<String, Object> buildItem(PostfachMail mail) {
-		return Map.of(
-				VorgangAttachedItemMapper.PROPERTY_CLIENT, CLIENT,
-				VorgangAttachedItemMapper.PROPERTY_VORGANG_ID, mail.getVorgangId(),
-				VorgangAttachedItemMapper.PROPERTY_ITEM_NAME, ITEM_NAME,
-				VorgangAttachedItemMapper.PROPERTY_ITEM, buildMailMap(mail));
-
-	}
-
-	Map<String, Object> buildMailMap(PostfachMail mail) {
-		Map<String, Object> result = new HashMap<>(Map.of(
-				PostfachMail.FIELD_VORGANG_ID, mail.getVorgangId(),
-				PostfachMail.FIELD_POSTFACH_ID, mail.getPostfachId(),
-				PostfachMail.FIELD_CREATED_AT, mail.getCreatedAt().format(DateTimeFormatter.ISO_DATE_TIME),
-				PostfachMail.FIELD_DIRECTION, mail.getDirection().name(),
-				PostfachMail.FIELD_REPLY_OPTION, mail.getReplyOption().name(),
-				PostfachMail.FIELD_SUBJECT, mail.getSubject(),
-				PostfachMail.FIELD_MAIL_BODY, mail.getMailBody(),
-				PostfachMail.FIELD_ATTACHMENTS, mail.getAttachments()));
-
-		putIfNonNull(result, PostfachMail.FIELD_MESSAGE_ID, mail.getMessageId());
-		putIfNonNull(result, PostfachMail.FIELD_CREATED_BY, mail.getCreatedBy());
-		putIfNonNull(result, PostfachMail.FIELD_SENT_SUCCESSFUL, mail.getSentSuccessful());
-		putIfNonNull(result, PostfachMail.FIELD_MESSAGE_CODE, mail.getMessageCode());
-		putDateIfNonNull(result, PostfachMail.FIELD_SENT_AT, mail.getSentAt());
-
-		return Collections.unmodifiableMap(result);
-	}
-
-	private Map<String, Object> putIfNonNull(Map<String, Object> mapIn, String key, Object value) {
-		if (Objects.nonNull(value)) {
-			mapIn.put(key, value);
-		}
-		return mapIn;
-	}
-
-	private Map<String, Object> putDateIfNonNull(Map<String, Object> mapIn, String key, Object value) {
-		if (Objects.nonNull(value)) {
-			mapIn.put(key, ((ZonedDateTime) value).format(DateTimeFormatter.ISO_DATE_TIME));
-		}
-		return mapIn;
-	}
-
-	@Override
-	public Optional<Map<String, Object>> findById(String postfachNachrichtId) {
-		return attachedItemService.findById(postfachNachrichtId).map(VorgangAttachedItem::getItem);
-	}
-
-	@Override
-	public Stream<Map<String, Object>> findByVorgangAsMap(String vorgangId) {
-		return attachedItemService.find(vorgangId, Optional.of(CLIENT), Optional.of(ITEM_NAME)).map(VorgangAttachedItem::getItem);
-	}
-
-	@Override
-	public void patch(String postfachNachrichtId, Map<String, Object> propertyMap) {
-		attachedItemService.forcePatch(postfachNachrichtId, propertyMap);
-	}
-
-	@Override
-	public Map<String, Object> getById(String postfachNachrichtId) {
-		return attachedItemService.getById(postfachNachrichtId).getItem();
-	}
-
-	@Override
-	public String persistAttachment(String vorgangId, MessageAttachment attachment) {
-		var decContent = Base64.getDecoder().decode(attachment.getContent());
-		var contentType = getTypeByFile(attachment.getFileName(), attachment.getContent());
-
-		try {
-			return fileService.uploadFileStream(
-					createUploadedFilesReference(vorgangId),
-					createOzgFile(attachment, contentType, decContent.length),
-					Optional.empty(),
-					new ByteArrayInputStream(decContent)).get(10, TimeUnit.MINUTES).toString();
-		} catch (ExecutionException | TimeoutException e) {
-			throw new TechnicalException(e.getMessage(), e);
-		} catch (InterruptedException e) {
-			Thread.currentThread().interrupt();
-			throw new TechnicalException(e.getMessage(), e);
-		}
-	}
-
-	UploadedFilesReference createUploadedFilesReference(String vorgangId) {
-		return UploadedFilesReference.builder().vorgangId(vorgangId).client(CLIENT).name(ATTACHMENT_NAME).build();
-	}
-
-	OzgFile createOzgFile(MessageAttachment attachment, String contentType, long size) {
-		return OzgFile.builder().name(attachment.getFileName()).contentType(contentType).size(size).build();
-	}
-
-	String getTypeByFile(String fileName, String content) {
-		var fileNameMap = URLConnection.getFileNameMap();
-
-		return Optional.ofNullable(fileNameMap.getContentTypeFor(fileName)).orElseGet(() -> getTypeByContent(fileName, content));
-	}
-
-	private String getTypeByContent(String fileName, String content) {
-		try {
-			return Optional.ofNullable(URLConnection.guessContentTypeFromStream(new ByteArrayInputStream(content.getBytes())))
-					.orElseGet(() -> getByMimeTypes(fileName));
-		} catch (IOException e) {
-			LOG.warn("IO-Exception while guessing content type", e);
-		}
-		return ContentType.APPLICATION_OCTET_STREAM.toString();
-	}
-
-	// uses map file: src/main/resources/mime.types
-	private String getByMimeTypes(String fileName) {
-		MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
-
-		return fileTypeMap.getContentType(fileName);
-	}
-
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/StatusOrder.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/StatusOrder.java
deleted file mode 100644
index 945ac432c35111a506d3abf8d540d608b1d70722..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/StatusOrder.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.command;
-
-import java.util.Optional;
-
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@Getter
-@AllArgsConstructor
-@NoArgsConstructor
-enum StatusOrder {
-
-	VORGANG_ANNEHMEN(VorgangService::annehmen),
-	VORGANG_VERWERFEN(VorgangService::verwerfen),
-	VORGANG_ZURUECKHOLEN(VorgangService::setStatusNeu),
-	VORGANG_BEARBEITEN(VorgangService::bearbeiten),
-	VORGANG_BESCHEIDEN(VorgangService::bescheiden),
-	VORGANG_ZURUECKSTELLEN(VorgangService::annehmen),
-	VORGANG_ABSCHLIESSEN(VorgangService::abschliessen),
-	VORGANG_WIEDEREROEFFNEN(VorgangService::wiedereroeffnen),
-
-	REDIRECT_VORGANG,
-
-	ASSIGN_USER,
-
-	FORWARD_SUCCESSFULL,
-	FORWARD_FAILED,
-
-	SEND_POSTFACH_MAIL,
-	RESEND_POSTFACH_MAIL,
-
-	CREATE_ATTACHED_ITEM,
-	UPDATE_ATTACHED_ITEM;
-
-	interface OrderMethod {
-		Vorgang executeOrder(VorgangService service, Command command);
-	}
-
-	private OrderMethod method;
-
-	/** @deprecated please implement event/listener */
-	@Deprecated
-	static Optional<OrderMethod> getOrderMethod(String order) {
-		try {
-			return Optional.ofNullable(StatusOrder.valueOf(order).method);
-		} catch (IllegalArgumentException e) {
-			return Optional.empty();
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing.java
deleted file mode 100644
index 0f6a5535191d351428da4cdedc8267982092ec71..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.mongodb.core.query.Update;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-
-@ChangeUnit(id = "2022-01-21 13:57:00 OZG-2047", order = "M000", author = "jreese", runAlways = false)
-public class M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing { // NOSONAR
-	static final String FORM_ID_BAULASTENAUSKUNFT = "baulastenauskunft/baulastenaufkunft";
-	static final String ORGANISATIONSEINHEITEN_ID = "248240886";
-	static final String CUSTOMER_ID = "nordfriesland";
-	private static final String ZUSTAENDIGESTELLE_FIELD = "eingangs.0.zustaendigeStelle";
-	private static final String ZUSTAENDIGESTELLE_ORGANISATIONSEINHEITEN_ID_FIELD = "eingangs.0.zustaendigeStelle.organisationseinheitenId";
-	private static final String CUSTOMER_ID_FIELD = "eingangs.0.header.customerId";
-	private static final String FORM_ID_FIELD = "eingangs.0.header.formId";
-	private static final String COLLECTION_NAME = "vorgang";
-
-	@Execution
-	public void migrationMethod(MongoTemplate template) {
-		Update update = new Update();
-		update.set(ZUSTAENDIGESTELLE_ORGANISATIONSEINHEITEN_ID_FIELD, ORGANISATIONSEINHEITEN_ID);
-
-		Query query = new Query(Criteria
-				.where(ZUSTAENDIGESTELLE_FIELD)
-				.exists(false)
-				.and(CUSTOMER_ID_FIELD).is(CUSTOMER_ID)
-				.and(FORM_ID_FIELD).is(FORM_ID_BAULASTENAUSKUNFT));
-
-		template.updateMulti(query, update, COLLECTION_NAME);
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFs.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFs.java
deleted file mode 100644
index 298e1ac851ca4b1d76ef27a6f48cb06eba627405..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFs.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.List;
-import java.util.Objects;
-
-import org.bson.BsonObjectId;
-import org.bson.Document;
-import org.bson.types.Binary;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-
-import com.mongodb.MongoServerException;
-import com.mongodb.client.gridfs.GridFSBucket;
-import com.mongodb.client.gridfs.GridFSBuckets;
-import com.mongodb.client.gridfs.model.GridFSUploadOptions;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-import lombok.extern.log4j.Log4j2;
-
-@Log4j2
-@ChangeUnit(id = "2022-03-08 10:03:00 OZG-2259", order = "M001", author = "jreese", runAlways = false)
-public class M001_MigrateMailServiceAttachmentsToGridFs { // NOSONAR
-
-	private static final String ATTACHED_ITEM = "item";
-	static final String ATTACHED_ITEM_COLLECTION = "vorgangAttachedItem";
-	private static final String CONTENT_FIELD = "content";
-	static final String BINARY_FILE_COLLECTION = "binaryFile";
-	static final String GRID_FS_FILE_COLLECTION = "fs.files";
-	private static final String CREATED_BY = "createdBy";
-	private static final String CREATED_AT = "createdAt";
-	private static final String FILE_FIELD_NAME = "field";
-	private static final String FILE_FIELD = "file";
-	static final String OBJECT_ID = "_id";
-
-	static final String CLIENT = "client";
-	static final String CLIENT_VALUE = "MailService";
-	static final String CONTENT_TYPE = "contentType";
-	static final String FIELD_NAME = "fieldName";
-	static final String FILE_NAME = "name";
-	static final String VORGANG_ID = "vorgangId";
-
-	@Execution
-	public void migrationMethod(final MongoTemplate template) {
-		var attachedItems = findAttachedItems(template);
-		var gridFsBucket = getGridFsBucket(template);
-
-		attachedItems.stream()
-				.flatMap(attachedItem -> getAttachmentIds(attachedItem).stream())
-				.forEach(attachment -> doMigration(template, gridFsBucket, attachment));
-	}
-
-	private List<Document> findAttachedItems(MongoTemplate template) {
-		return template.find(Query.query(Criteria.where(CLIENT).is(CLIENT_VALUE)), Document.class, ATTACHED_ITEM_COLLECTION);
-	}
-
-	private GridFSBucket getGridFsBucket(MongoTemplate template) {
-		return GridFSBuckets.create(template.getDb());
-	}
-
-	@SuppressWarnings("unchecked")
-	private List<String> getAttachmentIds(Document attachedItem) {
-		return (List<String>) attachedItem.get(ATTACHED_ITEM, Document.class).get("attachments");
-	}
-
-	private void doMigration(final MongoTemplate template, GridFSBucket gridFs, String attachment) {
-		var gridFsFile = getFileFromGridFs(attachment, template);
-		if (Objects.isNull(gridFsFile)) {
-			var file = getFile(attachment, template);
-			if (Objects.nonNull(file)) {
-				try {
-					storeToGridFs(gridFs, file);
-				} catch (MongoServerException | IOException e) {
-					LOG.error("Error migrating Attachment id " + attachment, e);
-					throw new MigrationException("Error migrating Attachment with id " + attachment, e);
-				}
-			}
-		}
-	}
-
-	private Document getFile(String fileId, MongoTemplate template) {
-		return template.findOne(Query.query(Criteria.where(OBJECT_ID).is(fileId)), Document.class, BINARY_FILE_COLLECTION);
-	}
-
-	private Document getFileFromGridFs(String fileId, MongoTemplate template) {
-		return template.findOne(Query.query(Criteria.where(OBJECT_ID).is(fileId)), Document.class, GRID_FS_FILE_COLLECTION);
-	}
-
-	void storeToGridFs(GridFSBucket gridFsBucket, Document entry) throws IOException {
-		var file = entry.get(FILE_FIELD, Document.class);
-		byte[] convertedContent = convertContent(file);
-		try (var fileContentInputStream = new ByteArrayInputStream(convertedContent)) {
-			gridFsBucket.uploadFromStream(
-					createObjectId(entry),
-					createFilePath(entry, file),
-					fileContentInputStream,
-					createGridFsUploadOptions(entry, file));
-
-		}
-	}
-
-	@SuppressWarnings("unchecked")
-	byte[] convertContent(Document file) {
-		var content = (List<Binary>) file.get(CONTENT_FIELD);
-		List<byte[]> allData = content.stream().map(Binary::getData).toList();
-		final ByteArrayOutputStream out = new ByteArrayOutputStream();
-		allData.forEach(t -> {
-			try {
-				out.write(t);
-			} catch (IOException e) {
-				throw new MigrationException("Error converting data", e);
-			}
-		});
-		return out.toByteArray();
-	}
-
-	private BsonObjectId createObjectId(Document entry) {
-		return new BsonObjectId(entry.getObjectId(OBJECT_ID));
-	}
-
-	private String createFilePath(Document entry, Document file) {
-		return String.format("%s/%s/%s/%s",
-				entry.getString(VORGANG_ID),
-				entry.getString(CLIENT),
-				entry.getString(FILE_FIELD_NAME),
-				file.getString(FILE_NAME));
-	}
-
-	private GridFSUploadOptions createGridFsUploadOptions(Document entry, Document file) {
-		var uploadOptions = new GridFSUploadOptions();
-		uploadOptions.metadata(createMetaData(entry, file));
-		return uploadOptions;
-	}
-
-	private Document createMetaData(Document entry, Document file) {
-		var metadata = new Document();
-		metadata.append(VORGANG_ID, entry.get(VORGANG_ID));
-		metadata.append(CLIENT, entry.get(CLIENT));
-		metadata.append(FIELD_NAME, entry.get(FILE_FIELD_NAME));
-		metadata.append(CONTENT_TYPE, file.get(CONTENT_TYPE));
-		metadata.append(FILE_NAME, file.get(FILE_NAME));
-		metadata.append(CREATED_BY, entry.get(CREATED_BY));
-		metadata.append(CREATED_AT, entry.get(CREATED_AT));
-		return metadata;
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs.java
deleted file mode 100644
index 5cadda54a61d1941b620a1ec54170a227b96a79a..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.List;
-import java.util.Objects;
-
-import org.bson.Document;
-import org.bson.types.Binary;
-import org.bson.types.ObjectId;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-
-import com.mongodb.MongoServerException;
-import com.mongodb.client.gridfs.GridFSBucket;
-import com.mongodb.client.gridfs.GridFSBuckets;
-import com.mongodb.client.gridfs.model.GridFSUploadOptions;
-
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-import lombok.extern.log4j.Log4j2;
-
-@Log4j2
-//@ChangeUnit(id = "2022-04-29 14:45:00 OZG-2093", order = "M003", author = "jreese", runAlways = false)
-public class M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs { // NOSONAR
-
-	private static final String ATTACHMENTS_FIELD = "attachments";
-	private static final String REPRESENTATIONS_FIELD = "representations";
-	private static final String CONTENT_FIELD = "content";
-	private static final String CREATED_BY = "createdBy";
-	private static final String CREATED_AT = "createdAt";
-	private static final String EINGANGS_FIELD = "eingangs";
-	private static final String EINGANGS_ATTACHMENTS_FIELD = EINGANGS_FIELD + "." + ATTACHMENTS_FIELD;
-	private static final String FILES_FIELD = "files";
-
-	static final String CLIENT = "client";
-	static final String CLIENT_VALUE = "eingangManager";
-	static final String CONTENT_TYPE = "contentType";
-	static final String FILE_FIELD_NAME = "fieldName";
-	static final String ATTACHMENT_FIELD_NAME_VALUE = "vorgangAttachment";
-	static final String REPRESENTATION_FIELD_NAME_VALUE = "vorgangRepresentation";
-	static final String FILE_NAME = "name";
-	static final String GRID_FS_FILE_COLLECTION = "fs.files";
-	static final String GRISFS_FILE_NAME_FIELD = "filename";
-	static final String OBJECT_ID = "_id";
-	static final String VORGANG_ID = "vorgangId";
-	static final String VORGANG_COLLECTION = "vorgang";
-
-	@Execution
-	public void migrationMethod(final MongoTemplate template) {
-		var vorgangs = findVorgangsWithAttachments(template);
-		var gridFsBucket = getGridFsBucket(template);
-
-		vorgangs.forEach(vorgang -> {
-			getAttachments(vorgang).stream().flatMap(attachment -> getFiles(attachment).stream())
-					.filter(Objects::nonNull)
-					.forEach(file -> doMigration(template, gridFsBucket, file, vorgang, ATTACHMENT_FIELD_NAME_VALUE));
-			getRepresentations(vorgang).stream()
-					.forEach(file -> doMigration(template, gridFsBucket, file, vorgang, REPRESENTATION_FIELD_NAME_VALUE));
-		});
-	}
-
-	private List<Document> findVorgangsWithAttachments(MongoTemplate template) {
-		return template.find(Query.query(Criteria.where(EINGANGS_ATTACHMENTS_FIELD).exists(Boolean.TRUE)), Document.class, VORGANG_COLLECTION);
-	}
-
-	private GridFSBucket getGridFsBucket(MongoTemplate template) {
-		return GridFSBuckets.create(template.getDb());
-	}
-
-	private List<Document> getAttachments(Document vorgang) {
-		return vorgang.getList(EINGANGS_FIELD, Document.class).get(0).getList(ATTACHMENTS_FIELD, Document.class);
-	}
-
-	private List<Document> getRepresentations(Document vorgang) {
-		return vorgang.getList(EINGANGS_FIELD, Document.class).get(0).getList(REPRESENTATIONS_FIELD, Document.class);
-	}
-
-	private List<Document> getFiles(Document attachment) {
-		return attachment.getList(FILES_FIELD, Document.class);
-	}
-
-	private void doMigration(final MongoTemplate template, GridFSBucket gridFs, Document file, Document vorgang, String fieldValue) {
-		final String vorgangId = vorgang.getObjectId(OBJECT_ID).toString();
-		file.put(CREATED_AT, vorgang.getDate(CREATED_AT));
-		var existingGridFsFile = getFileFromGridFsById(file.getString(OBJECT_ID), template);
-		if (Objects.isNull(existingGridFsFile)) {
-			try {
-				var objectId = storeToGridFs(gridFs, file, vorgangId, fieldValue);
-				updateMigratedFile(template, file, objectId, vorgang);
-			} catch (MongoServerException | IOException e) {
-				LOG.error("Error migrating attachment {}", file, e);
-				throw new IllegalStateException(e.getMessage(), e);
-			}
-		}
-	}
-
-	private Document getFileFromGridFsById(String id, MongoTemplate template) {
-		return template.findOne(Query.query(Criteria.where(OBJECT_ID).is(id)), Document.class, GRID_FS_FILE_COLLECTION);
-	}
-
-	ObjectId storeToGridFs(GridFSBucket gridFsBucket, Document file, String vorgangId, String fieldValue) throws IOException {
-		byte[] content = ((Binary) file.get(CONTENT_FIELD)).getData();
-		try (var fileContentInputStream = new ByteArrayInputStream(content)) {
-			return gridFsBucket.uploadFromStream(
-					createFilePath(vorgangId, file, fieldValue),
-					fileContentInputStream,
-					createGridFsUploadOptions(file, vorgangId, fieldValue));
-
-		}
-	}
-
-	void updateMigratedFile(MongoTemplate template, Document file, ObjectId id, Document vorgang) {
-		file.put(OBJECT_ID, id.toHexString());
-
-		template.save(vorgang, VORGANG_COLLECTION);
-	}
-
-	private String createFilePath(String vorgangId, Document file, String fieldValue) {
-		return String.format("%s/%s/%s/%s",
-				vorgangId,
-				CLIENT_VALUE,
-				fieldValue,
-				file.getString(FILE_NAME));
-	}
-
-	private GridFSUploadOptions createGridFsUploadOptions(Document file, String vorgangId, String fieldValue) {
-		var uploadOptions = new GridFSUploadOptions();
-		uploadOptions.metadata(createMetaData(file, vorgangId, fieldValue));
-		return uploadOptions;
-	}
-
-	private Document createMetaData(Document file, String vorgangId, String fieldValue) {
-		var metadata = new Document();
-		metadata.append(VORGANG_ID, vorgangId);
-		metadata.append(CLIENT, CLIENT_VALUE);
-		metadata.append(FILE_FIELD_NAME, fieldValue);
-		metadata.append(CONTENT_TYPE, file.get(CONTENT_TYPE));
-		metadata.append(FILE_NAME, file.get(FILE_NAME));
-		metadata.append(CREATED_BY, file.get(CREATED_BY));
-		metadata.append(CREATED_AT, file.get(CREATED_AT));
-		return metadata;
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M004_RemoveWiedervorlagen.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M004_RemoveWiedervorlagen.java
deleted file mode 100644
index a84416efbbd55052829179b41a41f59bff162334..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M004_RemoveWiedervorlagen.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import org.bson.Document;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.mongodb.core.query.Update;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-
-@ChangeUnit(id = "2022-04-29 11:00:00 OZG-1918 OZG-2476", order = "M004", author = "jreese", runAlways = false)
-public class M004_RemoveWiedervorlagen { // NOSONAR
-	static final String BINARY_FILE_COLLECTION = "binaryFile";
-	static final String FIELD_KEY = "field";
-	static final String FIELD_KEY_VALUE = "wiedervorlageAttachment";
-	static final String WIEDERVORLAGES_FIELD_KEY = "wiedervorlages";
-	static final String VORGANG_COLLECTION = "vorgang";
-	static final String VORGANG_ID = "_id";
-
-	@Execution
-	public void migrationMethod(final MongoTemplate template) {
-		deleteWiedervorlageAttachments(template);
-		deleteWiedervorlagen(template);
-	}
-
-	private void deleteWiedervorlageAttachments(final MongoTemplate template) {
-		var query = new Query(Criteria.where(FIELD_KEY).is(FIELD_KEY_VALUE));
-
-		template.remove(query, BINARY_FILE_COLLECTION);
-	}
-
-	private void deleteWiedervorlagen(MongoTemplate template) {
-		var query = new Query(Criteria.where(WIEDERVORLAGES_FIELD_KEY).exists(true));
-		var vorgangs = template.find(query, Document.class, VORGANG_COLLECTION);
-
-		vorgangs.forEach(vorgangDoc -> {
-			var update = new Update();
-			update.unset(WIEDERVORLAGES_FIELD_KEY);
-			var updateQuery = new Query(Criteria.where(VORGANG_ID).is(vorgangDoc.getObjectId(VORGANG_ID)));
-			template.updateMulti(updateQuery, update, VORGANG_COLLECTION);
-		});
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M005_CreateIndexesInVorgang.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M005_CreateIndexesInVorgang.java
deleted file mode 100644
index e8f6ef8e8f7ffd5aed2e8797fa05add59c743365..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M005_CreateIndexesInVorgang.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-
-@ChangeUnit(id = "2022-04-29 12:08:00 OZG-2232", order = "M005", author = "tobr", runAlways = false)
-public class M005_CreateIndexesInVorgang { // NOSONAR
-
-	@Execution
-	public void createIndexes(MongoTemplate template) {
-		createIndexWithoutStatus(template);
-		createIndexWithStatus(template);
-	}
-
-	void createIndexWithStatus(MongoTemplate template) {
-		var createIndexCommand = """
-				{
-				    "createIndexes": "vorgang",
-				    "indexes": [{
-				        "key": {
-				             "inCreation": 1,
-				             "eingangs.zustaendigeStelle.organisationseinheitenId": 1,
-				             "status": 1
-				             "createdAt": 1,
-				        },
-				        "name": "inCreation_orgaId_status_createdAt"
-				    }]
-				} """;
-
-		template.executeCommand(createIndexCommand);
-	}
-
-	void createIndexWithoutStatus(MongoTemplate template) {
-		var createIndexCommand = """
-				{
-				    "createIndexes": "vorgang",
-				    "indexes": [{
-				        "key": {
-				             "inCreation": 1,
-				             "eingangs.zustaendigeStelle.organisationseinheitenId": 1,
-				             "createdAt": 1,
-				        },
-				        "name": "inCreation_orgaId_createdAt"
-				    }]
-				} """;
-
-		template.executeCommand(createIndexCommand);
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M006_MigrateKommentar.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M006_MigrateKommentar.java
deleted file mode 100644
index 45a20e2d23924c6fbada0831cee49c69a360052f..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M006_MigrateKommentar.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
-
-import org.bson.Document;
-import org.bson.types.ObjectId;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-
-@ChangeUnit(id = "2022-05-24 15:45:00 OZG-1523", order = "M006", author = "mkuester", runAlways = true)
-public class M006_MigrateKommentar {// NOSONAR
-
-	private static final String VORGANG_COLLECTION = "vorgang";
-	private static final String VORGANG_KOMMENTAR_FIELD = "kommentars";
-
-	private static final String VORGANG_ID_FIELD = "vorgangId";
-	private static final String ATTACHED_ITEM_CLIENT_FIELD = "client";
-	public static final String ATTACHED_ITEM_CLIENT = "Goofy";
-	private static final String ATTACHED_ITEM_VERSION_FIELD = "version";
-	public static final int ATTACHED_ITEM_VERSION = 0;
-	private static final String ATTACHED_ITEM_ITEM_NAME_FIELD = "itemName";
-	public static final String ATTACHED_ITEM_ITEM_NAME = "Kommentar";
-	private static final String ATTACHED_ITEM_ITEM_FIELD = "item";
-
-	private static final String KOMMENTAR_CREATED_AT_FIELD = "createdAt";
-	private static final String KOMMENTAR_ID_FIELD = "id";
-
-	private static final String VORGANG_ATTACHED_ITEM_COLLECTION = "vorgangAttachedItem";
-
-	private static final String ID = "_id";
-
-	@Execution
-	public void migrationMethod(MongoTemplate template) {
-		var vorgaenge = template.findAll(Document.class, VORGANG_COLLECTION);
-		vorgaenge.forEach(vorgang -> migrateVorgang(template, vorgang));
-	}
-
-	private void migrateVorgang(MongoTemplate template, Document vorgang) {
-		var kommentare = vorgang.getList(VORGANG_KOMMENTAR_FIELD, Document.class);
-		if (Objects.nonNull(kommentare)) {
-			kommentare.forEach(kommentar -> migrateKommentar(template, vorgang.getObjectId(ID), kommentar));
-		}
-	}
-
-	private void migrateKommentar(MongoTemplate template, ObjectId vorgangId, Document kommentar) {
-		List<Document> existing = template.find(new Query(Criteria.where(ATTACHED_ITEM_ITEM_FIELD + "._id").is(kommentar.getString("_id"))),
-				Document.class,
-				VORGANG_ATTACHED_ITEM_COLLECTION);
-		if (existing.isEmpty()) {
-			var kommentarAttachedItem = createVorgangAttachedItem(vorgangId, kommentar);
-
-			template.save(kommentarAttachedItem, VORGANG_ATTACHED_ITEM_COLLECTION);
-		}
-	}
-
-	private Document createVorgangAttachedItem(ObjectId vorgangId, Document kommentar) {
-		var kommentarAsAttachedItem = new Document();
-		kommentarAsAttachedItem.put(VORGANG_ID_FIELD, vorgangId.toHexString());
-		kommentarAsAttachedItem.put(ATTACHED_ITEM_VERSION_FIELD, ATTACHED_ITEM_VERSION);
-		kommentarAsAttachedItem.put(ATTACHED_ITEM_CLIENT_FIELD, ATTACHED_ITEM_CLIENT);
-		kommentarAsAttachedItem.put(ATTACHED_ITEM_ITEM_NAME_FIELD, ATTACHED_ITEM_ITEM_NAME);
-		kommentarAsAttachedItem.put(ATTACHED_ITEM_ITEM_FIELD, buildItem(kommentar));
-
-		return kommentarAsAttachedItem;
-	}
-
-	private Document buildItem(Document kommentar) {
-		var attachedItemKommentar = kommentar;
-		attachedItemKommentar.remove(KOMMENTAR_ID_FIELD);
-		attachedItemKommentar.remove(VORGANG_ID_FIELD);
-		attachedItemKommentar.put(KOMMENTAR_CREATED_AT_FIELD, convertDate(kommentar.get(KOMMENTAR_CREATED_AT_FIELD)));
-
-		return attachedItemKommentar;
-	}
-
-	private String convertDate(Object dateValue) {
-		return ZonedDateTime.ofInstant(((Date) dateValue).toInstant(), ZoneId.of("UTC")).toString();
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommands.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommands.java
deleted file mode 100644
index 0e071164d06c845fa7c3558808b44b46eea22b51..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommands.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import org.bson.Document;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.util.CloseableIterator;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-
-@ChangeUnit(id = "2022-06-30 12:55:00 OZG-2566", order = "M007", author = "mkuester", runAlways = true)
-public class M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommands { // NOSONAR
-
-	static final String COMMAND_COLLECTION = "command";
-
-	static final String CONSIDERED_ORDER = "UPDATE_ATTACHED_ITEM";
-
-	private static final String ORDER_FIELD = "order";
-	private static final String RELATION_ID_FIELD = "relationId";
-	private static final String BODY_OBJECT_FIELD = "bodyObject";
-	private static final String ITEM_FIELD = "item";
-	private static final String ID_FIELD = "id";
-
-	private static final String BODY_OBJECT_ITEM_ID_FIELD = "bodyObject.item.id";
-
-	private MongoTemplate template;
-
-	@Execution
-	public void migrationMethod(MongoTemplate template) {
-		this.template = template;
-
-		try (var commands = getCommands(template)) {
-			commands.stream().forEach(this::migrateCommand);
-		}
-	}
-
-	CloseableIterator<Document> getCommands(MongoTemplate template) {
-		return template.stream(createSearchQuery(), Document.class, COMMAND_COLLECTION);
-	}
-
-	private Query createSearchQuery() {
-		return new Query(Criteria.where(ORDER_FIELD).is(CONSIDERED_ORDER)
-				.andOperator(Criteria.where(BODY_OBJECT_ITEM_ID_FIELD).exists(true)
-						.andOperator(createNeCriteria(RELATION_ID_FIELD, BODY_OBJECT_ITEM_ID_FIELD))));
-	}
-
-	private Criteria createNeCriteria(String field, String fieldToCompare) {
-		return new Criteria() {
-			@Override
-			public Document getCriteriaObject() {
-				Document obj = new Document();
-				obj.put("$where", "this." + field + " != this." + fieldToCompare);
-				return obj;
-			}
-		};
-	}
-
-	private void migrateCommand(Document command) {
-		command.put(RELATION_ID_FIELD, getItemId(command));
-
-		template.save(command, COMMAND_COLLECTION);
-	}
-
-	private Object getItemId(Document command) {
-		var bodyObject = (Document) command.get(BODY_OBJECT_FIELD);
-		var item = (Document) bodyObject.get(ITEM_FIELD);
-
-		return item.get(ID_FIELD);
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M009_RemoveAttachmentContent.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M009_RemoveAttachmentContent.java
deleted file mode 100644
index 9a0b78a6f5fc8e73abb9a90909c48e9dfb66810c..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M009_RemoveAttachmentContent.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.mongodb.core.query.Update;
-import org.springframework.data.mongodb.core.query.UpdateDefinition;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-
-@ChangeUnit(id = "2022-07-06 13:10:00 OZG-2690", order = "M009", author = "jreese", runAlways = true)
-public class M009_RemoveAttachmentContent {// NOSONAR
-
-	private static final String COLLECTION = "vorgang";
-	private static final String CONTENT_FIELD = "content";
-	private static final String ATTACHMENTS_FIELD = "attachments";
-	private static final String EINGANGS_FIELD = "eingangs";
-	private static final String FILES_FIELD = "files";
-	private static final String EINGANGS_ATTACHMENTS_FILES_FIELD = String.format("%s.%s.%s", EINGANGS_FIELD, ATTACHMENTS_FIELD,
-			FILES_FIELD);
-	private static final String EINGANGS_ATTACHMENTS_FILES_CONTENT_FIELD = EINGANGS_ATTACHMENTS_FILES_FIELD + "." + CONTENT_FIELD;
-
-	@Execution
-	public void migrationMethod(MongoTemplate template) {
-		template.updateMulti(findVorgangsAttachmentContentQuery(), unsetContent(), COLLECTION);
-	}
-
-	Query findVorgangsAttachmentContentQuery() {
-		return Query.query(Criteria.where(EINGANGS_ATTACHMENTS_FILES_CONTENT_FIELD).exists(Boolean.TRUE));
-	}
-
-	private UpdateDefinition unsetContent() {
-		return new Update().unset("eingangs.$[].attachments.$[].files.$[].content");
-
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M010_RemoveRepresentationContent.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M010_RemoveRepresentationContent.java
deleted file mode 100644
index 1b49cef328f2a16ef3f3a82ee1beaed6096f4ce8..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M010_RemoveRepresentationContent.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.mongodb.core.query.Update;
-import org.springframework.data.mongodb.core.query.UpdateDefinition;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-
-@ChangeUnit(id = "2022-07-08 11:20:00 OZG-2690", order = "M010", author = "jreese", runAlways = true)
-public class M010_RemoveRepresentationContent {// NOSONAR
-
-	private static final String COLLECTION = "vorgang";
-	private static final String CONTENT_FIELD = "content";
-	private static final String REPRESENTATIONS_FIELD = "representations";
-	private static final String EINGANGS_FIELD = "eingangs";
-	private static final String EINGANGS_REPRESENTATIONS_FIELD = EINGANGS_FIELD + "." + REPRESENTATIONS_FIELD;
-	private static final String EINGANGS_REPRESENTATIONS_CONTENT_FIELD = EINGANGS_REPRESENTATIONS_FIELD + "." + CONTENT_FIELD;
-
-	@Execution
-	public void migrationMethod(MongoTemplate template) {
-		template.updateMulti(findVorgangsAttachmentContentQuery(), unsetContent(), COLLECTION);
-	}
-
-	Query findVorgangsAttachmentContentQuery() {
-		return Query.query(Criteria.where(EINGANGS_REPRESENTATIONS_CONTENT_FIELD).exists(Boolean.TRUE));
-	}
-
-	private UpdateDefinition unsetContent() {
-		return new Update().unset("eingangs.$[].representations.$[].content");
-
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M011_FixTypeAlias.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M011_FixTypeAlias.java
deleted file mode 100644
index a99baf803ee3d2dea60f57efa55b215547f20cc0..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M011_FixTypeAlias.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.springframework.data.mongodb.core.query.Criteria.where;
-import static org.springframework.data.mongodb.core.query.Query.query;
-
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.mongodb.core.query.Update;
-import org.springframework.data.mongodb.core.query.UpdateDefinition;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-
-@ChangeUnit(id = "2022-08-01 15:23:00 OZG-2750", order = "M011", author = "tobr", runAlways = true)
-public class M011_FixTypeAlias {// NOSONAR
-
-	static final String TYPEKEY_ATTRIBUTE = "_class";
-
-	static final String COMMAND_TYPE_ALIAS = "Command";
-	static final String VORGANG_TYPE_ALIAS = "Vorgang";
-	static final String ITEM_TYPE_ALIAS = "VorgangAttachedItem";
-	static final String ATTRIBUTE_TYPE_ALIAS = "ClientAttribute";
-
-	static final String CLIENT_NAME_NACHRICHTEN_MANAGER = "KopNachrichtenManager";
-	static final String CLIENT_NAME_ALLGEMEINES_FV = "Goofy";
-
-	static final String ATTRIBUTES_FIELD_PATH_TEMPLATE = "clientAttributes.%s.%s._class";
-
-	@Execution
-	public void doMigration(MongoTemplate template) {
-		migrateCommands(template);
-		migrateVorgangs(template);
-		migrateVorgangAttachedItems(template);
-		migrateClientAttributes(template);
-	}
-
-	void migrateCommands(MongoTemplate template) {
-		template.updateMulti(buildQuery(), buildUpdate(COMMAND_TYPE_ALIAS), "command");
-	}
-
-	void migrateVorgangs(MongoTemplate template) {
-		template.updateMulti(buildQuery(), buildUpdate(VORGANG_TYPE_ALIAS), "vorgang");
-	}
-
-	void migrateVorgangAttachedItems(MongoTemplate template) {
-		template.updateMulti(buildQuery(), buildUpdate(ITEM_TYPE_ALIAS), "vorgangAttachedItem");
-	}
-
-	private UpdateDefinition buildUpdate(String typeAlias) {
-		return new Update().set(TYPEKEY_ATTRIBUTE, typeAlias);
-	}
-
-	Query buildQuery() {
-		return query(where(TYPEKEY_ATTRIBUTE).regex("pluto"));
-	}
-
-	void migrateClientAttributes(MongoTemplate template) {
-		migrateClientAttribute(CLIENT_NAME_NACHRICHTEN_MANAGER, "hasPostfachNachricht", template);
-		migrateClientAttribute(CLIENT_NAME_NACHRICHTEN_MANAGER, "hasNewPostfachNachricht", template);
-		migrateClientAttribute(CLIENT_NAME_ALLGEMEINES_FV, "nextWiedervorlageFrist", template);
-	}
-
-	void migrateClientAttribute(String clientName, String attributeName, MongoTemplate template) {
-		var fieldPath = String.format(ATTRIBUTES_FIELD_PATH_TEMPLATE, clientName, attributeName);
-
-		template.updateMulti(buildQueryForAttributes(fieldPath), buildUpdateForAttributes(fieldPath), "vorgang");
-	}
-
-	private UpdateDefinition buildUpdateForAttributes(String fieldPath) {
-		return new Update().set(fieldPath, ATTRIBUTE_TYPE_ALIAS);
-	}
-
-	Query buildQueryForAttributes(String fieldPath) {
-		return query(where(fieldPath).regex("pluto"));
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M012_MigrationUserId.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M012_MigrationUserId.java
deleted file mode 100644
index b2c2676270a0e16df307b0f43cf27b114fbd1650..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M012_MigrationUserId.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.Objects;
-import java.util.Optional;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-
-import org.bson.Document;
-import org.springframework.core.env.Environment;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.client.HttpClientErrorException;
-import org.springframework.web.client.RestTemplate;
-
-import io.mongock.api.annotations.ChangeUnit;
-import io.mongock.api.annotations.Execution;
-import io.mongock.api.annotations.RollbackExecution;
-import lombok.extern.log4j.Log4j2;
-
-@Log4j2
-@ChangeUnit(id = "2022-09-06 10:45:00 OZG-2737", order = "M012", author = "maku", runAlways = true)
-public class M012_MigrationUserId {// NOSONAR
-
-	private static final String KOP_USERMANAGER_URL_KEY = "kop.usermanager.url";
-	private static final String SYSTEM_USER_PREFIX = "system";
-
-	static final String COLLECTION_VORGANG_NAME = "vorgang";
-	static final String ASSIGNED_TO_FIELD = "assignedTo";
-
-	static final String COLLECTION_COMMAND_NAME = "command";
-
-	static final String CREATED_BY_FIELD = "createdBy";
-
-	static final String COLLECTION_VORGANG_ATTACHED_ITEM_NAME = "vorgangAttachedItem";
-	static final String VORGANG_ATTACHED_ITEM_ITEM_FIELD = "item";
-	static final String VORGANG_ATTACHED_ITEM_CREATED_BY_FIELD = VORGANG_ATTACHED_ITEM_ITEM_FIELD + "." + CREATED_BY_FIELD;
-
-	static final Pattern UUID_PATTERN = Pattern.compile("-");
-
-	private MongoTemplate template;
-
-	private RestTemplate restTemplate = new RestTemplate();
-
-	private String userManagerUrlTemplate;
-
-	@Execution
-	public void doMigration(MongoTemplate template, Environment environment) {
-		var userManagerUrl = environment.getProperty(KOP_USERMANAGER_URL_KEY);
-
-		if (Objects.nonNull(userManagerUrl)) {
-			this.template = template;
-			this.userManagerUrlTemplate = userManagerUrl + "/%s";
-
-			migrate();
-		} else {
-			logUrlIsNotConfigured();
-		}
-	}
-
-	private void migrate() {
-		migrateAssignedTo();
-		migrateCommandCreatedBy();
-		migrateVorgangAttachedItemCreatedBy();
-	}
-
-	void migrateAssignedTo() {
-		findVorgangWithFilledAssignedTo().forEach(this::updateAssignedTo);
-	}
-
-	private Stream<Document> findVorgangWithFilledAssignedTo() {
-		return template.stream(createFindVorgangWithFilledAssignedToQuery(), Document.class, COLLECTION_VORGANG_NAME).stream();
-	}
-
-	Query createFindVorgangWithFilledAssignedToQuery() {
-		return Query.query(Criteria.where(ASSIGNED_TO_FIELD).exists(Boolean.TRUE)
-				.andOperator(Criteria.where(ASSIGNED_TO_FIELD).regex(UUID_PATTERN)));
-	}
-
-	private void updateAssignedTo(Document vorgang) {
-		getNewInternalId(vorgang.getString(ASSIGNED_TO_FIELD)).ifPresent(newId -> doUpdateAssignedTo(vorgang, newId));
-	}
-
-	private void doUpdateAssignedTo(Document vorgang, String newId) {
-		vorgang.put(ASSIGNED_TO_FIELD, newId);
-
-		template.save(vorgang, COLLECTION_VORGANG_NAME);
-	}
-
-	void migrateCommandCreatedBy() {
-		findCommandWithCreateBy().forEach(this::updateCreatedBy);
-	}
-
-	private Stream<Document> findCommandWithCreateBy() {
-		return template.stream(createFindCommandWithCreatedByQuery(), Document.class, COLLECTION_COMMAND_NAME).stream();
-	}
-
-	Query createFindCommandWithCreatedByQuery() {
-		return Query.query(Criteria.where(CREATED_BY_FIELD).exists(Boolean.TRUE)
-				.andOperator(Criteria.where(CREATED_BY_FIELD).regex(UUID_PATTERN)));
-	}
-
-	private void updateCreatedBy(Document command) {
-		getNewInternalId(command.getString(CREATED_BY_FIELD)).ifPresent(newId -> doUpdateCreatedBy(command, newId));
-	}
-
-	private void doUpdateCreatedBy(Document command, String newId) {
-		command.put(CREATED_BY_FIELD, newId);
-
-		template.save(command, COLLECTION_COMMAND_NAME);
-	}
-
-	void migrateVorgangAttachedItemCreatedBy() {
-		findVorgangAttachedItemWithCreatedBy().forEach(this::updateVorgangAttachedItemCreatedBy);
-	}
-
-	private Stream<Document> findVorgangAttachedItemWithCreatedBy() {
-		return template.stream(createFindVorgangAttachedItemdWithCreatedByQuery(), Document.class, COLLECTION_VORGANG_ATTACHED_ITEM_NAME).stream();
-	}
-
-	Query createFindVorgangAttachedItemdWithCreatedByQuery() {
-		return Query.query(Criteria.where(VORGANG_ATTACHED_ITEM_CREATED_BY_FIELD).exists(Boolean.TRUE)
-				.andOperator(Criteria.where(VORGANG_ATTACHED_ITEM_CREATED_BY_FIELD).regex(UUID_PATTERN)));
-	}
-
-	private void updateVorgangAttachedItemCreatedBy(Document vorgangAttachedItem) {
-		var itemCreatedBy = ((Document) vorgangAttachedItem.get(VORGANG_ATTACHED_ITEM_ITEM_FIELD)).getString(CREATED_BY_FIELD);
-
-		getNewInternalId(itemCreatedBy).ifPresent(newId -> doUpdateVorgangAttachedItemCreatedBy(vorgangAttachedItem, newId));
-	}
-
-	private void doUpdateVorgangAttachedItemCreatedBy(Document vorgangAttachedItem, String newId) {
-		var item = (Document) vorgangAttachedItem.get(VORGANG_ATTACHED_ITEM_ITEM_FIELD);
-		item.put(CREATED_BY_FIELD, newId);
-		vorgangAttachedItem.put(VORGANG_ATTACHED_ITEM_ITEM_FIELD, item);
-
-		template.save(vorgangAttachedItem, COLLECTION_VORGANG_ATTACHED_ITEM_NAME);
-	}
-
-	private Optional<String> getNewInternalId(String currentId) {
-		if (currentId.startsWith(SYSTEM_USER_PREFIX)) {
-			return Optional.empty();
-		}
-
-		try {
-			return Optional.of(getInternalId(currentId));
-		} catch (HttpClientErrorException e) {
-			if (e.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
-				logNotFoundException(e, currentId);
-			} else {
-				logHttpException(e, currentId);
-			}
-			return Optional.empty();
-
-		} catch (Exception e) {
-			logException(e, currentId);
-			return Optional.empty();
-		}
-	}
-
-	String getInternalId(String currentId) {
-		return restTemplate.getForEntity(String.format(userManagerUrlTemplate, currentId), String.class).getBody();
-	}
-
-	void logNotFoundException(HttpClientErrorException e, String currentId) {
-		LOG.info(String.format("No matching user found by id %s- proceed without migration.", currentId), e);
-	}
-
-	void logHttpException(HttpClientErrorException e, String currentId) {
-		LOG.warn(String.format("Http Error %s while fetching internal id for external id %s. Proceeding with next user id",
-				e.getStatusCode().name(), currentId), e);
-	}
-
-	void logException(Exception e, String currentId) {
-		LOG.error(String.format("Error while fetching internal id for external id %s. Proceeding with next user id", currentId), e);
-	}
-
-	void logUrlIsNotConfigured() {
-		LOG.warn("UserManager url is not configured - user migration not started.");
-	}
-
-	@RollbackExecution
-	public void rollback() {
-		// kein rollback implementiert
-	}
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepositoryImpl.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepositoryImpl.java
deleted file mode 100644
index 093f964e9fbfb9b882190a93d950ff1d71cf6c9d..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepositoryImpl.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.search;
-
-import static de.itvsh.ozg.pluto.common.search.IndexedVorgang.*;
-import static org.elasticsearch.index.query.AbstractQueryBuilder.*;
-import static org.elasticsearch.index.query.QueryBuilders.*;
-
-import java.util.Arrays;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.elasticsearch.index.query.BoolQueryBuilder;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
-import org.springframework.data.elasticsearch.core.SearchHit;
-import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
-import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
-import org.springframework.data.support.PageableExecutionUtils;
-import org.springframework.stereotype.Repository;
-
-import de.itvsh.ozg.pluto.vorgang.VorgangHeader;
-
-@Repository
-class SearchVorgangCustomRepositoryImpl implements SearchVorgangCustomRepostitory {
-	private static final String JOIN_AND = " AND ";
-	private static final String WILDCARD_PATTERN = "(*%s*)";
-	private static final String KEYWORD = ".keyword";
-	private static final float HALF_BOOST = 0.5f;
-	private static final float DOUBLE_BOOST = 2f;
-
-	static final Map<String, Float> FIELD_MAP = Map.of(
-			FIELD_NAME, HALF_BOOST,
-			FIELD_VORGANG_NUMMER, DOUBLE_BOOST,
-			FIELD_AKTENZEICHEN, DOUBLE_BOOST,
-			FIELD_ANTRAGSTELLER_NAME, DEFAULT_BOOST,
-			FIELD_ANTRAGSTELLTER_VORNAME, DEFAULT_BOOST);
-
-	@Autowired
-	private ElasticsearchOperations elasticsearchOperations;
-
-	@Autowired
-	private IndexedVorgangMapper mapper;
-
-	@Override
-	public Page<VorgangHeader> searchBy(SearchRequest request) {
-		var pageable = PageRequest.of(request.getOffSet(), request.getLimit());
-		var searchQuery = createQuery(request, pageable);
-
-		var result = elasticsearchOperations.search(searchQuery, IndexedVorgang.class);
-		var mappedResult = result.get().map(SearchHit::getContent).map(mapper::toVorgangHeader).toList();
-
-		return PageableExecutionUtils.getPage(mappedResult, pageable, result::getTotalHits);
-	}
-
-	NativeSearchQuery createQuery(SearchRequest request, PageRequest pageable) {
-		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
-
-		setFilter(request, searchQueryBuilder);
-
-		var queryString = Arrays.stream(request.getQuery().strip().split(StringUtils.SPACE)).map(
-				WILDCARD_PATTERN::formatted).collect(Collectors.joining(JOIN_AND));
-
-		searchQueryBuilder.withQuery(queryStringQuery(queryString).fields(SearchVorgangCustomRepositoryImpl.FIELD_MAP));
-
-		return searchQueryBuilder.withPageable(pageable).build();
-	}
-
-	private void setFilter(SearchRequest request, NativeSearchQueryBuilder searchQueryBuilder) {
-		var query = boolQuery();
-
-		if (request.isFilterByOrganisationseinheitIds()) {
-			addByOrganisationseinheitIdsFilters(request, query);
-		} else if (CollectionUtils.isNotEmpty(request.getStatus())) {
-			query.must(termsQuery(FIELD_STATUS + KEYWORD, request.getStatus()));
-		}
-
-		searchQueryBuilder.withFilter(query);
-	}
-
-	private void addByOrganisationseinheitIdsFilters(SearchRequest request, BoolQueryBuilder query) {
-		query.must(termsQuery(FIELD_ORGANISATIONSEINHEITEN_ID, request.getOrganisationseinheitIds()));
-
-		if (CollectionUtils.isNotEmpty(request.getStatus())) {
-			query.must(termsQuery(FIELD_STATUS + KEYWORD, request.getStatus()));
-		}
-
-		if (StringUtils.isNotEmpty(request.getAssignedTo())) {
-			query.must(termsQuery(FIELD_ASSIGNED_TO + KEYWORD, request.getAssignedTo()));
-		}
-	}
-}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/security/PolicyRepository.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/security/PolicyRepository.java
deleted file mode 100644
index 7a63c573f7ea12f77fed22d00db857a6f840b3b1..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/security/PolicyRepository.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.security;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-import org.bson.Document;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.aggregation.Aggregation;
-import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.stereotype.Repository;
-
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-
-@Repository
-class PolicyRepository {
-
-	private static final String VORANG_ID_AS_OBJECT_ID_FIELD = """
-			{"$addFields" : {"vorgangObjecId" : {"$toObjectId": "$vorgangId"}}}
-			""";
-	private static final String VORANG_ID_FROM_FILE_AS_OBJECT_ID_FIELD = """
-			{"$addFields" : {"vorgangObjecId" : {"$toObjectId": "$metadata.vorgangId"}}}
-			""";
-	private static final AggregationOperation ADD_VORGANG_OBJECT_ID_FIELD = context -> org.bson.Document.parse(VORANG_ID_AS_OBJECT_ID_FIELD);
-
-	private static final AggregationOperation ADD_VORGANG_FROM_FILE = context -> org.bson.Document.parse(VORANG_ID_FROM_FILE_AS_OBJECT_ID_FIELD);
-
-	@Autowired
-	private MongoTemplate template;
-
-	public boolean existsByCommandId(String commandId, Collection<String> organisationEinheitenIds) {
-		return evaluateAggregation(buildAggregation(commandId, organisationEinheitenIds, ADD_VORGANG_OBJECT_ID_FIELD), Command.class);
-	}
-
-	public boolean existsByVorgangAttachedItem(String vorgangAttachedItemId, Collection<String> organisationEinheitenIds) {
-		return evaluateAggregation(buildAggregation(vorgangAttachedItemId, organisationEinheitenIds, ADD_VORGANG_OBJECT_ID_FIELD),
-				VorgangAttachedItem.class);
-	}
-
-	public boolean existsByFileId(String fileId, Collection<String> organisationEinheitenIds) {
-		return evaluateAggregation(buildAggregation(fileId, organisationEinheitenIds, ADD_VORGANG_FROM_FILE), Document.class, "fs.files");
-	}
-
-	private Aggregation buildAggregation(String objectId, Collection<String> organisationEinheitenIds, AggregationOperation operation) {
-		return Aggregation.newAggregation(Arrays.asList(
-				matchId(objectId),
-				operation,
-				lookupVorgang(),
-				matchOrganisationEinheitenId(organisationEinheitenIds)));
-	}
-
-	private boolean evaluateAggregation(Aggregation aggregation, Class<?> givenCollectionClass) {
-		var foundResult = template.aggregate(aggregation, givenCollectionClass, givenCollectionClass).getMappedResults();
-
-		return !foundResult.isEmpty();
-	}
-
-	private boolean evaluateAggregation(Aggregation aggregation, Class<?> givenCollectionClass, String collectionName) {
-		var foundResult = template.aggregate(aggregation, collectionName, givenCollectionClass).getMappedResults();
-
-		return !foundResult.isEmpty();
-	}
-
-	private AggregationOperation matchId(String id) {
-		return Aggregation.match(new Criteria(Vorgang.MONGODB_FIELDNAME_ID).is(id));
-	}
-
-	private AggregationOperation lookupVorgang() {
-		return Aggregation.lookup(Vorgang.COLLECTION_NAME, "vorgangObjecId", "_id", "vorgang");
-	}
-
-	private AggregationOperation matchOrganisationEinheitenId(Collection<String> organisationEinheitenIds) {
-		return Aggregation.match(Criteria.where("vorgang." + Vorgang.FIELD_ORGANISATIONSEINHEIT).in(organisationEinheitenIds));
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangEventListener.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangEventListener.java
deleted file mode 100644
index e1d9b99b66741e00fc46c4576d1325e5e407cd79..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangEventListener.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.vorgang;
-
-import java.util.function.Predicate;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Component;
-
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEvent;
-import de.itvsh.ozg.pluto.command.Order;
-import de.itvsh.ozg.pluto.vorgang.redirect.VorgangForwardFailedEvent;
-import de.itvsh.ozg.pluto.vorgang.redirect.VorgangRedirectedEvent;
-
-@Component
-public class VorgangEventListener {
-
-	private static final String IS_ASSIGN_COMMAND_CONDITION = "{T(de.itvsh.ozg.pluto.vorgang.VorgangEventListener).IS_ASSIGN_COMMAND.test(event.getSource())}";
-
-	public static final Predicate<Command> IS_ASSIGN_COMMAND = command -> Order.ASSIGN_USER.isMeant(command.getOrder());
-
-	@Autowired
-	private VorgangService service;
-
-	@EventListener
-	public void updateStatus(VorgangRedirectedEvent event) {
-		service.setStatusToWeitergeleitet(event.getSource());
-	}
-
-	@EventListener
-	public void updateStatus(VorgangForwardFailedEvent event) {
-		service.setStatusToInBearbeitung(event.getSource(), event.getVorgangId());
-	}
-
-	@EventListener(condition = IS_ASSIGN_COMMAND_CONDITION)
-	public void assignToUser(CommandCreatedEvent event) {
-		service.assignToUser(event.getSource());
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/main/resources/application-dev.yml b/pluto-server/src/main/resources/application-dev.yml
deleted file mode 100644
index 3ca673cd6b6c71e4f51dac4d44d9bb0eb297e07b..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/resources/application-dev.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-spring:
-  mail:
-    properties:
-      "[mail.smtp.starttls.enable]": true
-
-pluto:
-  redirect:
-    mail-from: ea@ozg-sh.de
-kop:
-  notification:
-    mail-from: ea@ozg-sh.de
diff --git a/pluto-server/src/main/resources/application-e2e.yml b/pluto-server/src/main/resources/application-e2e.yml
deleted file mode 100644
index f7b0b5a5f8a6a4bf7a5ca4b64d4175c24019a341..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/resources/application-e2e.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-kop:
-  osi:
-    postfach:
-      scheduler:
-        enabled: false
-      proxyapi:
-        url:  mockedForE2E
-        key:  mockedForE2E
-        realm: mockedForE2E
-        
-mongock:
-  enabled: false
\ No newline at end of file
diff --git a/pluto-server/src/main/resources/application-local.yml b/pluto-server/src/main/resources/application-local.yml
deleted file mode 100644
index d5fe0c6c22cb73d3941a8a439a7f3b1371801539..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/resources/application-local.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-logging:
-  level:
-    root: WARN,
-    "[de.itvsh]": INFO
-    "[org.elasticsearch.client]": WARN
-  config: classpath:log4j2-local.xml
-
-server:
-  port: 8085
-
-management:
-  server.port: 8083
-  health:
-    elasticsearch:
-      enabled: false
-  endpoint:
-    health:
-      show-details: always
-
-spring:
-  data:
-    mongodb:
-      database: pluto-local
-  mail:
-    properties:
-      "[mail.smtp.starttls.enable]": true
-  elasticsearch:
-    uris: http://localhost:9200
-
-pluto:
-  redirect:
-    mail-from: ea@ozg-sh.de
-
-kop:
-  osi:
-    postfach:
-      scheduler:
-        enabled: false
-        fixedDelay: 10000
-      proxyapi:
-        url: https://postfach.serviceportal-stage.schleswig-holstein.de/ApiProxy/V1/Message
-        realm: urn:osp:names:realm:stage:sh
-  elasticsearch:
-    initEnabled: true
-    index: test-index
-  notification:
-    mail-from: ea@ozg-sh.de
-  usermanager:
-    url: http://localhost:9092/migration/user
-
-aktenzeichen: de.itvsh.ozg.pluto.vorgang.AktenzeichenProviderEA
-
-mongock:
-  transactionEnabled: false
diff --git a/pluto-server/src/main/resources/application-prod.yml b/pluto-server/src/main/resources/application-prod.yml
deleted file mode 100644
index 68af29d298eff1162f79b6f4abc503ab73db158c..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/resources/application-prod.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-spring:
-  mail:
-    port: 25
-
-kop:
-  production: true
diff --git a/pluto-server/src/main/resources/application-test.yml b/pluto-server/src/main/resources/application-test.yml
deleted file mode 100644
index a7bacd503b63d3b1a116cc1acf0ce1e6df19d314..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/resources/application-test.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-spring:
-  mail:
-    properties:
-      "[mail.smtp.starttls.enable]": true
-
-pluto:
-  redirect:
-    mail-from: ea@ozg-sh.de
diff --git a/pluto-server/src/main/resources/application-withdevdb.yml b/pluto-server/src/main/resources/application-withdevdb.yml
deleted file mode 100644
index 30ce9f0380c1b7e1d275a0c1804b47b17e57fd58..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/resources/application-withdevdb.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-spring:
-  data:
-    mongodb:
-      database: pluto-database
diff --git a/pluto-server/src/main/resources/banner.txt b/pluto-server/src/main/resources/banner.txt
deleted file mode 100644
index 1df2e8adffe5764e65d8f17b85b4d2ad476b7b6c..0000000000000000000000000000000000000000
--- a/pluto-server/src/main/resources/banner.txt
+++ /dev/null
@@ -1,5 +0,0 @@
- ___  _     _   _  _____   ___  
-| _ \| |   | | | ||_   _| / _ \ 
-|  _/| |__ | |_| |  | |  | (_) |
-|_|  |____| \___/   |_|   \___/ 
-${spring-boot.version}		${application.version}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemRepositoryITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemRepositoryITCase.java
deleted file mode 100644
index 483c50b33dc6827c6c8e88252913acbe51df0e85..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemRepositoryITCase.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.attached_item;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.Map;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoOperations;
-
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-
-@DataITCase
-class VorgangAttachedItemRepositoryITCase {
-
-	@Autowired
-	private VorgangAttachedItemRepository repository;
-	@Autowired
-	private MongoOperations mongoOperations;
-
-	private VorgangAttachedItem persistedItem;
-
-	@BeforeEach
-	void prepareDatabase() {
-		mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
-	}
-
-	@DisplayName("Find by")
-	@Nested
-	class TestFindBy {
-
-		@BeforeEach
-		void init() {
-			persistedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).build());
-		}
-
-		@Nested
-		class VorgangIdAndClientAndItemName {
-
-			@Test
-			void shouldReturnResult() {
-				var loadedItems = repository.findByVorgangIdAndClientAndItemName(VorgangTestFactory.ID, VorgangAttachedItemTestFactory.CLIENT,
-						VorgangAttachedItemTestFactory.ITEM_NAME);
-
-				assertThat(loadedItems).hasSize(1);
-			}
-		}
-
-		@Nested
-		class VorgangIdAndClient {
-
-			@Test
-			void shouldReturnResult() {
-				var loadedItems = repository.findByVorgangIdAndClient(VorgangTestFactory.ID, VorgangAttachedItemTestFactory.CLIENT);
-
-				assertThat(loadedItems).hasSize(1);
-			}
-		}
-
-		@Nested
-		class VorgangIdAndItemName {
-
-			@Test
-			void shouldReturnResult() {
-				var loadedItems = repository.findByVorgangIdAndItemName(VorgangTestFactory.ID, VorgangAttachedItemTestFactory.ITEM_NAME);
-
-				assertThat(loadedItems).hasSize(1);
-			}
-		}
-
-		@Nested
-		class VorgangId {
-
-			@Test
-			void shouldReturnResult() {
-				var loadedItems = repository.findByVorgangId(VorgangTestFactory.ID);
-
-				assertThat(loadedItems).hasSize(1);
-			}
-		}
-	}
-
-	@Nested
-	class TestPatch {
-
-		@BeforeEach
-		void prepareDatabase() {
-			mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
-
-			persistedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).build());
-		}
-
-		@Test
-		void shouldUpdateFieldValue() {
-			repository.patch(persistedItem.getId(), persistedItem.getVersion(), buildPatchMap());
-
-			var loaded = findVorgangAttachedItem();
-			assertThat(loaded).isNotNull();
-			assertThat(loaded.getItem()).containsOnly(
-					entry("dontTouch", 600),
-					entry(VorgangAttachedItemTestFactory.ITEM_FIELD_NAME, VorgangAttachedItemTestFactory.ITEM_FIELD_STRING_VALUE));
-		}
-
-		@Test
-		void shouldIncreaseVersion() {
-			repository.patch(persistedItem.getId(), persistedItem.getVersion(), buildPatchMap());
-
-			var loaded = findVorgangAttachedItem();
-			assertThat(loaded).isNotNull();
-			assertThat(loaded.getVersion()).isEqualTo(persistedItem.getVersion() + 1);
-		}
-
-		@Test
-		void shouldNotUpdateOnWrongVersion() {
-			repository.patch(persistedItem.getId(), 42, buildPatchMap());
-
-			var loaded = findVorgangAttachedItem();
-
-			assertThat(loaded).usingRecursiveComparison().isEqualTo(persistedItem);
-		}
-
-		private Map<String, Object> buildPatchMap() {
-			return Map.of("dontTouch", 600);
-		}
-	}
-
-	private VorgangAttachedItem findVorgangAttachedItem() {
-		return mongoOperations.findById(persistedItem.getId(), VorgangAttachedItem.class);
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandRepositoryITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandRepositoryITCase.java
deleted file mode 100644
index cad79be642df5cec1e7c5e294b04bca11280b723..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandRepositoryITCase.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.command;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.Collections;
-import java.util.Optional;
-import java.util.UUID;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoOperations;
-
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-
-@DataITCase
-class CommandRepositoryITCase {
-
-	@Autowired
-	private CommandRepository repository;
-	@Autowired
-	private MongoOperations mongoOperations;
-
-	@BeforeEach
-	void clearDB() {
-		mongoOperations.dropCollection(Command.class);
-	}
-
-	@Nested
-	class TestSave {
-
-		@Test
-		void shouldSave() {
-			repository.save(CommandTestFactory.create());
-
-			verifyCommandExists(CommandTestFactory.ID);
-		}
-
-		@Test
-		void shouldGenerateIdOnSave() {
-			Command command = repository.save(CommandTestFactory.createBuilder().id(null).build());
-
-			verifyCommandExists(command.getId());
-		}
-
-		private void verifyCommandExists(String id) {
-			Command command = mongoOperations.findById(id, Command.class);
-
-			assertThat(command).isNotNull();
-			assertThat(command.getId()).isEqualTo(id);
-		}
-	}
-
-	@Nested
-	class TestGetById {
-
-		private final String ADDITIONAL_COMMAND_ID = UUID.randomUUID().toString();
-
-		@BeforeEach
-		void persistAdditionalCommandToVorgang() {
-			mongoOperations.save(CommandTestFactory.create());
-		}
-
-		@Test
-		void shouldFindCommand() {
-			verifyCommandExists(CommandTestFactory.ID);
-		}
-
-		@Test
-		void shouldFindAdditionalCommand() {
-			mongoOperations.save(CommandTestFactory.createBuilder().id(ADDITIONAL_COMMAND_ID).build());
-
-			verifyCommandExists(ADDITIONAL_COMMAND_ID);
-		}
-
-		private void verifyCommandExists(String id) {
-			Optional<Command> command = repository.getById(id);
-
-			assertThat(command).isPresent();
-			assertThat(command.get().getId()).isEqualTo(id);
-		}
-	}
-
-	@Nested
-	class TestUpdateCommandStatus {
-
-		@BeforeEach
-		void persistVorgangWithCommand() {
-			repository.save(CommandTestFactory.create());
-		}
-
-		@ParameterizedTest
-		@EnumSource(CommandStatus.class)
-		void shouldUpdateCommandStatus(CommandStatus status) {
-			repository.updateCommandStatus(CommandTestFactory.ID, status);
-
-			Optional<Command> command = repository.getById(CommandTestFactory.ID);
-
-			assertThat(command).isPresent();
-			assertThat(command.get().getStatus()).isEqualTo(status);
-		}
-	}
-
-	@Nested
-	class TestUpdateCommandStatusAndVersion {
-
-		@BeforeEach
-		void persistVorgangWithCommand() {
-			repository.save(CommandTestFactory.create());
-		}
-
-		@ParameterizedTest
-		@EnumSource(CommandStatus.class)
-		void shouldUpdateCommandStatus(CommandStatus status) {
-			repository.updateCommandStatusAndVersion(CommandTestFactory.ID, status, 78L);
-
-			Optional<Command> command = repository.getById(CommandTestFactory.ID);
-
-			assertThat(command).isPresent();
-			assertThat(command.get().getRelationVersion()).isEqualTo(78L);
-			assertThat(command.get().getStatus()).isEqualTo(status);
-		}
-	}
-
-	@Nested
-	class TestGetPendingCommands {
-
-		@BeforeEach
-		void persistCommand() {
-			repository.save(CommandTestFactory.create());
-			repository.save(CommandTestFactory.createBuilder().id(null).vorgangId(VorgangTestFactory.ID).status(CommandStatus.FINISHED).build());
-		}
-
-		@Test
-		void shouldReturnPendingCommand() {
-			var result = repository.getPendingCommands(VorgangTestFactory.ID);
-
-			assertThat(result).hasSize(1);
-			assertThat(result.get(0).getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
-			assertThat(result.get(0).getStatus()).isEqualTo(CommandStatus.PENDING);
-		}
-	}
-
-	@Nested
-	class TestFindCommands {
-
-		@Test
-		void shouldReturnCommandByVorgang() {
-			repository.save(CommandTestFactory.create());
-
-			var commands = repository.findCommands(VorgangTestFactory.ID, Collections.emptyList(), Optional.empty());
-
-			assertThat(commands).hasSize(1);
-		}
-
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M000_AddOrganisationIdMigrationITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M000_AddOrganisationIdMigrationITCase.java
deleted file mode 100644
index 133841061a3ab22c1ad8d21e61c3c23cf462235d..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M000_AddOrganisationIdMigrationITCase.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.List;
-
-import org.bson.Document;
-import org.bson.types.ObjectId;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M000_AddOrganisationIdMigrationITCase {
-
-	private final M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing migrator = new M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing();
-
-	@Autowired
-	private MongoTemplate template;
-
-	private Document vorgangToMigrate;
-	private Document vorgangNotToMigrate;
-
-	@BeforeEach
-	public void init() {
-		template.dropCollection(MigrationDbTestUtils.VORGANG_COLLECTION);
-
-		vorgangNotToMigrate = template.save(MigrationVorgangTestFactory.create(), MigrationDbTestUtils.VORGANG_COLLECTION);
-		vorgangToMigrate = template.save(createVorgangToMigrate(), MigrationDbTestUtils.VORGANG_COLLECTION);
-	}
-
-	private Document createVorgangToMigrate() {
-		var eingangHeader = MigrationEingangHeaderTestFactory.create();
-		eingangHeader.put(MigrationEingangHeaderTestFactory.FIELD_CUSTOMER_ID,
-				M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing.CUSTOMER_ID);
-		eingangHeader.put(MigrationEingangHeaderTestFactory.FIELD_FORM_ID,
-				M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing.FORM_ID_BAULASTENAUSKUNFT);
-
-		var eingang = MigrationEingangTestFactory.create();
-		eingang.put(MigrationEingangTestFactory.FIELD_HEADER, eingangHeader);
-		eingang.remove(MigrationEingangTestFactory.FIELD_ZUSTAENDIDGESTELLE);
-
-		var vorgang = MigrationVorgangTestFactory.create();
-		vorgang.put(MigrationVorgangTestFactory.FIELD_EINGANGS, List.of(eingang));
-
-		return vorgang;
-	}
-
-	@Test
-	void shouldMigrate() {
-		migrator.migrationMethod(template);
-
-		var organisationseinheitenId = getOrganisationeinheitenId(getVorgang(MigrationTestUtils.getObjectId(vorgangToMigrate)));
-		assertThat(organisationseinheitenId).isEqualTo(M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing.ORGANISATIONSEINHEITEN_ID);
-	}
-
-	@Test
-	void shoulNotMigrate() {
-		migrator.migrationMethod(template);
-
-		var organisationseinheitenId = getOrganisationeinheitenId(getVorgang(MigrationTestUtils.getObjectId(vorgangNotToMigrate)));
-		assertThat(organisationseinheitenId).isNotEqualTo(M000_AddOrganisationseinheitenIdForNordfrieslandWhenMissing.ORGANISATIONSEINHEITEN_ID);
-	}
-
-	private Object getOrganisationeinheitenId(Document vorgang) {
-		return getZustaendigeStelle(vorgang).get(MigrationZustaendigeStelleTestFactory.FIELD_ORGANISATIONSEINHEITEN_ID);
-	}
-
-	private Document getZustaendigeStelle(Document vorgang) {
-		return (Document) MigrationTestUtils.getList(vorgang, MigrationVorgangTestFactory.FIELD_EINGANGS).get(0)
-				.get(MigrationEingangTestFactory.FIELD_ZUSTAENDIDGESTELLE);
-	}
-
-	private Document getVorgang(ObjectId vorgangId) {
-		return MigrationDbTestUtils.getVorgang(template, vorgangId);
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFsITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFsITCase.java
deleted file mode 100644
index 6b0dd6ed0853cdb6dd6d8b59a246ff6f7b09e864..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M001_MigrateMailServiceAttachmentsToGridFsITCase.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-import org.bson.Document;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Spy;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.gridfs.GridFsTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M001_MigrateMailServiceAttachmentsToGridFsITCase {
-
-	@Spy
-	private M001_MigrateMailServiceAttachmentsToGridFs migrator = new M001_MigrateMailServiceAttachmentsToGridFs();
-
-	@Autowired
-	private MongoTemplate template;
-	@Autowired
-	private GridFsTemplate gridFsTemplate;
-
-	private Document binaryFileToMigrate;
-	private Document binaryFileNotToMigrate;
-
-	@BeforeEach
-	public void init() {
-		template.dropCollection(MigrationDbTestUtils.BINARY_FILE_COLLECTION);
-		template.dropCollection(MigrationDbTestUtils.GRID_FS_FILES_COLLECTION);
-		template.dropCollection(MigrationDbTestUtils.GRID_FS_CHUNKS_COLLECTION);
-
-		binaryFileToMigrate = MigrationDbTestUtils.saveBinaryFile(template, MigrationBinaryFileTestFactory.create());
-		binaryFileNotToMigrate = MigrationDbTestUtils.saveBinaryFile(template, MigrationBinaryFileTestFactory.create());
-
-		saveVorgangAttachedItem();
-	}
-
-	private void saveVorgangAttachedItem() {
-		var vorgangAttachedItem = MigrationVorgangAttachedItemTestFactory.create();
-		vorgangAttachedItem.put(MigrationVorgangAttachedItemTestFactory.FIELD_ITEM,
-				Map.of("attachments", List.of(MigrationTestUtils.getObjectId(binaryFileToMigrate).toString())));
-
-		MigrationDbTestUtils.saveVorgangAttachedItem(template, vorgangAttachedItem);
-	}
-
-	@Test
-	void shouldHaveFilePath() {
-		migrate();
-
-		var expectedPath = String.format("%s/%s/%s/%s",
-				MigrationBinaryFileTestFactory.VORGANG_ID,
-				MigrationBinaryFileTestFactory.CLIENT,
-				MigrationBinaryFileTestFactory.FIELD, MigrationIncomingFileTestFactory.NAME);
-
-		var gridFsFile = MigrationDbTestUtils.getGridFsFile(gridFsTemplate, MigrationTestUtils.getObjectId(binaryFileToMigrate));
-		assertThat(gridFsFile.getFilename()).isEqualTo(expectedPath);
-	}
-
-	@Test
-	void shouldHaveMetadata() {
-		migrate();
-
-		var gridFsFile = MigrationDbTestUtils.getGridFsFile(gridFsTemplate, MigrationTestUtils.getObjectId(binaryFileToMigrate));
-		var metadata = gridFsFile.getMetadata();
-		assertThat(metadata.getString(MigrationGridFSFileTestFactory.FIELD_CLIENT))
-				.isEqualTo(MigrationBinaryFileTestFactory.CLIENT);
-		assertThat(metadata.getString(MigrationGridFSFileTestFactory.FIELD_VORGANG_ID)).isEqualTo(MigrationBinaryFileTestFactory.VORGANG_ID);
-		assertThat(metadata.getString(MigrationGridFSFileTestFactory.FIELD_FIELD_NAME)).isEqualTo(MigrationBinaryFileTestFactory.FIELD);
-		assertThat(metadata.getString(MigrationGridFSFileTestFactory.FIELD_CONTENT_TYPE))
-				.isEqualTo(MigrationIncomingFileTestFactory.CONTENT_TYPE);
-		assertThat(metadata.getString(MigrationGridFSFileTestFactory.FIELD_NAME)).isEqualTo(MigrationIncomingFileTestFactory.NAME);
-	}
-
-	@Test
-	void shouldHaveContent() throws IOException {
-		migrate();
-
-		var gridFsResource = MigrationDbTestUtils.getGridFsResource(gridFsTemplate, MigrationTestUtils.getObjectId(binaryFileToMigrate));
-		assertThat(gridFsResource.getContent().readAllBytes()).isEqualTo(MigrationIncomingFileTestFactory.CONTENT);
-	}
-
-	@Test
-	void shouldNotHaveBeenMigrated() {
-		migrate();
-
-		var binaryFileId = MigrationTestUtils.getObjectId(binaryFileNotToMigrate).toString();
-		var binaryFile = MigrationDbTestUtils.getBinaryFile(template, binaryFileId);
-		assertThat(MigrationTestUtils.getObjectId(binaryFile)).hasToString(binaryFileId);
-	}
-
-	@Test
-	void shouldNotStopOnExceptionWhenMigrationASecondTime() {
-		migrate();
-
-		assertThatNoException().isThrownBy(this::migrate);
-	}
-
-	@Test
-	void shouldThrowException() throws IOException {
-		doThrow(new IOException("Test")).when(migrator).storeToGridFs(any(), any());
-
-		assertThatThrownBy(this::migrate).isInstanceOf(RuntimeException.class);
-	}
-
-	private void migrate() {
-		migrator.migrationMethod(template);
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M002_SetInCreationFalseForAllVorgangsITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M002_SetInCreationFalseForAllVorgangsITCase.java
deleted file mode 100644
index 1d840e89d7f1852930a31b2460dcc5b6dcf394d1..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M002_SetInCreationFalseForAllVorgangsITCase.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.assertj.core.api.Assertions.*;
-
-import org.bson.Document;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M002_SetInCreationFalseForAllVorgangsITCase { // NOSONAR
-
-	private final M002_SetInCreationFalseForAllVorgangs migrator = new M002_SetInCreationFalseForAllVorgangs();
-
-	@Autowired
-	private MongoTemplate template;
-
-	private Document vorgangNotToMigrate;
-	private Document vorgangToMigrate;
-
-	@BeforeEach
-	public void init() {
-		MigrationDbTestUtils.dropVorgangCollection(template);
-
-		vorgangNotToMigrate = MigrationDbTestUtils.saveVorgang(template, createVorgangNotToMigrate());
-		vorgangToMigrate = MigrationDbTestUtils.saveVorgang(template, createVorgangToMigrate());
-	}
-
-	private Document createVorgangNotToMigrate() {
-		var vorgang = MigrationVorgangTestFactory.create();
-		vorgang.put(MigrationVorgangTestFactory.FIELD_IN_CREATION, true);
-
-		return vorgang;
-	}
-
-	private Document createVorgangToMigrate() {
-		var vorgang = MigrationVorgangTestFactory.create();
-		vorgang.remove(MigrationVorgangTestFactory.FIELD_IN_CREATION);
-
-		return vorgang;
-	}
-
-	@Test
-	void shouldMigrate() {
-		migrator.migrationMethod(template);
-
-		var vorgangDocument = MigrationDbTestUtils.getVorgang(template, MigrationTestUtils.getObjectId(vorgangToMigrate));
-
-		assertThat(vorgangDocument).containsEntry(MigrationVorgangTestFactory.FIELD_IN_CREATION, Boolean.FALSE);
-	}
-
-	@Test
-	void shoulNotMigrate() {
-		migrator.migrationMethod(template);
-
-		var vorgangDocument = MigrationDbTestUtils.getVorgang(template, MigrationTestUtils.getObjectId(vorgangNotToMigrate));
-
-		assertThat(vorgangDocument).containsEntry(MigrationVorgangTestFactory.FIELD_IN_CREATION, Boolean.TRUE);
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase.java
deleted file mode 100644
index 0b8c6a636d03c69101ac80c8eee7091b8d28fc4d..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static de.itvsh.ozg.pluto.common.migration.M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs.*;
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.io.IOException;
-
-import org.apache.commons.lang3.StringUtils;
-import org.bson.Document;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.Spy;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.gridfs.GridFsTemplate;
-
-import com.mongodb.client.gridfs.model.GridFSFile;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M003_MigrateVorgangAttachmentsAndRepresentationsToGridFsITCase {// NOSONAR
-
-	@Spy
-	private M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs migrator = new M003_MigrateVorgangAttachmentsAndRepresentationsToGridFs();
-	@Autowired
-	private MongoTemplate template;
-	@Autowired
-	private GridFsTemplate gridFsTemplate;
-
-	private Document vorgang;
-
-	@BeforeEach
-	void init() {
-		template.dropCollection(MigrationDbTestUtils.GRID_FS_FILES_COLLECTION);
-		template.dropCollection(MigrationDbTestUtils.GRID_FS_CHUNKS_COLLECTION);
-		template.dropCollection(MigrationDbTestUtils.VORGANG_COLLECTION);
-
-		vorgang = MigrationDbTestUtils.saveVorgang(template, MigrationVorgangTestFactory.create());
-	}
-
-	@Test
-	void shouldNotStopOnExceptionWhenMigrationASecondTime() {
-		doMigration();
-
-		doMigration();
-
-		assertThatNoException().isThrownBy(this::doMigration);
-	}
-
-	@Test
-	void shouldThrowException() throws IOException {
-		doThrow(new IOException("Test Migration Exception")).when(migrator).storeToGridFs(any(), any(), any(), any());
-
-		assertThatThrownBy(this::doMigration).isInstanceOf(IllegalStateException.class);
-	}
-
-	@Nested
-	class TestAttachmentMigration {
-
-		@Nested
-		class TestFirstAttachmentFile {
-
-			private final static String NAME = MigrationAttachmentTestFactory.ATTACHMENT_FILE_NAME;
-
-			@Test
-			void shouldKeepDataInVorgangAttachment() {
-				doMigration();
-
-				var attachment = getAttachment(getIdOfCreatedGridFsFile(ATTACHMENT_FIELD_NAME_VALUE, NAME));
-				assertThat(attachment.getString(MigrationIncomingFileTestFactory.FIELD_CONTENT_TYPE))
-						.isEqualTo(MigrationIncomingFileTestFactory.CONTENT_TYPE);
-				assertThat(attachment.getString(MigrationIncomingFileTestFactory.FIELD_NAME)).isEqualTo(NAME);
-				assertThat(attachment.getLong(MigrationIncomingFileTestFactory.FIELD_SIZE)).isEqualTo(MigrationIncomingFileTestFactory.SIZE);
-			}
-
-			@Test
-			void shouldUpdateAttachmentFileId() {
-				doMigration();
-
-				var gridFsFileId = getIdOfCreatedGridFsFile(ATTACHMENT_FIELD_NAME_VALUE, NAME);
-				var attachment = getAttachment(gridFsFileId);
-				assertThat(gridFsFileId).isEqualTo(attachment.getString(OBJECT_ID));
-			}
-
-			@Nested
-			class TestCreatedGridFs {
-
-				@Test
-				void shouldHaveAttachmentFilePath() {
-					doMigration();
-
-					var expectedFilename = buildAttachmentFilename(NAME);
-					var migratedFilename = getGridFsFile(expectedFilename).getFilename();
-					assertThat(migratedFilename).isEqualTo(expectedFilename);
-				}
-
-				@Test
-				void shouldHaveGridFsFileMetadata() {
-					doMigration();
-
-					var gridFsFile = getGridFsFile(buildAttachmentFilename(NAME));
-					var metadata = gridFsFile.getMetadata();
-					assertThat(metadata.getString(CLIENT)).isEqualTo(CLIENT_VALUE);
-					assertThat(metadata.getString(VORGANG_ID)).isEqualTo(MigrationTestUtils.getObjectId(vorgang).toHexString());
-					assertThat(metadata.getString(FILE_FIELD_NAME)).isEqualTo(ATTACHMENT_FIELD_NAME_VALUE);
-				}
-
-				@Test
-				void shouldHaveAttachmentContent() throws IOException {
-					doMigration();
-
-					var gridFsFileContent = getGridFsFileContent(getGridFsFile(buildAttachmentFilename(NAME)));
-					assertThat(gridFsFileContent).isEqualTo(MigrationIncomingFileTestFactory.CONTENT);
-				}
-			}
-		}
-
-		@Nested
-		class TestSecondAttachmentFile {
-
-			private final static String NAME = MigrationAttachmentTestFactory.ATTACHMENT_FILE_NAME2;
-
-			@Test
-			void shouldKeepDataInVorgang() {
-				doMigration();
-
-				var attachment = getAttachment(getIdOfCreatedGridFsFile(ATTACHMENT_FIELD_NAME_VALUE, NAME));
-				assertThat(attachment.getString(MigrationIncomingFileTestFactory.FIELD_CONTENT_TYPE))
-						.isEqualTo(MigrationIncomingFileTestFactory.CONTENT_TYPE);
-				assertThat(attachment.getString(MigrationIncomingFileTestFactory.FIELD_NAME)).isEqualTo(NAME);
-				assertThat(attachment.getLong(MigrationIncomingFileTestFactory.FIELD_SIZE)).isEqualTo(MigrationIncomingFileTestFactory.SIZE);
-			}
-
-			@Test
-			void shouldUpdateAttachmentFileId() {
-				doMigration();
-
-				var gridFsFileId = getIdOfCreatedGridFsFile(ATTACHMENT_FIELD_NAME_VALUE, NAME);
-				var attachment = getAttachment(gridFsFileId);
-				assertThat(gridFsFileId).isEqualTo(attachment.getString(OBJECT_ID).toString());
-			}
-
-			@Nested
-			class TestCreatedGridFs {
-
-				@Test
-				void shouldHaveAttachmentFilePath() {
-					doMigration();
-
-					var expectedFilename = buildAttachmentFilename(NAME);
-					var gridFsFile = getGridFsFile(expectedFilename);
-					var migratedFilename = gridFsFile.getFilename();
-					assertThat(migratedFilename).isEqualTo(expectedFilename);
-				}
-
-				@Test
-				void shouldHaveGridFsFileMetadata() {
-					doMigration();
-
-					var gridFsFileMetadata = getGridFsFile(buildAttachmentFilename(NAME)).getMetadata();
-					assertThat(gridFsFileMetadata.getString(CLIENT)).isEqualTo(CLIENT_VALUE);
-					assertThat(gridFsFileMetadata.getString(VORGANG_ID)).isEqualTo(MigrationTestUtils.getObjectId(vorgang).toHexString());
-					assertThat(gridFsFileMetadata.getString(FILE_FIELD_NAME)).isEqualTo(ATTACHMENT_FIELD_NAME_VALUE);
-				}
-
-				@Test
-				void shouldHaveAttachmentContent() throws IOException {
-					doMigration();
-
-					var gridFsFileContent = getGridFsFileContent(getGridFsFile(buildAttachmentFilename(NAME)));
-					assertThat(gridFsFileContent).isEqualTo(MigrationIncomingFileTestFactory.CONTENT);
-				}
-			}
-		}
-
-		private Document getAttachment(String gridFsFileId) {
-			var attachments = getVorgang().getList(MigrationVorgangTestFactory.FIELD_EINGANGS, Document.class).get(0)
-					.getList(MigrationEingangTestFactory.FIELD_ATTACHMENTS, Document.class);
-			return attachments.stream()
-					.flatMap(oneattachment -> oneattachment.getList("files", Document.class).stream())
-					.filter(attachmentFile -> StringUtils.equals(attachmentFile.getString(OBJECT_ID), gridFsFileId))
-					.toList().get(0);
-		}
-	}
-
-	@Nested
-	class TestRepresentationMigration {
-
-		private final static String NAME = MigrationIncomingFileTestFactory.NAME;
-
-		@Test
-		void shouldKeepDataInVorgang() {
-			doMigration();
-
-			var representation = getRepresentation(getVorgang(), getIdOfCreatedGridFsFile());
-			assertThat(representation.getString(MigrationIncomingFileTestFactory.FIELD_CONTENT_TYPE))
-					.isEqualTo(MigrationIncomingFileTestFactory.CONTENT_TYPE);
-			assertThat(representation.getString(MigrationIncomingFileTestFactory.FIELD_NAME)).isEqualTo(NAME);
-			assertThat(representation.getLong(MigrationIncomingFileTestFactory.FIELD_SIZE)).isEqualTo(MigrationIncomingFileTestFactory.SIZE);
-		}
-
-		@Test
-		void shouldUpdateRepresentationFileId() {
-			doMigration();
-
-			var gridFsFileId = getIdOfCreatedGridFsFile();
-			var representation = getRepresentation(getVorgang(), gridFsFileId);
-			assertThat(gridFsFileId).isEqualTo(representation.getString(OBJECT_ID));
-		}
-
-		private String getIdOfCreatedGridFsFile() {
-			var gridFsFile = getGridFsFile(buildRepresentationFilename());
-			var gridFsFileId = gridFsFile.getId().asObjectId().getValue().toHexString();
-			return gridFsFileId;
-		}
-
-		@Nested
-		class TestCreatedGridFs {
-
-			@Test
-			void shouldHaveRepresentationFilePath() {
-				doMigration();
-
-				var expectedFilename = buildRepresentationFilename();
-				var gridFsFile = getGridFsFile(buildRepresentationFilename());
-				var migratedFilename = gridFsFile.getFilename();
-				assertThat(migratedFilename).isEqualTo(expectedFilename);
-			}
-
-			@Test
-			void shouldSetGridFsFileMetadata() {
-				doMigration();
-
-				var gridFsFile = getGridFsFile(buildRepresentationFilename());
-				var metadata = gridFsFile.getMetadata();
-				assertThat(metadata.getString(CLIENT)).isEqualTo(CLIENT_VALUE);
-				assertThat(metadata.getString(VORGANG_ID)).isEqualTo(MigrationTestUtils.getObjectId(vorgang).toHexString());
-				assertThat(metadata.getString(FILE_FIELD_NAME)).isEqualTo(REPRESENTATION_FIELD_NAME_VALUE);
-			}
-
-			@Test
-			void shouldHaveRepresentationContent() throws IOException {
-				doMigration();
-
-				var gridFsFileContent = getGridFsFileContent(getGridFsFile(buildRepresentationFilename()));
-				assertThat(gridFsFileContent).isEqualTo(MigrationIncomingFileTestFactory.CONTENT);
-			}
-		}
-
-		private Document getRepresentation(Document vorgang, String gridFsFileId) {
-			var representations = vorgang.getList(MigrationVorgangTestFactory.FIELD_EINGANGS, Document.class).get(0)
-					.getList(MigrationEingangTestFactory.FIELD_REPRESENTATIONS, Document.class);
-			return representations.stream()
-					.filter(representationFile -> StringUtils.equals(representationFile.getString(OBJECT_ID), gridFsFileId))
-					.toList().get(0);
-		}
-
-		private String buildRepresentationFilename() {
-			return buildFilename(REPRESENTATION_FIELD_NAME_VALUE, NAME);
-		}
-	}
-
-	private byte[] getGridFsFileContent(GridFSFile gridFsFile) throws IOException {
-		return gridFsTemplate.getResource(gridFsFile).getContent().readAllBytes();
-	}
-
-	private Document getVorgang() {
-		return MigrationDbTestUtils.getVorgang(template, MigrationTestUtils.getObjectId(vorgang));
-	}
-
-	private String buildFilename(String fieldValue, String name) {
-		return String.format("%s/%s/%s/%s",
-				MigrationTestUtils.getObjectId(vorgang).toHexString(),
-				CLIENT_VALUE,
-				fieldValue,
-				name);
-	}
-
-	private GridFSFile getGridFsFile(String filename) {
-		return MigrationDbTestUtils.getGridFsFile(gridFsTemplate, filename);
-	}
-
-	private String getIdOfCreatedGridFsFile(String fieldName, String name) {
-		var filename = buildFilename(fieldName, name);
-		return getGridFsFile(filename).getId().asObjectId().getValue().toHexString();
-	}
-
-	private String buildAttachmentFilename(String name) {
-		return buildFilename(ATTACHMENT_FIELD_NAME_VALUE, name);
-	}
-
-	private void doMigration() {
-		migrator.migrationMethod(template);
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M004_RemoveWiedervorlagenITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M004_RemoveWiedervorlagenITCase.java
deleted file mode 100644
index 95b6a0c72962bddfb314c8e905244d436fed0ca1..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M004_RemoveWiedervorlagenITCase.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static de.itvsh.ozg.pluto.common.migration.M004_RemoveWiedervorlagen.*;
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.List;
-
-import org.bson.Document;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Spy;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M004_RemoveWiedervorlagenITCase {// NOSONAR
-
-	private static final String OTHER_FIELD_ID_VALUE = "postfachNachrichtAttachment";
-
-	@Spy
-	private M004_RemoveWiedervorlagen migrator = new M004_RemoveWiedervorlagen();
-
-	@Autowired
-	private MongoTemplate template;
-
-	private Document vorgang;
-
-	@BeforeEach
-	public void init() {
-		MigrationDbTestUtils.dropBinaryFileCollection(template);
-		MigrationDbTestUtils.dropVorgangCollection(template);
-
-		vorgang = MigrationDbTestUtils.saveVorgang(template, createVorgangWithWiedervorlage());
-
-		MigrationDbTestUtils.saveBinaryFile(template, createBinaryFile(FIELD_KEY_VALUE));
-		MigrationDbTestUtils.saveBinaryFile(template, createBinaryFile(OTHER_FIELD_ID_VALUE));
-	}
-
-	private Document createVorgangWithWiedervorlage() {
-		var vorgang = MigrationVorgangTestFactory.create();
-		vorgang.put(MigrationVorgangTestFactory.FIELD_WIEDERVORLAGES, List.of(MigrationWiedervorlageTestFactory.create()));
-		return vorgang;
-	}
-
-	private Document createBinaryFile(String fieldValue) {
-		var binaryFileDoc = MigrationBinaryFileTestFactory.create();
-		binaryFileDoc.put(MigrationBinaryFileTestFactory.FIELD_VORGANG_ID, MigrationTestUtils.getObjectId(vorgang).toHexString());
-		binaryFileDoc.put(MigrationBinaryFileTestFactory.FIELD_CLIENT, "goofy");
-		binaryFileDoc.put(MigrationBinaryFileTestFactory.FIELD_FIELD, fieldValue);
-
-		return binaryFileDoc;
-	}
-
-	@Test
-	void shouldRemoveWiedervorlageAttachment() {
-		migrate();
-
-		var wiedervorlageAttachments = findBinaryFile(FIELD_KEY_VALUE);
-		assertThat(wiedervorlageAttachments).isEmpty();
-	}
-
-	@Test
-	void shouldRemoveWiedervorlages() {
-		migrate();
-
-		var migratedVorgang = MigrationDbTestUtils.getVorgang(template, MigrationTestUtils.getObjectId(vorgang));
-		assertThat(migratedVorgang.get(WIEDERVORLAGES_FIELD_KEY)).isNull();
-	}
-
-	@Test
-	void shouldNotRemovePostfachNachrichtAttachment() {
-		migrate();
-
-		var postfachNachrichtAttachments = findBinaryFile(OTHER_FIELD_ID_VALUE);
-		assertThat(postfachNachrichtAttachments).isNotEmpty();
-
-	}
-
-	private void migrate() {
-		migrator.migrationMethod(template);
-	}
-
-	private List<Document> findBinaryFile(String fieldValue) {
-		return MigrationDbTestUtils.findBinaryFile(template, new Query(Criteria.where(FIELD_KEY).is(fieldValue)));
-	}
-}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M005_CreateIndexesInVorgangITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M005_CreateIndexesInVorgangITCase.java
deleted file mode 100644
index ac795a9952ae5aaa9dd43be78f4e4ef80171cfef..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M005_CreateIndexesInVorgangITCase.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.assertj.core.api.Assertions.*;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M005_CreateIndexesInVorgangITCase {
-
-	@InjectMocks
-	private M005_CreateIndexesInVorgang migration;
-
-	@Autowired
-	private MongoTemplate template;
-
-	@BeforeEach
-	void clearDb() {
-		template.indexOps(MigrationDbTestUtils.VORGANG_COLLECTION).dropAllIndexes();
-	}
-
-	@Test
-	void shouldCreateIndexes() {
-		migration.createIndexes(template);
-
-		var indexInfos = template.indexOps(MigrationDbTestUtils.VORGANG_COLLECTION).getIndexInfo();
-		assertThat(indexInfos).hasSize(3);
-	}
-
-	@Nested
-	class TestCreateIndexWithoutStatus {
-		@Test
-		void shouldCreateIndex() {
-			migration.createIndexWithoutStatus(template);
-
-			var indexInfos = template.indexOps(MigrationDbTestUtils.VORGANG_COLLECTION).getIndexInfo();
-			assertThat(indexInfos).hasSize(2);
-		}
-	}
-
-	@Nested
-	class TestCreateIndexWithStatus {
-		@Test
-		void shouldCreateIndex() {
-			migration.createIndexWithStatus(template);
-
-			var indexInfos = template.indexOps(MigrationDbTestUtils.VORGANG_COLLECTION).getIndexInfo();
-			assertThat(indexInfos).hasSize(2);
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M006_MigrateKommentarITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M006_MigrateKommentarITCase.java
deleted file mode 100644
index 4423425ff82f711fd7df8cd4a337924b768000e0..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M006_MigrateKommentarITCase.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.List;
-
-import org.bson.Document;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.Spy;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M006_MigrateKommentarITCase {
-
-	@Spy
-	private M006_MigrateKommentar migrator = new M006_MigrateKommentar();
-
-	@Autowired
-	private MongoTemplate template;
-
-	private Document savedVorgang;
-
-	@BeforeEach
-	void initKommentar() {
-		MigrationDbTestUtils.dropVorgangCollection(template);
-		MigrationDbTestUtils.dropVorgangAttachedItemCollection(template);
-
-		var vorgang = MigrationVorgangTestFactory.create();
-		vorgang.put(MigrationVorgangTestFactory.FIELD_KOMMENTARS, List.of(MigrationKommentarTestFactory.create()));
-		savedVorgang = MigrationDbTestUtils.saveVorgang(template, vorgang);
-	}
-
-	@DisplayName("Migrate Kommentare")
-	@Nested
-	class TestMigrateKommentar {
-
-		@Nested
-		class CreateAttachedItem {
-
-			@Test
-			void shouldExists() {
-				migrator.migrationMethod(template);
-
-				var kommentarAsAttachedItem = getKommentare();
-
-				assertThat(kommentarAsAttachedItem).isNotEmpty().hasSize(1);
-			}
-
-			@Test
-			void shouldContainsData() {
-				migrator.migrationMethod(template);
-
-				var kommentarAsAttachedItem = getKommentare().get(0);
-
-				assertThat(kommentarAsAttachedItem)
-						.containsEntry(MigrationVorgangAttachedItemTestFactory.FIELD_ITEM_NAME, M006_MigrateKommentar.ATTACHED_ITEM_ITEM_NAME)
-						.containsEntry(MigrationVorgangAttachedItemTestFactory.FIELD_CLIENT, M006_MigrateKommentar.ATTACHED_ITEM_CLIENT)
-						.containsEntry(MigrationVorgangAttachedItemTestFactory.VERSION_FIELD, M006_MigrateKommentar.ATTACHED_ITEM_VERSION);
-			}
-
-			@Test
-			void shouldContainsItemData() {
-				migrator.migrationMethod(template);
-
-				var kommentarAsAttachedItem = getKommentare().get(0);
-				var item = (Document) kommentarAsAttachedItem.get(MigrationVorgangAttachedItemTestFactory.FIELD_ITEM);
-
-				assertThat(item)
-						.containsEntry(MigrationKommentarTestFactory.CREATED_AT_FIELD, MigrationKommentarTestFactory.CREATED_AT_STR)
-						.containsEntry(MigrationKommentarTestFactory.CREATED_BY_FIELD, MigrationKommentarTestFactory.CREATED_BY)
-						.containsEntry(MigrationKommentarTestFactory.TEXT_FIELD, MigrationKommentarTestFactory.TEXT);
-			}
-
-			@Test
-			void shouldNotMigrateTwice() {
-				migrator.migrationMethod(template);
-
-				migrator.migrationMethod(template);
-
-				assertThat(getKommentare()).hasSize(1);
-
-			}
-
-			private List<Document> getKommentare() {
-				return MigrationDbTestUtils.getVorgangAttachedItem(template, "itemName", "Kommentar");
-			}
-		}
-
-		@Nested
-		class DataAtVorgang {
-
-			@Test
-			void shouldStillExists() {
-				migrator.migrationMethod(template);
-
-				var kommentarAtVorgang = getKommentare();
-
-				assertThat(kommentarAtVorgang).isNotEmpty().hasSize(1);
-			}
-
-			@Test
-			void shouldKeptData() {
-				migrator.migrationMethod(template);
-
-				var kommentarAtVorgang = getKommentare().get(0);
-
-				assertThat(kommentarAtVorgang).usingRecursiveComparison().isEqualTo(MigrationKommentarTestFactory.create());
-			}
-
-			private List<Document> getKommentare() {
-				var vorgang = MigrationDbTestUtils.getVorgang(template, MigrationTestUtils.getObjectId(savedVorgang));
-				return MigrationTestUtils.getList(vorgang, MigrationVorgangTestFactory.FIELD_KOMMENTARS);
-			}
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommandsITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommandsITCase.java
deleted file mode 100644
index 59bf2edc53a4459a2b6bfa0345eba7a198739085..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommandsITCase.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.UUID;
-
-import org.bson.Document;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import static org.assertj.core.api.Assertions.*;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommandsITCase {
-
-	private final M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommands migrator = new M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommands();
-
-	@Autowired
-	private MigrationDbTestUtils dbTestUtils;
-	@Autowired
-	private MongoTemplate template;
-
-	private Document kommentarCommandToUpdate;
-	private Document wiedervorlageCommandToUpdate;
-	private Document doNotMigrateCommandByWrongOrder;
-	private Document doNotMigrateCommandByValidRelationId;
-
-	@BeforeEach
-	void initDatabase() {
-		dbTestUtils.dropCommandCollection();
-
-		kommentarCommandToUpdate = dbTestUtils.saveCommand(M007_MigrationTestFactory.createCommandWithKommentarAsBody());
-		wiedervorlageCommandToUpdate = dbTestUtils.saveCommand(M007_MigrationTestFactory.createCommandWithWiedervorlageAsBody());
-
-		doNotMigrateCommandByWrongOrder = dbTestUtils.saveCommand(M007_MigrationTestFactory.createCommandWithWrongOrder());
-		doNotMigrateCommandByValidRelationId = dbTestUtils.saveCommand(M007_MigrationTestFactory.createCommandWithValidRelationId());
-	}
-
-	@DisplayName("Migrate relationId")
-	@Nested
-	class TestMigrateRelationId {
-
-		@Test
-		void shouldFindAllConsidered() {
-			var commands = migrator.getCommands(template).stream().toList();
-
-			assertThat(commands).hasSize(2);
-		}
-
-		@DisplayName("should not update relation id")
-		@Nested
-		class TestNotUpdateRelationid {
-
-			@DisplayName("on not considered order")
-			@Test
-			void onOtherOrderCommands() {
-				migrator.migrationMethod(template);
-
-				var migratedCommand = reloadCommand(doNotMigrateCommandByWrongOrder);
-				assertThat(migratedCommand).containsEntry(
-						M007_MigrationTestFactory.COMMAND_RELATION_ID_FIELD, M007_MigrationTestFactory.COMMAND_RELATION_ID);
-			}
-
-			@DisplayName("on valid relation id")
-			@Test
-			void onfValidRelationId() {
-				migrator.migrationMethod(template);
-
-				var migratedCommand = reloadCommand(doNotMigrateCommandByValidRelationId);
-				assertThat(migratedCommand).containsEntry(
-						M007_MigrationTestFactory.COMMAND_RELATION_ID_FIELD, M007_MigrationTestFactory.WIEDERVORLAGE_ID);
-			}
-		}
-
-		@DisplayName("of edit kommentar command")
-		@Nested
-		class TestEditKommentarCommand {
-
-			@Test
-			void shouldSetItemIdAsRelationId() {
-				migrator.migrationMethod(template);
-
-				var migratedCommand = reloadCommand(kommentarCommandToUpdate);
-				assertThat(migratedCommand).containsEntry(
-						M007_MigrationTestFactory.COMMAND_RELATION_ID_FIELD, M007_MigrationTestFactory.KOMMENTAR_ID);
-			}
-		}
-
-		@DisplayName("of update wiedervorlage command")
-		@Nested
-		class TestUpdateWiedervorlageCommand {
-
-			@Test
-			void shouldSetItemIdAsRelationId() {
-				migrator.migrationMethod(template);
-
-				var migratedCommand = reloadCommand(wiedervorlageCommandToUpdate);
-				assertThat(migratedCommand).containsEntry(
-						M007_MigrationTestFactory.COMMAND_RELATION_ID_FIELD, M007_MigrationTestFactory.WIEDERVORLAGE_ID);
-			}
-		}
-
-		private Document reloadCommand(Document commandToReload) {
-			return dbTestUtils.getCommand(MigrationTestUtils.getObjectId(commandToReload));
-		}
-	}
-
-	private class M007_MigrationTestFactory {
-
-		private static final String ID_FIELD = "id";
-
-		static final String KOMMENTAR_ID = UUID.randomUUID().toString();
-		static final String WIEDERVORLAGE_ID = UUID.randomUUID().toString();
-
-		private static final String ITEM_FIELD = "item";
-
-		private static final String ITEM_NAME_FIELD = "itemName";
-		private static final String ITEM_NAME_WIEDERVORLAGE = "Wiedervorlage";
-		private static final String ITEM_NAME_KOMMENTAR = "Kommentar";
-
-		static final String COMMAND_RELATION_ID_FIELD = "relationId";
-		static final String COMMAND_RELATION_ID = UUID.randomUUID().toString();
-
-		private static final String COMMAND_RELATION_VERSION_FIELD = "relationVersion";
-		private static final int COMMAND_RELATION_VERSION = 42;
-
-		private static final String COMMAND_BODY_OBJECT_FIELD = "bodyObject";
-
-		private static final String COMMAND_ORDER_FIELD = "order";
-
-		public static Document createCommandWithKommentarAsBody() {
-			return createCommandWithBody(createKommentar());
-		}
-
-		private static Document createKommentar() {
-			var item = new Document();
-			item.put(ID_FIELD, KOMMENTAR_ID);
-
-			var vorgangAttachedItem = new Document();
-			vorgangAttachedItem.put(ITEM_NAME_FIELD, ITEM_NAME_KOMMENTAR);
-			vorgangAttachedItem.put(ITEM_FIELD, item);
-
-			return vorgangAttachedItem;
-		}
-
-		public static Document createCommandWithWiedervorlageAsBody() {
-			return createCommandWithBody(createWiedervorlage());
-		}
-
-		private static Document createWiedervorlage() {
-			var item = new Document();
-			item.put(ID_FIELD, WIEDERVORLAGE_ID);
-
-			var vorgangAttachedItem = new Document();
-			vorgangAttachedItem.put(ITEM_NAME_FIELD, ITEM_NAME_WIEDERVORLAGE);
-			vorgangAttachedItem.put(ITEM_FIELD, item);
-
-			return vorgangAttachedItem;
-		}
-
-		private static Document createCommandWithBody(Document bodyObject) {
-			var command = createCommand();
-			command.put(COMMAND_RELATION_ID_FIELD, COMMAND_RELATION_ID);
-			command.put(COMMAND_ORDER_FIELD, M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommands.CONSIDERED_ORDER);
-			command.put(COMMAND_BODY_OBJECT_FIELD, bodyObject);
-
-			return command;
-		}
-
-		public static Document createCommandWithValidRelationId() {
-			var command = createCommand();
-			command.put(COMMAND_RELATION_ID_FIELD, WIEDERVORLAGE_ID);
-			command.put(COMMAND_BODY_OBJECT_FIELD, createWiedervorlage());
-			command.put(COMMAND_ORDER_FIELD, M007_MigrateRelationIdOnUpdateVorgangAttachedItemCommands.CONSIDERED_ORDER);
-
-			return command;
-		}
-
-		public static Document createCommandWithWrongOrder() {
-			var command = createCommand();
-			command.put(COMMAND_RELATION_ID_FIELD, COMMAND_RELATION_ID);
-			command.put(COMMAND_ORDER_FIELD, "ANY_ORDER");
-
-			return command;
-		}
-
-		private static Document createCommand() {
-			var command = new Document();
-			command.put(COMMAND_RELATION_VERSION_FIELD, COMMAND_RELATION_VERSION);
-			command.put(COMMAND_BODY_OBJECT_FIELD, new Document());
-
-			return command;
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M008_DropBinaryFilesCollectionITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M008_DropBinaryFilesCollectionITCase.java
deleted file mode 100644
index fdf50e3690738cfa0c653f097cc77bf70741b709..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M008_DropBinaryFilesCollectionITCase.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.assertj.core.api.Assertions.*;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M008_DropBinaryFilesCollectionITCase {
-
-	private M008_DropBinaryFilesCollection migrator = new M008_DropBinaryFilesCollection();
-
-	@Autowired
-	private MongoTemplate template;
-
-	@BeforeEach
-	void initDatabase() {
-		template.dropCollection(MigrationDbTestUtils.BINARY_FILE_COLLECTION);
-		template.dropCollection(MigrationDbTestUtils.VORGANG_COLLECTION);
-
-		template.createCollection(MigrationDbTestUtils.BINARY_FILE_COLLECTION);
-		template.createCollection(MigrationDbTestUtils.VORGANG_COLLECTION);
-	}
-
-	@DisplayName("Test dropping binaryFile collection")
-	@Nested
-	class TestDropCollection {
-		@Test
-		void shouldDropCollection() {
-			migrator.migrationMethod(template);
-
-			assertThat(template.collectionExists(MigrationDbTestUtils.BINARY_FILE_COLLECTION)).isFalse();
-		}
-
-		@Test
-		void shouldNotDropVorgangCollection() {
-			migrator.migrationMethod(template);
-
-			assertThat(template.collectionExists(MigrationDbTestUtils.VORGANG_COLLECTION)).isTrue();
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M009_RemoveAttachmentContentITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M009_RemoveAttachmentContentITCase.java
deleted file mode 100644
index 39efcb932fb78c10a3ffd96e538128ca32dbf5cc..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M009_RemoveAttachmentContentITCase.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static de.itvsh.ozg.pluto.common.migration.MigrationAttachmentTestFactory.*;
-import static de.itvsh.ozg.pluto.common.migration.MigrationEingangTestFactory.*;
-import static de.itvsh.ozg.pluto.common.migration.MigrationIncomingFileTestFactory.*;
-import static de.itvsh.ozg.pluto.common.migration.MigrationVorgangTestFactory.*;
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.List;
-
-import org.bson.Document;
-import org.bson.types.Binary;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M009_RemoveAttachmentContentITCase {
-
-	private M009_RemoveAttachmentContent migrator = new M009_RemoveAttachmentContent();
-
-	@Autowired
-	private MongoTemplate template;
-
-	private Document savedVorgang1;
-	private Document savedVorgang2;
-
-	@BeforeEach
-	void initDatabase() {
-		MigrationDbTestUtils.dropVorgangCollection(template);
-
-		savedVorgang1 = MigrationDbTestUtils.saveVorgang(template, TestFactory.create(true));
-		savedVorgang2 = MigrationDbTestUtils.saveVorgang(template, TestFactory.create(false));
-	}
-
-	@DisplayName("Test removing attachment content")
-	@Nested
-	class TestRemoveAttachmentContent {
-		@Test
-		void shouldRemoveAttachmentContent() {
-			migrator.migrationMethod(template);
-
-			assertThat(getFirstAttachment(savedVorgang1)).doesNotContainKey("content");
-		}
-
-		@Test
-		void shouldNotTouchVorgangWithoutAttachmentContent() {
-			migrator.migrationMethod(template);
-
-			assertThat(getVorgang(savedVorgang2)).usingRecursiveComparison().isEqualTo(savedVorgang2);
-		}
-	}
-
-	private Document getVorgang(Document vorgang) {
-		return MigrationDbTestUtils.getVorgang(template, MigrationTestUtils.getObjectId(vorgang));
-	}
-
-	private Document getFirstAttachment(Document vorgang) {
-		var attachments = getVorgang(vorgang).getList(MigrationVorgangTestFactory.FIELD_EINGANGS, Document.class).get(0)
-				.getList(MigrationEingangTestFactory.FIELD_ATTACHMENTS, Document.class);
-
-		return attachments.get(0).getList("files", Document.class).get(0);
-	}
-
-	class TestFactory {
-		static Document create(boolean withContent) {
-			var vorgang = new Document();
-			vorgang.put(FIELD_EINGANGS, List.of(createEingang(withContent)));
-			return vorgang;
-		}
-
-		static Document createEingang(boolean withContent) {
-			var eingang = new Document();
-			eingang.put(FIELD_ATTACHMENTS, List.of(createFileGroup(withContent)));
-			eingang.put(FIELD_NUMBER_OF_ATTACHMENTS, 1);
-
-			return eingang;
-		}
-
-		private static Document createFileGroup(boolean withContent) {
-			var incomingFileGroup = new Document();
-			incomingFileGroup.put(FIELD_FILES, List.of(createFile(withContent)));
-
-			return incomingFileGroup;
-		}
-
-		static Document createFile(boolean withContent) {
-			var file = new Document();
-
-			file.put(FIELD_CONTENT_TYPE, CONTENT_TYPE);
-			file.put(FIELD_SIZE, SIZE);
-			if (withContent) {
-				file.put(FIELD_CONTENT, new Binary(CONTENT));
-			}
-
-			return file;
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M010_RemoveRepresentationsContentITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M010_RemoveRepresentationsContentITCase.java
deleted file mode 100644
index cfbeb6959333ef549548ce2a74821ee7e61761b2..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M010_RemoveRepresentationsContentITCase.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static de.itvsh.ozg.pluto.common.migration.MigrationEingangTestFactory.*;
-import static de.itvsh.ozg.pluto.common.migration.MigrationIncomingFileTestFactory.*;
-import static de.itvsh.ozg.pluto.common.migration.MigrationVorgangTestFactory.*;
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.HashMap;
-import java.util.List;
-
-import org.bson.Document;
-import org.bson.types.Binary;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M010_RemoveRepresentationsContentITCase {
-
-	private M010_RemoveRepresentationContent migrator = new M010_RemoveRepresentationContent();
-
-	@Autowired
-	private MongoTemplate template;
-
-	private Document savedVorgang1;
-	private Document savedVorgang2;
-
-	@BeforeEach
-	void initDatabase() {
-		MigrationDbTestUtils.dropVorgangCollection(template);
-
-		savedVorgang1 = MigrationDbTestUtils.saveVorgang(template, TestFactory.create(true));
-		savedVorgang2 = MigrationDbTestUtils.saveVorgang(template, TestFactory.create(false));
-	}
-
-	@DisplayName("Test removing representation content")
-	@Nested
-	class TestRemoveRepresentationContent {
-		@Test
-		void shouldRemoveRepresentationContent() {
-			migrator.migrationMethod(template);
-
-			assertThat(getRepresentation(savedVorgang1)).doesNotContainKey("content");
-		}
-
-		@Test
-		void shouldNotTouchVorgangWithoutRepresentationContent() {
-			migrator.migrationMethod(template);
-
-			assertThat(getVorgang(savedVorgang2)).usingRecursiveComparison().isEqualTo(savedVorgang2);
-		}
-	}
-
-	private Document getVorgang(Document vorgang) {
-		return MigrationDbTestUtils.getVorgang(template, MigrationTestUtils.getObjectId(vorgang));
-	}
-
-	private Document getRepresentation(Document vorgang) {
-		var eingangs = getVorgang(vorgang).getList(FIELD_EINGANGS, Document.class);
-		var representations = eingangs.get(0).getList(FIELD_REPRESENTATIONS, Document.class);
-		return representations.get(0);
-	}
-
-	class TestFactory {
-		static Document create(boolean withContent) {
-			var vorgang = new Document();
-			vorgang.put(FIELD_EINGANGS, List.of(createEingang(withContent)));
-			return vorgang;
-		}
-
-		static Document createEingang(boolean withContent) {
-			var eingang = new Document();
-			eingang.put(FIELD_REPRESENTATIONS, List.of(createFile(withContent)));
-			eingang.put(FIELD_NUMBER_OF_REPRESENTATIONS, 1);
-			eingang.put(FIELD_FORMDATA, new HashMap<String, Object>());
-
-			return eingang;
-		}
-
-		static Document createFile(boolean withContent) {
-			var file = new Document();
-
-			file.put(FIELD_CONTENT_TYPE, CONTENT_TYPE);
-			file.put(FIELD_SIZE, SIZE);
-			if (withContent) {
-				file.put(FIELD_CONTENT, new Binary(CONTENT));
-			}
-
-			return file;
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M011_FixTypeAliasITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M011_FixTypeAliasITCase.java
deleted file mode 100644
index 1da102479ca91e587de7a57fd77575973c31f2fb..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M011_FixTypeAliasITCase.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Stream;
-
-import org.bson.Document;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Spy;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M011_FixTypeAliasITCase {
-
-	@Spy
-	@InjectMocks
-	private M011_FixTypeAlias migration;
-
-	@Autowired
-	private MongoTemplate template;
-
-	@BeforeEach
-	void clearDatabase() {
-		template.dropCollection(MigrationDbTestUtils.COMMAND_COLLECTION);
-		template.dropCollection(MigrationDbTestUtils.VORGANG_COLLECTION);
-		template.dropCollection(MigrationDbTestUtils.VORGANG_ATTACHED_ITEM_COLLECTION);
-	}
-
-	@Test
-	void shouldCallMigrateCommands() {
-		migration.doMigration(template);
-
-		verify(migration).migrateCommands(any());
-	}
-
-	@Test
-	void shouldCallMigrateVorgangs() {
-		migration.doMigration(template);
-
-		verify(migration).migrateVorgangs(any());
-	}
-
-	@Test
-	void shouldCallMigrateItems() {
-		migration.doMigration(template);
-
-		verify(migration).migrateVorgangAttachedItems(template);
-	}
-
-	@Test
-	void shouldCallMigrateAttributes() {
-		migration.doMigration(template);
-
-		verify(migration).migrateClientAttributes(template);
-	}
-
-	@Nested
-	class TestMigrationOfCommands {
-
-		@BeforeEach
-		void persistCommand() {
-			template.save(buildDocument("de.itvsh.ozg.pluto.command.Command"), MigrationDbTestUtils.COMMAND_COLLECTION);
-			template.save(buildDocument("de.itvsh.ozg.pluto.command.PersistedCommand"), MigrationDbTestUtils.COMMAND_COLLECTION);
-
-			assertThat(getCommands()).isNotEmpty().allMatch(doc -> doc.containsKey("_class"));
-		}
-
-		@Test
-		void shouldUpdateTypeAttributeKey() {
-			migration.migrateCommands(template);
-
-			assertThat(getCommands()).isNotEmpty()
-					.allMatch(doc -> Objects.equals(doc.getString(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE), M011_FixTypeAlias.COMMAND_TYPE_ALIAS));
-		}
-
-		@Test
-		void shouldMatchNothingAfterMigration() {
-			migration.migrateCommands(template);
-
-			assertThat(template.count(migration.buildQuery(), MigrationDbTestUtils.COMMAND_COLLECTION)).isZero();
-		}
-
-		private List<Document> getCommands() {
-			return template.findAll(Document.class, MigrationDbTestUtils.COMMAND_COLLECTION);
-		}
-
-	}
-
-	@Nested
-	class TestMigrateVorgangs {
-		@BeforeEach
-		void persistVorgang() {
-			template.save(buildDocument("de.itvsh.ozg.pluto.vorgang.Vorgang"), MigrationDbTestUtils.VORGANG_COLLECTION);
-		}
-
-		@Test
-		void shouldUpdateTypeAttributeKey() {
-			migration.migrateVorgangs(template);
-
-			assertThat(getVorgangs()).isNotEmpty()
-					.allMatch(doc -> Objects.equals(doc.getString(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE), M011_FixTypeAlias.VORGANG_TYPE_ALIAS));
-		}
-
-		@Test
-		void shouldMatchNothingAfterMigration() {
-			migration.migrateVorgangs(template);
-
-			assertThat(template.count(migration.buildQuery(), MigrationDbTestUtils.VORGANG_COLLECTION)).isZero();
-		}
-
-		private List<Document> getVorgangs() {
-			return template.findAll(Document.class, MigrationDbTestUtils.VORGANG_COLLECTION);
-		}
-	}
-
-	@Nested
-	class TestMigrateVorgangAttachedItems {
-		@BeforeEach
-		void persistItem() {
-			template.save(buildDocument("de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem"),
-					MigrationDbTestUtils.VORGANG_ATTACHED_ITEM_COLLECTION);
-		}
-
-		@Test
-		void shouldUpdateTypeAttributeKey() {
-			migration.migrateVorgangAttachedItems(template);
-
-			assertThat(getItems()).isNotEmpty()
-					.allMatch(doc -> Objects.equals(doc.getString(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE), M011_FixTypeAlias.ITEM_TYPE_ALIAS));
-		}
-
-		@Test
-		void shouldMatchNothingAfterMigration() {
-			migration.migrateVorgangAttachedItems(template);
-
-			assertThat(template.count(migration.buildQuery(), MigrationDbTestUtils.VORGANG_ATTACHED_ITEM_COLLECTION)).isZero();
-		}
-
-		private List<Document> getItems() {
-			return template.findAll(Document.class, MigrationDbTestUtils.VORGANG_ATTACHED_ITEM_COLLECTION);
-		}
-	}
-
-	private Document buildDocument(String typeKeyValue) {
-		var doc = new Document();
-		doc.put(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE, typeKeyValue);
-		return doc;
-	}
-
-	@Nested
-	class TestMigrateClientAttributes {
-
-		private static final String FIELD_CLIENT_ATTRIBUTES = "clientAttributes";
-		private static final String FIELD_CLIENT_NAME = "KopNachrichtenManager";
-		private static final String FIELD_ATTRIBUTE_NAME_HASNACHRICHT = "hasPostfachNachricht";
-		private static final String FIELD_ATTRIBUTE_NAME_NEWNACHRICHT = "hasNewPostfachNachricht";
-		private static final String FIELD_ATTRIBUTE_NAME_WIEDERVORLAGE = "nextWiedervorlageFrist";
-
-		@BeforeEach
-		void persistAttribute() {
-			template.save(buildVorgangWithAttribute(), MigrationDbTestUtils.VORGANG_COLLECTION);
-		}
-
-		@Test
-		void shouldUpdateTypeAttributeKeys() {
-			migration.migrateClientAttributes(template);
-
-			assertThat(getClientAttributes()).isNotEmpty().allMatch(this::areTypeAliasMigrated);
-		}
-
-		@Test
-		void shouldMatchNothingAfterMigration() {
-			migration.migrateClientAttributes(template);
-
-			assertThat(countMatch("hasPostfachNachricht")).isZero();
-			assertThat(countMatch("hasNewPostfachNachricht")).isZero();
-		}
-
-		@Test
-		void shouldUpdateForGoofyAsClient() {
-			template.save(buildVorgangWithWiedervorlageAttribute(), MigrationDbTestUtils.VORGANG_COLLECTION);
-
-			migration.migrateClientAttributes(template);
-
-			assertThat(getClientAttributes("Goofy")).isNotEmpty().allMatch(doc -> Objects.equals(
-					((Document) doc.get(FIELD_ATTRIBUTE_NAME_WIEDERVORLAGE)).get(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE),
-					M011_FixTypeAlias.ATTRIBUTE_TYPE_ALIAS));
-		}
-
-		private long countMatch(String attributeName) {
-			String fieldPathTemplate = "clientAttributes.KopNachrichtenManager.%s._class";
-
-			return template.count(migration.buildQueryForAttributes(String.format(fieldPathTemplate, attributeName)),
-					MigrationDbTestUtils.VORGANG_COLLECTION);
-		}
-
-		private boolean areTypeAliasMigrated(Document attributesDoc) {
-			var hasNachrichtDoc = (Document) attributesDoc.get(FIELD_ATTRIBUTE_NAME_HASNACHRICHT);
-			var hasNewNachrichtDoc = (Document) attributesDoc.get(FIELD_ATTRIBUTE_NAME_NEWNACHRICHT);
-
-			return Objects.equals(hasNachrichtDoc.get(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE), M011_FixTypeAlias.ATTRIBUTE_TYPE_ALIAS)
-					&& Objects.equals(hasNewNachrichtDoc.get(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE), M011_FixTypeAlias.ATTRIBUTE_TYPE_ALIAS);
-		}
-
-		private Stream<Document> getClientAttributes() {
-			return getClientAttributes(FIELD_CLIENT_NAME);
-		}
-
-		private Stream<Document> getClientAttributes(String clientName) {
-			var vorgangs = template.findAll(Document.class, MigrationDbTestUtils.VORGANG_COLLECTION);
-			return vorgangs.stream()
-					.map(vorgangDoc -> (Document) vorgangDoc.get(FIELD_CLIENT_ATTRIBUTES))
-					.map(attributesDoc -> (Document) attributesDoc.get(clientName))
-					.filter(Objects::nonNull);
-		}
-
-		private Document buildVorgangWithWiedervorlageAttribute() {
-			var doc = new Document();
-
-			var attributes = new Document();
-			doc.put(FIELD_CLIENT_ATTRIBUTES, attributes);
-
-			var nachrichtenManager = new Document();
-			attributes.put("Goofy", nachrichtenManager);
-
-			var hasNachricht = new Document();
-			hasNachricht.put(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE, "de.itvsh.ozg.pluto.clientattribute.ClientAttribute");
-			nachrichtenManager.put(FIELD_ATTRIBUTE_NAME_WIEDERVORLAGE, hasNachricht);
-
-			return doc;
-		}
-
-		private Document buildVorgangWithAttribute() {
-			var doc = new Document();
-
-			var attributes = new Document();
-			doc.put(FIELD_CLIENT_ATTRIBUTES, attributes);
-
-			var nachrichtenManager = new Document();
-			attributes.put(FIELD_CLIENT_NAME, nachrichtenManager);
-
-			var hasNachricht = new Document();
-			hasNachricht.put(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE, "de.itvsh.ozg.pluto.clientattribute.ClientAttribute");
-			nachrichtenManager.put(FIELD_ATTRIBUTE_NAME_HASNACHRICHT, hasNachricht);
-
-			var hasNewNachricht = new Document();
-			hasNewNachricht.put(M011_FixTypeAlias.TYPEKEY_ATTRIBUTE, "de.itvsh.ozg.pluto.clientattribute.ClientAttribute");
-			nachrichtenManager.put(FIELD_ATTRIBUTE_NAME_NEWNACHRICHT, hasNewNachricht);
-
-			return doc;
-		}
-	}
-}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M012_MigrationUserIdITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M012_MigrationUserIdITCase.java
deleted file mode 100644
index b4a94d007ec6c709d7e9b660d1d359ebfa31e320..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/M012_MigrationUserIdITCase.java
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.util.List;
-import java.util.UUID;
-
-import org.bson.Document;
-import org.bson.types.ObjectId;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.mock.mockito.SpyBean;
-import org.springframework.core.env.Environment;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.test.util.ReflectionTestUtils;
-import org.springframework.web.client.HttpClientErrorException;
-import org.springframework.web.client.RestTemplate;
-
-import de.itvsh.kop.common.test.DataITCase;
-
-@DataITCase
-class M012_MigrationUserIdITCase {
-
-	private final static String USER_MANAGER_URL = "userManagerUrlForTest";
-
-	@SpyBean
-	private M012_MigrationUserId migration;
-
-	@Autowired
-	private MigrationDbTestUtils dbUtils;
-
-	@Autowired
-	private MongoTemplate template;
-
-	@Mock
-	private RestTemplate restTemplate;
-
-	@DisplayName("Migrate")
-	@Nested
-	class TestMigration {
-
-		@Mock
-		private Environment env;
-
-		@BeforeEach
-		void init() {
-			ReflectionTestUtils.setField(migration, "restTemplate", restTemplate);
-		}
-
-		@Test
-		void shouldInitMigration() {
-			when(env.getProperty(anyString())).thenReturn(USER_MANAGER_URL);
-
-			migration.doMigration(template, env);
-
-			verify(migration, never()).logUrlIsNotConfigured();
-		}
-
-		@Test
-		void shouldNotInitMigration() {
-			migration.doMigration(template, env);
-
-			verify(migration).logUrlIsNotConfigured();
-		}
-
-		@DisplayName("vorgang assignedTo")
-		@Nested
-		class TestMigrateAssignedTo {
-
-			private final static String ASSIGNED_TO = UUID.randomUUID().toString();
-			private final static String NEW_ASSIGNED_TO = new ObjectId().toHexString();
-
-			private Document vorgang;
-
-			@BeforeEach
-			void init() {
-				dbUtils.dropVorgangCollection();
-
-				vorgang = dbUtils.saveVorgang(createVorgangWithAssignedTo());
-			}
-
-			@SuppressWarnings("unchecked")
-			@Test
-			void shouldMigrateOnValidResponse() {
-				ResponseEntity<Object> response = mock(ResponseEntity.class);
-				when(response.getBody()).thenReturn(NEW_ASSIGNED_TO);
-				when(restTemplate.getForEntity(anyString(), any())).thenReturn(response);
-
-				migrateAssignedTo();
-
-				assertThat(loadVorgang()).containsEntry(M012_MigrationUserId.ASSIGNED_TO_FIELD, NEW_ASSIGNED_TO);
-			}
-
-			@DisplayName("on exception")
-			@Nested
-			class TestOnException {
-
-				@Test
-				void shouldProceed() {
-					mockHttpNotFound();
-
-					migrateAssignedTo();
-
-					assertThat(loadVorgang()).containsEntry(M012_MigrationUserId.ASSIGNED_TO_FIELD, ASSIGNED_TO);
-				}
-
-				@Test
-				void shouldLogOnHttpNotFound() {
-					mockHttpNotFound();
-
-					migrateAssignedTo();
-
-					verify(migration).logNotFoundException(any(), any());
-				}
-
-				@Test
-				void shouldLogOnHttpError() {
-					mockHttpError();
-
-					migrateAssignedTo();
-
-					verify(migration).logHttpException(any(), any());
-				}
-			}
-
-			private void migrateAssignedTo() {
-				migration.migrateAssignedTo();
-			}
-
-			private Document loadVorgang() {
-				return dbUtils.getVorgang(MigrationTestUtils.getObjectId(vorgang));
-			}
-
-			@DisplayName("find all vorgaenge with assignedTo field filled")
-			@Nested
-			class TestFindVorgangWithFilledAssignedTo {
-
-				@BeforeEach
-				void mock() {
-					dbUtils.dropVorgangCollection();
-					dbUtils.dropVorgangAttachedItemCollection();
-				}
-
-				@Test
-				void shouldFindWithOldAssignedToData() {
-					dbUtils.saveVorgang(createVorgangWithAssignedTo());
-
-					var vorgaenge = findVorgang();
-
-					assertThat(vorgaenge).hasSize(1);
-					assertThat(vorgaenge.get(0)).containsEntry(M012_MigrationUserId.ASSIGNED_TO_FIELD, ASSIGNED_TO);
-				}
-
-				@Test
-				void shouldReturnEmptyListOnNewAssignedToData() {
-					dbUtils.saveVorgang(new Document(M012_MigrationUserId.ASSIGNED_TO_FIELD, NEW_ASSIGNED_TO));
-
-					var vorgaenge = findVorgang();
-
-					assertThat(vorgaenge).isEmpty();
-				}
-
-				private List<Document> findVorgang() {
-					return template.find(migration.createFindVorgangWithFilledAssignedToQuery(), Document.class,
-							M012_MigrationUserId.COLLECTION_VORGANG_NAME);
-				}
-			}
-
-			private Document createVorgangWithAssignedTo() {
-				return new Document(M012_MigrationUserId.ASSIGNED_TO_FIELD, ASSIGNED_TO);
-			}
-		}
-
-		@DisplayName("command createdBy")
-		@Nested
-		class TestMigrateCreatedBy {
-
-			private final static String CREATED_BY = UUID.randomUUID().toString();
-			private final static String NEW_CREATED_BY = new ObjectId().toHexString();
-
-			private Document command;
-
-			@BeforeEach
-			void init() {
-				dbUtils.dropCommandCollection();
-
-				command = dbUtils.saveCommand(createCommandWithCreatedBy());
-			}
-
-			@SuppressWarnings("unchecked")
-			@Test
-			void shouldMigrateOnValidResponse() {
-				ResponseEntity<Object> response = mock(ResponseEntity.class);
-				when(response.getBody()).thenReturn(NEW_CREATED_BY);
-				when(restTemplate.getForEntity(anyString(), any())).thenReturn(response);
-
-				migrateCreatedBy();
-
-				assertThat(loadCommand()).containsEntry(M012_MigrationUserId.CREATED_BY_FIELD, NEW_CREATED_BY);
-			}
-
-			@DisplayName("on exception")
-			@Nested
-			class TestOnException {
-				@Test
-				void shouldProceed() {
-					mockHttpNotFound();
-
-					migrateCreatedBy();
-
-					assertThat(loadCommand()).containsEntry(M012_MigrationUserId.CREATED_BY_FIELD, CREATED_BY);
-				}
-
-				@Test
-				void shouldLogOnNotFound() {
-					mockHttpNotFound();
-
-					migrateCreatedBy();
-
-					verify(migration).logNotFoundException(any(), any());
-				}
-
-				@Test
-				void shouldLogOnHttpError() {
-					mockHttpError();
-
-					migrateCreatedBy();
-
-					verify(migration).logHttpException(any(), any());
-				}
-			}
-
-			private void migrateCreatedBy() {
-				migration.migrateCommandCreatedBy();
-			}
-
-			private Document loadCommand() {
-				return dbUtils.getCommand(MigrationTestUtils.getObjectId(command));
-			}
-
-			@DisplayName("find all commands with createdBy field filled")
-			@Nested
-			class TestFindCommandWithFilledCreatedBy {
-
-				@BeforeEach
-				void mock() {
-					dbUtils.dropCommandCollection();
-				}
-
-				@Test
-				void shouldFindWithOldCreatedByData() {
-					dbUtils.saveCommand(createCommandWithCreatedBy());
-
-					var commands = findCommand();
-
-					assertThat(commands).hasSize(1);
-					assertThat(commands.get(0)).containsEntry(M012_MigrationUserId.CREATED_BY_FIELD, CREATED_BY);
-				}
-
-				@Test
-				void shouldReturnEmptyListOnNewCreatedByData() {
-					dbUtils.saveVorgang(new Document(M012_MigrationUserId.CREATED_BY_FIELD, NEW_CREATED_BY));
-
-					var commands = findCommand();
-
-					assertThat(commands).isEmpty();
-				}
-
-				private List<Document> findCommand() {
-					return template.find(migration.createFindCommandWithCreatedByQuery(), Document.class,
-							M012_MigrationUserId.COLLECTION_COMMAND_NAME);
-				}
-			}
-
-			private static Document createCommandWithCreatedBy() {
-				return new Document(M012_MigrationUserId.CREATED_BY_FIELD, CREATED_BY);
-			}
-		}
-
-		@DisplayName("vorgangAttachedItem createdBy")
-		@Nested
-		class TestAttachedItemCreatedBy {
-
-			private static final String SYSTEM_NOTIFICATION_MANAGER_NEW_VORGANG = "system-notification_manager-new_vorgang";
-			private final static String CREATED_BY = UUID.randomUUID().toString();
-			private final static String NEW_CREATED_BY = new ObjectId().toHexString();
-
-			private Document vorganAttachedItem;
-
-			@BeforeEach
-			void init() {
-				dbUtils.dropVorgangAttachedItemCollection();
-
-				vorganAttachedItem = dbUtils.saveVorgangAttachedItem(createVorgangAttachedItemWithCreatedBy(CREATED_BY));
-			}
-
-			@Test
-			void shouldMigrateOnValidResponse() {
-				doReturn(NEW_CREATED_BY).when(migration).getInternalId(anyString());
-
-				migrateVorgangAttachedItemCreatedBy();
-
-				assertThat(((Document) loadVorgangAttachedItem().get(M012_MigrationUserId.VORGANG_ATTACHED_ITEM_ITEM_FIELD)))
-						.containsEntry(M012_MigrationUserId.CREATED_BY_FIELD, NEW_CREATED_BY);
-			}
-
-			@Test
-			void shouldNotMigrateOnSystemUser() {
-				dbUtils.dropVorgangAttachedItemCollection();
-				vorganAttachedItem = dbUtils
-						.saveVorgangAttachedItem(createVorgangAttachedItemWithCreatedBy(SYSTEM_NOTIFICATION_MANAGER_NEW_VORGANG));
-
-				migrateVorgangAttachedItemCreatedBy();
-
-				verify(migration, never()).getInternalId(any());
-			}
-
-			@DisplayName("on exception")
-			@Nested
-			class TestOnException {
-				@Test
-				void shouldProceedOnNotFound() {
-					mockHttpNotFound();
-
-					migrateVorgangAttachedItemCreatedBy();
-
-					assertThat((Document) loadVorgangAttachedItem().get(M012_MigrationUserId.VORGANG_ATTACHED_ITEM_ITEM_FIELD))
-							.containsEntry(M012_MigrationUserId.CREATED_BY_FIELD, CREATED_BY);
-				}
-
-				@Test
-				void shouldLogOnNotFound() {
-					mockHttpNotFound();
-
-					migrateVorgangAttachedItemCreatedBy();
-
-					verify(migration).logNotFoundException(any(), any());
-				}
-
-				@Test
-				void shouldLogOnHttpError() {
-					mockHttpError();
-
-					migrateVorgangAttachedItemCreatedBy();
-
-					verify(migration).logHttpException(any(), any());
-				}
-			}
-
-			private void migrateVorgangAttachedItemCreatedBy() {
-				migration.migrateVorgangAttachedItemCreatedBy();
-			}
-
-			private Document loadVorgangAttachedItem() {
-				return dbUtils.getVorgangAttachedItem(MigrationTestUtils.getObjectId(vorganAttachedItem));
-			}
-
-			@DisplayName("find all vorgangAttachedItem with createdBy field filled")
-			@Nested
-			class TestFindVorgangAttachedItemWithFilledCreatedBy {
-
-				@BeforeEach
-				void mock() {
-					dbUtils.dropVorgangAttachedItemCollection();
-				}
-
-				@Test
-				void shouldFindWithOldCreatedByData() {
-					dbUtils.saveVorgangAttachedItem(createVorgangAttachedItemWithCreatedBy(CREATED_BY));
-
-					var vorgangAttachedItems = findVorgangAttachedItem();
-
-					assertThat(vorgangAttachedItems).hasSize(1);
-					assertThat(((Document) vorgangAttachedItems.get(0).get(M012_MigrationUserId.VORGANG_ATTACHED_ITEM_ITEM_FIELD)))
-							.containsEntry(M012_MigrationUserId.CREATED_BY_FIELD, CREATED_BY);
-				}
-
-				@Test
-				void shouldReturnEmptyListOnNewCreatedByData() {
-					dbUtils.saveVorgangAttachedItem(new Document(M012_MigrationUserId.VORGANG_ATTACHED_ITEM_ITEM_FIELD,
-							new Document(M012_MigrationUserId.CREATED_BY_FIELD, NEW_CREATED_BY)));
-
-					var vorgangAttachedItems = findVorgangAttachedItem();
-
-					assertThat(vorgangAttachedItems).isEmpty();
-				}
-
-				private List<Document> findVorgangAttachedItem() {
-					return template.find(migration.createFindVorgangAttachedItemdWithCreatedByQuery(), Document.class,
-							M012_MigrationUserId.COLLECTION_VORGANG_ATTACHED_ITEM_NAME);
-				}
-			}
-
-			private static Document createVorgangAttachedItemWithCreatedBy(String createdById) {
-				return new Document(M012_MigrationUserId.VORGANG_ATTACHED_ITEM_ITEM_FIELD,
-						new Document(M012_MigrationUserId.CREATED_BY_FIELD, createdById));
-			}
-		}
-	}
-
-	private void mockHttpNotFound() {
-		when(restTemplate.getForEntity(anyString(), any())).thenThrow(new HttpClientErrorException(HttpStatus.NOT_FOUND));
-	}
-
-	private void mockHttpError() {
-		when(restTemplate.getForEntity(anyString(), any())).thenThrow(new HttpClientErrorException(HttpStatus.BAD_GATEWAY));
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationAttachmentTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationAttachmentTestFactory.java
deleted file mode 100644
index acd5b0c60f1cdfe4627546f94544ee5cd0c0e6a1..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationAttachmentTestFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.List;
-import java.util.UUID;
-
-import org.bson.Document;
-
-import com.thedeanda.lorem.LoremIpsum;
-
-class MigrationAttachmentTestFactory {
-
-	static final String FIELD_NAME = "name";
-	static final String NAME = LoremIpsum.getInstance().getName();
-
-	static final String FIELD_FILES = "files";
-
-	static final String ATTACHMENT_FILE_ID = UUID.randomUUID().toString();
-	static final String ATTACHMENT_FILE_NAME = LoremIpsum.getInstance().getName();
-
-	static final String ATTACHMENT_FILE_ID2 = UUID.randomUUID().toString();
-	static final String ATTACHMENT_FILE_NAME2 = LoremIpsum.getInstance().getName();
-
-	static Document create() {
-		var incomingFileGroup = new Document();
-		incomingFileGroup.put(FIELD_NAME, NAME);
-		incomingFileGroup.put(FIELD_FILES, List.of(
-				createAttachment(ATTACHMENT_FILE_ID, ATTACHMENT_FILE_NAME),
-				createAttachment(ATTACHMENT_FILE_ID2, ATTACHMENT_FILE_NAME2)));
-
-		return incomingFileGroup;
-	}
-
-	private static Document createAttachment(String id, String name) {
-		var attachmentFile = MigrationIncomingFileTestFactory.create();
-		attachmentFile.remove(MigrationIncomingFileTestFactory.FIELD_ID);
-		attachmentFile.put(MigrationIncomingFileTestFactory.FIELD_ID, id);
-		attachmentFile.remove(MigrationIncomingFileTestFactory.FIELD_NAME);
-		attachmentFile.put(MigrationIncomingFileTestFactory.FIELD_NAME, name);
-		return attachmentFile;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationBinaryFileTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationBinaryFileTestFactory.java
deleted file mode 100644
index f276a27886cc19ef2a3ae899bd94e92cc037ee17..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationBinaryFileTestFactory.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.List;
-
-import org.bson.Document;
-import org.bson.types.Binary;
-import org.bson.types.ObjectId;
-
-class MigrationBinaryFileTestFactory {
-
-	public final static String FIELD_VORGANG_ID = "vorgangId";
-	public final static String VORGANG_ID = new ObjectId().toHexString();
-
-	public final static String FIELD_CLIENT = "client";
-	public final static String CLIENT = "MailService";
-
-	public final static String FIELD_FIELD = "field";
-	public final static String FIELD = "files";
-
-	public final static String FIELD_FILE = "file";
-
-	public static Document create() {
-		var binaryFileDoc = new Document();
-		binaryFileDoc.put(FIELD_VORGANG_ID, VORGANG_ID);
-		binaryFileDoc.put(FIELD_CLIENT, CLIENT);
-		binaryFileDoc.put(FIELD_FIELD, FIELD);
-		binaryFileDoc.put(FIELD_FILE, createFile());
-
-		return binaryFileDoc;
-	}
-
-	public static Document createFile() {
-		var file = MigrationIncomingFileTestFactory.create();
-		file.put(MigrationIncomingFileTestFactory.FIELD_CONTENT, List.of(new Binary(MigrationIncomingFileTestFactory.CONTENT)));
-
-		return file;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationDbTestUtils.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationDbTestUtils.java
deleted file mode 100644
index fb75cde8774e91a2797c8fa95c2d508443371513..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationDbTestUtils.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.List;
-
-import org.bson.Document;
-import org.bson.types.ObjectId;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.mongodb.gridfs.GridFsResource;
-import org.springframework.data.mongodb.gridfs.GridFsTemplate;
-import org.springframework.stereotype.Component;
-
-import com.mongodb.client.gridfs.model.GridFSFile;
-
-@Component
-class MigrationDbTestUtils {
-
-	public static final String COMMAND_COLLECTION = "command";
-	public static final String VORGANG_COLLECTION = "vorgang";
-	public static final String VORGANG_ATTACHED_ITEM_COLLECTION = "vorgangAttachedItem";
-	public static final String BINARY_FILE_COLLECTION = "binaryFile";
-
-	public static final String GRID_FS_CHUNKS_COLLECTION = "fs.chunk";
-	public static final String GRID_FS_FILES_COLLECTION = "fs.files";
-
-	@Autowired
-	private MongoTemplate template;
-
-	public Document saveCommand(Document doc) {
-		return template.save(doc, COMMAND_COLLECTION);
-	}
-
-	public Document getCommand(ObjectId id) {
-		return template.findById(id, Document.class, COMMAND_COLLECTION);
-	}
-
-	public void dropCommandCollection() {
-		template.dropCollection(COMMAND_COLLECTION);
-	}
-
-	public void dropVorgangCollection() {
-		template.dropCollection(VORGANG_COLLECTION);
-	}
-
-	public Document getVorgang(ObjectId id) {
-		return template.findById(id, Document.class, VORGANG_COLLECTION);
-	}
-
-	public Document saveVorgang(Document doc) {
-		return template.save(doc, VORGANG_COLLECTION);
-	}
-
-	public Document saveVorgangAttachedItem(Document doc) {
-		return template.save(doc, VORGANG_ATTACHED_ITEM_COLLECTION);
-	}
-
-	public Document getVorgangAttachedItem(ObjectId id) {
-		return template.findById(id, Document.class, VORGANG_ATTACHED_ITEM_COLLECTION);
-	}
-
-	public void dropVorgangAttachedItemCollection() {
-		template.dropCollection(VORGANG_ATTACHED_ITEM_COLLECTION);
-	}
-
-	/**
-	 * @param template
-	 * 
-	 * @deprecated Inject MigrationDbTestUtils and use {@link #saveVorgang()}
-	 *             instead.
-	 */
-	@Deprecated
-	public static Document saveVorgang(MongoTemplate template, Document doc) {
-		return template.save(doc, VORGANG_COLLECTION);
-	}
-
-	/**
-	 * @param template
-	 * 
-	 * @deprecated Inject MigrationDbTestUtils and use
-	 *             {@link #saveVorgangAttachedItem()} instead.
-	 */
-	public static Document saveVorgangAttachedItem(MongoTemplate template, Document doc) {
-		return template.save(doc, VORGANG_ATTACHED_ITEM_COLLECTION);
-	}
-
-	public static Document getBinaryFile(MongoTemplate template, String id) {
-		return template.findById(id, Document.class, BINARY_FILE_COLLECTION);
-	}
-
-	public static List<Document> findBinaryFile(MongoTemplate template, Query query) {
-		return template.find(query, Document.class, BINARY_FILE_COLLECTION);
-	}
-
-	public static Document saveBinaryFile(MongoTemplate template, Document doc) {
-		return template.save(doc, BINARY_FILE_COLLECTION);
-	}
-
-	/**
-	 * @param template
-	 * 
-	 * @deprecated Inject MigrationDbTestUtils and use {@link #getVorgang()}
-	 *             instead.
-	 */
-	@Deprecated
-	public static Document getVorgang(MongoTemplate template, ObjectId id) {
-		return template.findById(id, Document.class, MigrationDbTestUtils.VORGANG_COLLECTION);
-	}
-
-	public static List<Document> getVorgangAttachedItem(MongoTemplate template, String fieldKey, String fieldValue) {
-		return template.find(new Query(Criteria.where(fieldKey).is(fieldValue)), Document.class, VORGANG_ATTACHED_ITEM_COLLECTION);
-	}
-
-	public static void dropBinaryFileCollection(MongoTemplate template) {
-		template.dropCollection(BINARY_FILE_COLLECTION);
-	}
-
-	/**
-	 * @param template
-	 * 
-	 * @deprecated Inject MigrationDbTestUtils and use
-	 *             {@link #dropVorgangCollection()} instead.
-	 */
-	@Deprecated
-	public static void dropVorgangCollection(MongoTemplate template) {
-		template.dropCollection(VORGANG_COLLECTION);
-	}
-
-	/**
-	 * @param template
-	 * 
-	 * @deprecated Inject MigrationDbTestUtils and use
-	 *             {@link #dropVorgangAttachedItemCollection()} instead.
-	 */
-	@Deprecated
-	public static void dropVorgangAttachedItemCollection(MongoTemplate template) {
-		template.dropCollection(VORGANG_ATTACHED_ITEM_COLLECTION);
-	}
-
-	public static GridFsResource getGridFsResource(GridFsTemplate template, ObjectId id) {
-		return template.getResource(getGridFsFile(template, id));
-	}
-
-	public static GridFSFile getGridFsFile(GridFsTemplate template, ObjectId id) {
-		return template.findOne(Query.query(Criteria.where(MigrationTestUtils.FIELD_OBJECT_ID).is(id)));
-	}
-
-	public static GridFSFile getGridFsFile(GridFsTemplate template, String filename) {
-		return template.findOne(Query.query(Criteria.where(MigrationGridFSFileTestFactory.FIELD_FILE_NAME).is(filename)));
-	}
-}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangHeaderTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangHeaderTestFactory.java
deleted file mode 100644
index b40f1679d22237eac4c526fb9464bef219527efd..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangHeaderTestFactory.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.UUID;
-
-import org.bson.Document;
-
-import com.thedeanda.lorem.LoremIpsum;
-
-class MigrationEingangHeaderTestFactory {
-
-	public static final String FIELD_REQUEST_ID = "requestId";
-	public static final String REQUEST_ID = UUID.randomUUID().toString();
-
-	public static final String FIELD_CREATED_AT = "createdAt";
-	public static final String CREATED_AT_STR = "2021-01-10T10:30:00Z";
-
-	public static final String FIELD_FORM_NAME = "formName";
-	public static final String FORM_NAME = LoremIpsum.getInstance().getWords(10);
-
-	public static final String FIELD_FORM_ID = "formId";
-	public static final String FORM_ID = FORM_NAME;
-
-	public static final String FIELD_SENDER = "sender";
-	private static final String SENDER = LoremIpsum.getInstance().getWords(2);
-
-	public static final String FIELD_CUSTOMER = "customer";
-	private static final String CUSTOMER = LoremIpsum.getInstance().getWords(2);
-
-	public static final String FIELD_CUSTOMER_ID = "customerId";
-	private static final String CUSTOMER_ID = UUID.randomUUID().toString();
-
-	public static final String FIELD_CLIENT = "client";
-	private static final String CLIENT = LoremIpsum.getInstance().getWords(2);
-
-	public static final String FIELD_CLIENT_ID = "clientId";
-	public static final String CLIENT_ID = UUID.randomUUID().toString();
-
-	public static Document create() {
-		var eingangHeader = new Document();
-		eingangHeader.put(FIELD_REQUEST_ID, REQUEST_ID);
-		eingangHeader.put(FIELD_CREATED_AT, CREATED_AT_STR);
-		eingangHeader.put(FIELD_FORM_NAME, FORM_NAME);
-		eingangHeader.put(FIELD_FORM_ID, FORM_ID);
-		eingangHeader.put(FIELD_SENDER, SENDER);
-		eingangHeader.put(FIELD_CUSTOMER, CUSTOMER);
-		eingangHeader.put(FIELD_CUSTOMER_ID, CUSTOMER_ID);
-		eingangHeader.put(FIELD_CLIENT, CLIENT);
-		eingangHeader.put(FIELD_CLIENT_ID, CLIENT_ID);
-
-		return eingangHeader;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangTestFactory.java
deleted file mode 100644
index 7a091c2e3a66e3d63bb2a1ec35e2c0ae9b05d413..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationEingangTestFactory.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.UUID;
-
-import org.bson.Document;
-
-class MigrationEingangTestFactory {
-
-	static final String FIELD_ID = "_id";
-	static final String ID = UUID.randomUUID().toString();
-
-	static final String FIELD_HEADER = "header";
-	static final String FIELD_ANTRAGSTELLER = "antragsteller";
-	static final String FIELD_ZUSTAENDIDGESTELLE = "zustaendigeStelle";
-	static final String FIELD_REPRESENTATIONS = "representations";
-	static final String FIELD_NUMBER_OF_REPRESENTATIONS = "numberOfRepresentations";
-	static final String FIELD_ATTACHMENTS = "attachments";
-	static final String FIELD_NUMBER_OF_ATTACHMENTS = "numberOfAttachments";
-	static final String FIELD_FORMDATA = "formData";
-
-	static Document create() {
-		var eingang = new Document();
-		eingang.put(FIELD_ID, ID);
-		eingang.put(FIELD_HEADER, MigrationEingangHeaderTestFactory.create());
-		eingang.put(FIELD_ANTRAGSTELLER, new Document());
-		eingang.put(FIELD_ZUSTAENDIDGESTELLE, MigrationZustaendigeStelleTestFactory.create());
-		eingang.put(FIELD_ATTACHMENTS, List.of(MigrationAttachmentTestFactory.create()));
-		eingang.put(FIELD_NUMBER_OF_ATTACHMENTS, 2);
-		eingang.put(FIELD_REPRESENTATIONS, List.of(MigrationIncomingFileTestFactory.create()));
-		eingang.put(FIELD_NUMBER_OF_REPRESENTATIONS, 1);
-		eingang.put(FIELD_FORMDATA, new HashMap<String, Object>());
-
-		return eingang;
-	}
-}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationGridFSFileTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationGridFSFileTestFactory.java
deleted file mode 100644
index 65664f0959fb73b479c02abe0d5b00640bb64897..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationGridFSFileTestFactory.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-class MigrationGridFSFileTestFactory {
-
-	public final static String FIELD_CLIENT = "client";
-	public final static String FIELD_VORGANG_ID = "vorgangId";
-	public final static String FIELD_FIELD_NAME = "fieldName";
-	public final static String FIELD_CONTENT_TYPE = "contentType";
-	public final static String FIELD_NAME = "name";
-	public final static String FIELD_FILE_NAME = "filename";
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationIncomingFileTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationIncomingFileTestFactory.java
deleted file mode 100644
index b4917ce63c5a9f9d5e26d94907cb1f6bc984e0c9..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationIncomingFileTestFactory.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.bson.Document;
-import org.bson.types.Binary;
-import org.bson.types.ObjectId;
-
-import de.itvsh.kop.common.test.TestUtils;
-
-class MigrationIncomingFileTestFactory {
-
-	static final String FIELD_ID = "_id";
-	static final String ID = new ObjectId().toHexString();
-
-	static final String FIELD_NAME = "name";
-	static final String NAME = "TestDoc.docx";
-
-	static final String FIELD_CONTENT_TYPE = "contentType";
-	static final String CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
-
-	static final String FIELD_SIZE = "size";
-	static final long SIZE;
-
-	static final String FIELD_CONTENT = "content";
-	static final byte[] CONTENT;
-
-	static {
-		CONTENT = initContent();
-		SIZE = CONTENT.length;
-	}
-
-	private static byte[] initContent() {
-		try (InputStream in = TestUtils.loadFile(NAME)) {
-			byte[] fileData = new byte[in.available()];
-			in.read(fileData);
-
-			return fileData;
-		} catch (IOException e) {
-			throw new IllegalStateException("Error reading test file " + NAME);
-		}
-	}
-
-	static Document create() {
-		var incomingFile = new Document();
-		incomingFile.put(FIELD_ID, ID);
-		incomingFile.put(FIELD_NAME, NAME);
-		incomingFile.put(FIELD_CONTENT_TYPE, CONTENT_TYPE);
-		incomingFile.put(FIELD_SIZE, SIZE);
-		incomingFile.put(FIELD_CONTENT, new Binary(CONTENT));
-
-		return incomingFile;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationKommentarTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationKommentarTestFactory.java
deleted file mode 100644
index 10c902c1a5660a6efb833463e2c37f74bd08f85f..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationKommentarTestFactory.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.Date;
-import java.util.UUID;
-
-import org.bson.Document;
-
-import com.thedeanda.lorem.LoremIpsum;
-
-public class MigrationKommentarTestFactory {
-
-	public static final String ID_FIELD = "id";
-
-	public static final String VORGANG_ID_FIELD = "vorgangId";
-	public static final String VORGANG_ID = UUID.randomUUID().toString();
-
-	public static final String CREATED_AT_FIELD = "createdAt";
-	public static final Date CREATED_AT = new Date();
-	public static final String CREATED_AT_STR = ZonedDateTime.ofInstant(CREATED_AT.toInstant(), ZoneId.of("UTC")).toString();
-
-	public static final String CREATED_BY_FIELD = "createdBy";
-	public static final String CREATED_BY = UUID.randomUUID().toString();
-
-	public static final String TEXT_FIELD = "text";
-	public static final String TEXT = LoremIpsum.getInstance().getWords(20);
-
-	public static Document create() {
-		var kommentar = new Document();
-		kommentar.put(VORGANG_ID_FIELD, VORGANG_ID);
-		kommentar.put(CREATED_AT_FIELD, CREATED_AT);
-		kommentar.put(CREATED_BY_FIELD, CREATED_BY);
-		kommentar.put(TEXT_FIELD, TEXT);
-
-		return kommentar;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangAttachedItemTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangAttachedItemTestFactory.java
deleted file mode 100644
index b2619fb0f54cfd1b25c98014e5b42fd91919a3ff..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangAttachedItemTestFactory.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.Collections;
-
-import org.bson.Document;
-
-class MigrationVorgangAttachedItemTestFactory {
-
-	public final static String FIELD_CLIENT = "client";
-	public final static String CLIENT = "MailService";
-
-	public final static String FIELD_ITEM_NAME = "itemName";
-	public final static String ITEM_NAME = "files";
-
-	public final static String FIELD_ITEM = "item";
-
-	public final static String VERSION_FIELD = "version";
-	public final static int VERSION = 0;
-
-	public static Document create() {
-		var vorgangAttachedItem = new Document();
-		vorgangAttachedItem.put(FIELD_CLIENT, CLIENT);
-		vorgangAttachedItem.put(FIELD_ITEM_NAME, ITEM_NAME);
-		vorgangAttachedItem.put(VERSION_FIELD, VERSION);
-		vorgangAttachedItem.put(FIELD_ITEM, Collections.emptyMap());
-
-		return vorgangAttachedItem;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangTestFactory.java
deleted file mode 100644
index 8c7622ac94a892bdc3bfdfdbd1a7f8f3a607f978..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationVorgangTestFactory.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.List;
-
-import org.bson.Document;
-
-class MigrationVorgangTestFactory {
-
-	static final String FIELD_NAME = "name";
-	static final String NAME = "Test Vorgang";
-
-	static final String FIELD_NUMMER = "nummer";
-	static final String NUMMER = "2342454345654";
-
-	static final String FIELD_STATUS = "status";
-	static final String STATUS = "NEU";
-
-	static final String FIELD_VERSION = "version";
-	static final String VERSION = "0";
-
-	static final String FIELD_EINGANGS = "eingangs";
-
-	static final String FIELD_FORWARDINGS = "forwardings";
-
-	static final String FIELD_IN_CREATION = "inCreation";
-	static final boolean IN_CREATION = false;
-
-	static final String FIELD_WIEDERVORLAGES = "wiedervorlages";
-
-	static final String FIELD_KOMMENTARS = "kommentars";
-
-	static Document create() {
-		var vorgang = new Document();
-		vorgang.put(FIELD_NAME, NAME);
-		vorgang.put(FIELD_NUMMER, NUMMER);
-		vorgang.put(FIELD_STATUS, STATUS);
-		vorgang.put(FIELD_VERSION, VERSION);
-		vorgang.put(FIELD_EINGANGS, List.of(MigrationEingangTestFactory.create()));
-		vorgang.put(FIELD_FORWARDINGS, new Document());
-		vorgang.put(FIELD_IN_CREATION, IN_CREATION);
-
-		return vorgang;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationWiedervorlageTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationWiedervorlageTestFactory.java
deleted file mode 100644
index d041df5817340985662614a7202730c87f229b36..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationWiedervorlageTestFactory.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import java.util.Collections;
-
-import org.bson.Document;
-
-import com.thedeanda.lorem.LoremIpsum;
-
-public class MigrationWiedervorlageTestFactory {
-
-	public final static String FIELD_BETREFF = "betreff";
-	public final static String BETREFF = LoremIpsum.getInstance().getWords(2);
-
-	public final static String FIELD_BESCHREIBUNG = "beschreibung";
-	public final static String BESCHREIBUNG = LoremIpsum.getInstance().getWords(3);
-
-	public final static String FIELD_ATTACHMENTS = "attachments";
-
-	public static Document create() {
-		var wiedervorlage = new Document();
-		wiedervorlage.put(FIELD_BETREFF, BETREFF);
-		wiedervorlage.put(FIELD_BESCHREIBUNG, BESCHREIBUNG);
-		wiedervorlage.put(FIELD_ATTACHMENTS, Collections.emptyList());
-
-		return wiedervorlage;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationZustaendigeStelleTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationZustaendigeStelleTestFactory.java
deleted file mode 100644
index f0cdf392ed3dc20d26eed879d969d5577d57bf76..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationZustaendigeStelleTestFactory.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.migration;
-
-import org.bson.Document;
-
-class MigrationZustaendigeStelleTestFactory {
-
-	public static final String FIELD_ORGANISATIONSEINHEITEN_ID = "organisationseinheitenId";
-	public static final String ORGANISATIONSEINHEIT_ID = "08150815";
-
-	public static final String FIELD_EMAIL = "email";
-	public static final String EMAIL = "hase@loewenkaefig.de";
-
-	static Document create() {
-		var zustaendigeStelle = new Document();
-		zustaendigeStelle.put(FIELD_ORGANISATIONSEINHEITEN_ID, ORGANISATIONSEINHEIT_ID);
-		zustaendigeStelle.put(FIELD_EMAIL, EMAIL);
-
-		return zustaendigeStelle;
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchRequestTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchRequestTestFactory.java
deleted file mode 100644
index bd812f642b26fffafaa14b79ced190d8cdce9d88..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchRequestTestFactory.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.search;
-
-import org.elasticsearch.core.List;
-
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.vorgang.FindVorgangRequestTestFactory;
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelleTestFactory;
-
-class SearchRequestTestFactory {
-	static final int LIMIT = FindVorgangRequestTestFactory.LIMIT;
-	static final int OFFSET = FindVorgangRequestTestFactory.OFFSET;
-
-	static final String QUERY = "vors";
-	static final String ORGANISATIONSEINHEIT_ID = ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID;
-	static final boolean FILTER_BY_ORGANISATIONSEINHEIT_ID = true;
-	static final String ASSIGNED_TO = UserTestFactory.ID;
-
-	static SearchRequest create() {
-		return createBuilder().build();
-	}
-
-	static SearchRequest.SearchRequestBuilder createBuilder() {
-		return SearchRequest.builder()
-				.limit(LIMIT)
-				.offSet(OFFSET)
-				.query(QUERY)
-				.filterByOrganisationseinheitIds(FILTER_BY_ORGANISATIONSEINHEIT_ID)
-				.assignedTo(ASSIGNED_TO)
-				.organisationseinheitIds(List.of(ORGANISATIONSEINHEIT_ID));
-	}
-}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchServiceITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchServiceITCase.java
deleted file mode 100644
index 12ea40ee1ff27662f3a7b6f37e78198782b25e3a..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchServiceITCase.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.search;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-import java.io.IOException;
-import java.util.Optional;
-import java.util.UUID;
-
-import org.bson.types.ObjectId;
-import org.elasticsearch.core.List;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
-import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
-
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandService;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.vorgang.FilterCriteriaTestFactory;
-import de.itvsh.ozg.pluto.vorgang.FindVorgangRequestTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-
-@SearchITCase
-public class SearchServiceITCase {
-	@Autowired
-	private SearchService searchService;
-
-	@Autowired
-	private SearchVorgangRepostitory repostitory;
-
-	@Autowired
-	private ElasticsearchOperations elasticsearchOperations;
-
-	@MockBean
-	private CommandService commandService;
-
-	@Nested
-	class TestAddVorgang {
-		@BeforeEach
-		void init() {
-			elasticsearchOperations.indexOps(IndexedVorgang.class).delete();
-		}
-
-		@Test
-		void shouldAdd() throws IOException {
-			searchService.addVorgang(VorgangTestFactory.create());
-
-			Iterable<IndexedVorgang> vorgangs = repostitory.findAll();
-			assertThat(vorgangs).isNotEmpty();
-		}
-	}
-
-	@Nested
-	class TestUpdateVorgang {
-		@BeforeEach
-		void init() {
-			Command cmd = CommandTestFactory.createBuilder().build();
-			when(commandService.findCommand(CommandTestFactory.ID)).thenReturn(Optional.of(cmd));
-
-			elasticsearchOperations.indexOps(IndexedVorgang.class).delete();
-
-			searchService.addVorgang(VorgangTestFactory.create());
-		}
-
-		@Test
-		void shouldUpdate() throws IOException {
-			var vorgang = VorgangTestFactory.createBuilder().status(Status.ABGESCHLOSSEN).build();
-			searchService.updateVorgang(vorgang);
-
-			Iterable<IndexedVorgang> vorgangs = repostitory.findAll();
-			assertThat(vorgangs).isNotEmpty().hasSize(1);
-			assertThat(vorgangs.iterator().next().getStatus()).isEqualTo(Status.ABGESCHLOSSEN.name());
-		}
-	}
-
-	@Nested
-	class TestSearchVorgang {
-		@BeforeEach
-		void init() {
-			elasticsearchOperations.indexOps(IndexedVorgang.class).delete();
-
-			searchService.addVorgang(VorgangTestFactory.create());
-			searchService.addVorgang(VorgangTestFactory.createBuilder().id(new ObjectId().toHexString()).aktenzeichen("test")
-					.assignedTo(UUID.randomUUID().toString()).build());
-			searchService.addVorgang(VorgangTestFactory.createBuilder().id(new ObjectId().toHexString()).aktenzeichen("vors").build());
-			searchService.addVorgang(VorgangTestFactory.createBuilder().id(new ObjectId().toHexString()).aktenzeichen("vOrsi").build());
-
-			elasticsearchOperations.indexOps(IndexCoordinates.of("other-test")).delete();
-			elasticsearchOperations.indexOps(IndexCoordinates.of("other-test")).create();
-			elasticsearchOperations.save(IndexedVorgangTestFactory.create(), IndexCoordinates.of("other-test"));
-		}
-
-		@Nested
-		class filteredByOrganisationseinheitenId {
-			@Test
-			void shouldFindByAktenzeichen() {
-				var res = searchService.find(FindVorgangRequestTestFactory.createBuilder()
-						.searchBy("vors")
-						.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().assignedTo(null).build())
-						.build());
-
-				assertThat(res).hasSize(2);
-			}
-
-			@Test
-			void shouldFindByAntragstellerName() {
-				var res = searchService
-						.find(FindVorgangRequestTestFactory.createBuilder()
-								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME)
-								.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().assignedTo(null).build())
-								.build());
-
-				assertThat(res).hasSize(4);
-			}
-
-			@Test
-			void shouldFindByAntragstellerNameAndAktenzeichen() {
-				var res = searchService
-						.find(FindVorgangRequestTestFactory.createBuilder()
-								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME + " tes")
-								.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().assignedTo(null).build())
-								.build());
-
-				assertThat(res).hasSize(1);
-			}
-
-			@Test
-			void shouldFindByAntragstellerNameAndereOrganisationEinheitId() {
-				searchService
-						.addVorgang(
-								VorgangTestFactory.createWithOrganisationEinheitId("12345678").toBuilder().id(UUID.randomUUID().toString()).build());
-
-				var res = searchService.find(FindVorgangRequestTestFactory.createBuilder()
-						.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME).filterBy(
-								FilterCriteriaTestFactory.createBuilder()
-										.clearOrganisationseinheitIds()
-										.organisationseinheitIds(List.of("12345678"))
-										.clearStatus().build())
-						.build());
-
-				assertThat(res).hasSize(1);
-			}
-
-			@Test
-			void shouldDoPageination() {
-				var res = searchService
-						.find(FindVorgangRequestTestFactory.createBuilder()
-								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME)
-								.limit(2)
-								.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().build())
-								.build());
-
-				assertThat(res).hasSize(2);
-				assertThat(res.getTotalPages()).isEqualTo(2);
-			}
-		}
-
-		@Nested
-		class filteredForStatus {
-			@Test
-			void shouldFindByAntragstellerName() {
-				searchService
-						.addVorgang(
-								VorgangTestFactory.createWithOrganisationEinheitId("12345678").toBuilder().id(UUID.randomUUID().toString()).build());
-
-				var res = searchService
-						.find(FindVorgangRequestTestFactory.createBuilder()
-								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME)
-								.filterBy(FilterCriteriaTestFactory.createBuilder().filterByOrganisationseinheitenId(false).build())
-								.build());
-
-				assertThat(res).hasSize(5);
-			}
-		}
-
-		@Nested
-		class filteredForStatusAndOrganisationEinheitId {
-			@BeforeEach
-			void init() {
-				searchService
-						.addVorgang(
-								VorgangTestFactory.createWithOrganisationEinheitId("12345678").toBuilder().id(UUID.randomUUID().toString()).build());
-				searchService
-						.addVorgang(VorgangTestFactory.createBuilder().status(Status.ANGENOMMEN).id(UUID.randomUUID().toString()).build());
-			}
-
-			@Test
-			void shouldFindByAktenzeichen() {
-				var res = searchService
-						.find(FindVorgangRequestTestFactory.createBuilder()
-								.searchBy("test")
-								.filterBy(FilterCriteriaTestFactory.createBuilder().assignedTo(null).build())
-								.build());
-
-				assertThat(res).hasSize(1);
-			}
-
-			@Test
-			void shouldFindByAntragstellerName() {
-				var res = searchService
-						.find(FindVorgangRequestTestFactory.createBuilder()
-								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME)
-								.filterBy(FilterCriteriaTestFactory.createBuilder().assignedTo(null).build())
-								.build());
-
-				assertThat(res).hasSize(4);
-			}
-		}
-
-		@Nested
-		class filteredForAssignedToAndOrganisationEinheitId {
-			@BeforeEach
-			void init() {
-				searchService
-						.addVorgang(
-								VorgangTestFactory.createWithOrganisationEinheitId("12345678").toBuilder().id(UUID.randomUUID().toString()).build());
-			}
-
-			@Test
-			void shouldFindByAntragstellerName() {
-				var res = searchService
-						.find(FindVorgangRequestTestFactory.createBuilder()
-								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME)
-								.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().assignedTo(UserTestFactory.ID).build())
-								.build());
-
-				assertThat(res).hasSize(3);
-			}
-		}
-	}
-}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepositoryImplTest.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepositoryImplTest.java
deleted file mode 100644
index 5fc54e134a4688746a6110cdaa418a89f8bf56f2..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepositoryImplTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.common.search;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import org.elasticsearch.core.List;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
-import org.springframework.data.elasticsearch.core.SearchHit;
-import org.springframework.data.elasticsearch.core.SearchHits;
-import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
-
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangHeader;
-import de.itvsh.ozg.pluto.vorgang.VorgangHeaderTestFactory;
-
-class SearchVorgangCustomRepositoryImplTest {
-	@InjectMocks
-	private SearchVorgangCustomRepositoryImpl searchRepostitory;
-
-	@Mock
-	private IndexedVorgangMapper mapper;
-
-	@Mock
-	private SearchProperties properties;
-
-	@Mock
-	private ElasticsearchOperations operations;
-
-	@Nested
-	class TestSearch {
-
-		@Mock
-		private SearchHits<IndexedVorgang> searchHits;
-		@Mock
-		private SearchHit<IndexedVorgang> searchHit;
-
-		@BeforeEach
-		void init() {
-			when(searchHit.getContent()).thenReturn(IndexedVorgangTestFactory.create());
-			when(searchHits.get()).thenReturn(List.of(searchHit).stream());
-			when(operations.search(any(NativeSearchQuery.class), eq(IndexedVorgang.class))).thenReturn(searchHits);
-		}
-
-		@Test
-		void shouldCallSearch() {
-			searchRepostitory.searchBy(SearchRequestTestFactory.create());
-
-			verify(mapper, atLeastOnce()).toVorgangHeader(any());
-			verify(operations).search(any(NativeSearchQuery.class), eq(IndexedVorgang.class));
-		}
-
-		@Test
-		void shouldMapResult() {
-			when(mapper.toVorgangHeader(any())).thenReturn(VorgangHeaderTestFactory.create());
-
-			var res = searchRepostitory.searchBy(SearchRequestTestFactory.create());
-
-			assertThat(res).isNotEmpty().hasAtLeastOneElementOfType(VorgangHeader.class);
-		}
-	}
-
-	@Nested
-	class TestQuery {
-		@Test
-		void shouldHavePaging() {
-			var request = SearchRequestTestFactory.create();
-			var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-			assertThat(query.getPageable()).isNotNull();
-			assertThat(query.getPageable().getOffset()).isZero();
-			assertThat(query.getPageable().getPageSize()).isEqualTo(SearchRequestTestFactory.LIMIT);
-			assertThat(query.getPageable().getSort()).isEqualTo(Sort.unsorted());
-		}
-
-		@Test
-		void shouldHaveFieldsWithWights() {
-			var request = SearchRequestTestFactory.create();
-			var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-			assertThat(query.getQuery()).isNotNull();
-			assertThat(query.getQuery()).asString().contains("aktenzeichen^2.0");
-			assertThat(query.getQuery()).asString().contains("antragstellerName^1.0");
-			assertThat(query.getQuery()).asString().contains("antragstellerVorname^1.0");
-			assertThat(query.getQuery()).asString().contains("vorgangName^0.5");
-			assertThat(query.getQuery()).asString().contains("vorgangNummer^2.0");
-		}
-
-		@Test
-		void shouldHaveSimpleQuery() {
-			var request = SearchRequestTestFactory.create();
-			var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-			assertThat(query.getQuery()).asString().contains("\"query\" : \"(*vors*)\"");
-		}
-
-		@Test
-		void shouldHaveQuery() {
-			var request = SearchRequestTestFactory.createBuilder().query("vors test").build();
-			var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-			assertThat(query.getQuery()).asString().contains("\"query\" : \"(*vors*) AND (*test*)\"");
-		}
-
-		@Nested
-		class forRolePoststelle {
-			@Test
-			void shouldHaveStatusFilterOnly() {
-				var request = SearchRequestTestFactory.createBuilder().filterByOrganisationseinheitIds(false).organisationseinheitIds(null)
-						.status(List.of(Status.ABGESCHLOSSEN.name()))
-						.build();
-				var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-				assertThat(query.getFilter()).isNotNull();
-				assertThat(query.getFilter()).asString().contains("status");
-				assertThat(query.getFilter()).asString().contains(Status.ABGESCHLOSSEN.name());
-				assertThat(query.getFilter()).asString().doesNotContain("organisationseinheitenId");
-			}
-
-			@Test
-			void shouldHaveOrganisationseinheitenIdFilterOnly() {
-				var request = SearchRequestTestFactory.create();
-				var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-				assertThat(query.getFilter()).isNotNull();
-				assertThat(query.getFilter()).asString().contains("organisationseinheitenId");
-				assertThat(query.getFilter()).asString().contains(SearchRequestTestFactory.ORGANISATIONSEINHEIT_ID);
-			}
-
-			@Test
-			void shouldHaveOrganisationseinheitenAndStatusFilter() {
-				var request = SearchRequestTestFactory.createBuilder().status(List.of(Status.ABGESCHLOSSEN.name())).build();
-				var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-				assertThat(query.getFilter()).isNotNull();
-				assertThat(query.getFilter()).asString().contains("organisationseinheitenId");
-				assertThat(query.getFilter()).asString().contains(SearchRequestTestFactory.ORGANISATIONSEINHEIT_ID);
-				assertThat(query.getFilter()).asString().contains("status");
-				assertThat(query.getFilter()).asString().contains(Status.ABGESCHLOSSEN.name());
-			}
-		}
-
-		@Nested
-		class forOtherRoles {
-			@Test
-			void shouldHaveOrganisationseinheitenIdFilter() {
-				var request = SearchRequestTestFactory.create();
-				var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-				assertThat(query.getFilter()).isNotNull();
-				assertThat(query.getFilter()).asString().contains("organisationseinheitenId");
-				assertThat(query.getFilter()).asString().contains(SearchRequestTestFactory.ORGANISATIONSEINHEIT_ID);
-			}
-
-			@Test
-			void shouldHaveAssignedToFilter() {
-				var request = SearchRequestTestFactory.create();
-				var query = searchRepostitory.createQuery(request, PageRequest.of(request.getOffSet(), request.getLimit()));
-
-				assertThat(query.getFilter()).isNotNull();
-				assertThat(query.getFilter()).asString().contains("assignedTo");
-				assertThat(query.getFilter()).asString().contains(SearchRequestTestFactory.ASSIGNED_TO);
-			}
-		}
-	}
-}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderMapperTest.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderMapperTest.java
deleted file mode 100644
index 96f020d04a6192a84bc3f6cd26307a404f41e4ce..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderMapperTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.vorgang;
-
-import static org.assertj.core.api.Assertions.*;
-
-import org.apache.commons.lang3.StringUtils;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mapstruct.factory.Mappers;
-
-class EingangHeaderMapperTest {
-
-	private EingangHeaderMapper mapper = Mappers.getMapper(EingangHeaderMapper.class);
-
-	@Nested
-	class TestFromGrpc {
-
-		@Test
-		void shouldMapDateStrToZonedDateTime() {
-			GrpcEingangHeader grpcEingangHeader = GrpcEingangHeaderTestFactory.create();
-
-			var eingang = mapper.fromGrpc(grpcEingangHeader);
-
-			assertThat(eingang.getCreatedAt()).isEqualTo(GrpcEingangHeaderTestFactory.CREATED_AT);
-		}
-
-		@Test
-		void shouldMapAllFields() {
-			var mapped = mapper.fromGrpc(GrpcEingangHeaderTestFactory.create());
-
-			assertThat(mapped).usingRecursiveComparison().isEqualTo(EingangHeaderTestFactory.create());
-		}
-	}
-
-	@Nested
-	class TestToGrpc {
-
-		@Test
-		void shouldMapZonedDateTimeToDateStr() {
-			EingangHeader plutoEingangHeader = EingangHeaderTestFactory.create();
-
-			var eingangHeader = mapper.toGrpc(plutoEingangHeader);
-
-			assertThat(eingangHeader.getCreatedAt()).isEqualTo(EingangHeaderTestFactory.CREATED_AT_STR);
-		}
-
-		@Test
-		void shouldProceedWithEmptyValues() {
-			EingangHeader plutoEingangHeader = EingangHeaderTestFactory.createBuilder().createdAt(null).build();
-
-			var eingangHeader = mapper.toGrpc(plutoEingangHeader);
-
-			assertThat(eingangHeader.getCreatedAt()).isEqualTo(StringUtils.EMPTY);
-		}
-
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangServiceITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangServiceITCase.java
deleted file mode 100644
index 1eb03fa06efe49b311bce8c163a519dec6007e36..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangServiceITCase.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.ozg.pluto.vorgang;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.util.Optional;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.data.mongodb.core.MongoOperations;
-import org.springframework.security.test.context.support.WithMockUser;
-
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandService;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-
-@DataITCase
-@WithMockUser
-class VorgangServiceITCase {
-
-	@Autowired
-	private VorgangService vorgangService;
-
-	@Autowired
-	private VorgangRepository repository;
-
-	@Autowired
-	private MongoOperations mongoOperations;
-
-	@MockBean
-	private CommandService commandService;
-
-	@Nested
-	class TestVorgangUpdateStatus {
-
-		private Vorgang persistedVorgang;
-		private Command command;
-
-		@BeforeEach
-		void persistVorgang() {
-			mongoOperations.dropCollection(Vorgang.class);
-			persistedVorgang = repository.save(VorgangTestFactory.create());
-
-			command = CommandTestFactory.createBuilder().relationId(persistedVorgang.getId()).relationVersion(persistedVorgang.getVersion()).build();
-			when(commandService.findCommand(any())).thenReturn(Optional.of(command));
-		}
-
-		@Test
-		void annehmenShouldUpdateStatusAndVersion() {
-
-			vorgangService.annehmen(command);
-
-			Optional<Vorgang> vorgang = repository.findById(persistedVorgang.getId());
-
-			assertThat(vorgang.get().getStatus()).isEqualTo(Status.ANGENOMMEN);
-			assertThat(vorgang.get().getVersion()).isEqualTo(persistedVorgang.getVersion() + 1);
-		}
-
-		@Test
-		void verwerfenShouldUpdateStatusAndVersion() {
-
-			vorgangService.verwerfen(command);
-
-			Optional<Vorgang> vorgang = repository.findById(persistedVorgang.getId());
-
-			assertThat(vorgang.get().getStatus()).isEqualTo(Status.VERWORFEN);
-			assertThat(vorgang.get().getVersion()).isEqualTo(persistedVorgang.getVersion() + 1);
-		}
-
-		@Test
-		void bescheidenShouldUpdateStatusAndVersion() {
-
-			vorgangService.bescheiden(command);
-
-			Optional<Vorgang> vorgang = repository.findById(persistedVorgang.getId());
-
-			assertThat(vorgang.get().getStatus()).isEqualTo(Status.BESCHIEDEN);
-			assertThat(vorgang.get().getVersion()).isEqualTo(persistedVorgang.getVersion() + 1);
-		}
-
-		@Test
-		void wiedereroeffnenShouldUpdateStatusAndVersion() {
-
-			vorgangService.wiedereroeffnen(command);
-
-			Optional<Vorgang> vorgang = repository.findById(persistedVorgang.getId());
-
-			assertThat(vorgang.get().getStatus()).isEqualTo(Status.IN_BEARBEITUNG);
-			assertThat(vorgang.get().getVersion()).isEqualTo(persistedVorgang.getVersion() + 1);
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-server/src/test/resources/application-itcase.yml b/pluto-server/src/test/resources/application-itcase.yml
deleted file mode 100644
index 8af9c9e7159165e85e36f6043041972ed5c60cc3..0000000000000000000000000000000000000000
--- a/pluto-server/src/test/resources/application-itcase.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-logging:
-  level:
-    ROOT: ERROR,
-    '[org.springframework]': ERROR
-    '[org.springframework.data.mongodb.core]': WARN
-    '[de.itvsh]': WARN
-  config: classpath:log4j2-local.xml
-
-grpc:
-  server:
-    port: -1
-    
-aktenzeichen: de.itvsh.ozg.pluto.vorgang.AktenzeichenProviderEA
-
-kop:
-  osi:
-    postfach:
-      proxyapi:
-        url: http://localhost/ApiProxy/V1/Message
-        key: 1234
-        realm: test-realm
-  notification:
-    mail-from: test@local.host
-
-mongock:
-  enabled: false
\ No newline at end of file
diff --git a/pluto-utils/src/main/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectMapper.java b/pluto-utils/src/main/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectMapper.java
deleted file mode 100644
index 4fb8122ea315ecab9230442886176e27c097e788..0000000000000000000000000000000000000000
--- a/pluto-utils/src/main/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectMapper.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.kop.pluto.common.grpc;
-
-import java.time.LocalDate;
-import java.time.ZonedDateTime;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.mapstruct.Mapper;
-
-import de.itvsh.kop.common.datatype.StringBasedValue;
-import de.itvsh.ozg.pluto.common.GrpcObject;
-import de.itvsh.ozg.pluto.common.GrpcProperty;
-import de.itvsh.ozg.pluto.common.GrpcSubObject;
-
-@Mapper
-public interface GrpcObjectMapper {
-
-	default GrpcObject fromMap(Map<String, Object> map) {
-		return GrpcObject.newBuilder()
-				.addAllProperty(mapToAllProperties(map))
-				.addAllSubObject(mapToSubObjects(map))
-				.build();
-	}
-
-	@SuppressWarnings("unchecked")
-	default List<GrpcSubObject> mapToSubObjects(Map<String, Object> propertyMap) {
-		return propertyMap.entrySet().stream()
-				.filter(entry -> entry.getValue() instanceof Map)
-				.map(entry -> buildSubObject(entry.getKey(), (Map<String, Object>) entry.getValue()))
-				.toList();
-	}
-
-	default GrpcSubObject buildSubObject(String name, Map<String, Object> map) {
-		return GrpcSubObject.newBuilder().setName(name)
-				.addAllProperty(mapToAllProperties(map))
-				.addAllSubObject(mapToSubObjects(map)).build();
-	}
-
-	// FIXME den filter ausbauen - dadurch gehen unbemerkt properties verloren
-	default List<GrpcProperty> mapToAllProperties(Map<String, Object> propertyMap) {
-		return propertyMap.entrySet().stream().filter(this::isPropertyType)
-				.map(entry -> mapToProperty(entry.getKey(), entry.getValue()))
-				.toList();
-	}
-
-	default GrpcProperty mapToProperty(String name, Object value) {
-		// TODO nicht auf 'List' sondern auf 'Collection' prüfen
-		if (value instanceof List<?> valueList) {
-			return GrpcProperty.newBuilder().setName(name).addAllValue(valueList.stream().map(String::valueOf).toList())
-					.build();
-		}
-		return GrpcProperty.newBuilder().setName(name).addValue(value.toString()).build();
-	}
-
-	default boolean isPropertyType(Entry<String, Object> entry) {
-		return entry.getValue() instanceof String
-				|| entry.getValue() instanceof Integer
-				|| entry.getValue() instanceof Long
-				|| entry.getValue() instanceof ZonedDateTime
-				|| entry.getValue() instanceof LocalDate
-				|| entry.getValue() instanceof StringBasedValue
-				|| entry.getValue() instanceof Boolean
-				|| entry.getValue() instanceof List;
-	}
-
-	default Map<String, Object> mapFromGrpc(GrpcObject bodyObject) {
-		var map = new HashMap<String, Object>();
-		bodyObject.getPropertyList().stream().forEach(property -> mapProperty(map, property));
-		bodyObject.getSubObjectList().stream().forEach(subObject -> map.put(subObject.getName(), mapSubObject(subObject)));
-
-		return map;
-	}
-
-	private Map<String, Object> mapSubObject(GrpcSubObject object) {
-		var map = new HashMap<String, Object>();
-		object.getPropertyList().stream().forEach(property -> mapProperty(map, property));
-		object.getSubObjectList().stream().forEach(subObject -> map.put(subObject.getName(), mapSubObject(subObject)));
-
-		return map;
-	}
-
-	private void mapProperty(HashMap<String, Object> map, GrpcProperty property) {
-		if (property.getValueCount() == 1) {
-			map.put(property.getName(), String.valueOf(property.getValue(0)));
-		} else if (property.getValueCount() > 1) {
-			map.put(property.getName(), property.getValueList().stream().map(String::valueOf).toList());
-		}
-	}
-}
\ No newline at end of file
diff --git a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcFormDataMapperTest.java b/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcFormDataMapperTest.java
deleted file mode 100644
index 4ca5773dc3ee5ccfa23180bf0b996ba3de45cd14..0000000000000000000000000000000000000000
--- a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcFormDataMapperTest.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.kop.pluto.common.grpc;
-
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mapstruct.factory.Mappers;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-
-import de.itvsh.ozg.pluto.vorgang.GrpcFormData;
-import de.itvsh.ozg.pluto.vorgang.GrpcFormField;
-import de.itvsh.ozg.pluto.vorgang.GrpcSubForm;
-
-class GrpcFormDataMapperTest {
-
-	@InjectMocks
-	private GrpcFormDataMapper MAPPER_INSTANCE = Mappers.getMapper(GrpcFormDataMapper.class);
-
-	@Mock
-	private GrpcFormDataMapper grpcFormDataMapper;
-
-	@BeforeEach
-	void mockMapperReturnValues() {
-		lenient().when(grpcFormDataMapper.mapToFormData(anyMap()))
-				.thenReturn(GrpcFormData.newBuilder().addField(GrpcFormFieldTestFactory.create()).build());
-	}
-
-	@Nested
-	class TestSimpleValueMapping {
-
-		@Test
-		void shouldHaveField() {
-
-			GrpcFormData formData = MAPPER_INSTANCE.mapToFormData(Map.of("key", "value"));
-
-			assertThat(formData.getFieldList()).hasSize(1);
-		}
-
-		@Test
-		void shouldNotHaveSubForms() {
-
-			GrpcFormData formData = MAPPER_INSTANCE.mapToFormData(Map.of("key", "value"));
-
-			assertThat(formData.getFormList()).isEmpty();
-		}
-
-		@Test
-		void shouldHaveNameField() {
-
-			GrpcFormData formData = MAPPER_INSTANCE.mapToFormData(Map.of("key", "value"));
-
-			assertThat(formData.getField(0).getName()).isEqualTo("key");
-			assertThat(formData.getField(0).getValue()).isEqualTo("value");
-		}
-	}
-
-	@Nested
-	class TestSubFormMapping {
-
-		@Test
-		void shouldHaveSubForm() {
-
-			GrpcFormData formData = MAPPER_INSTANCE.mapToFormData(Map.of("key", Map.of("subKey", "value")));
-
-			assertThat(formData.getFormList()).hasSize(1);
-		}
-
-		@Test
-		void shouldNotHaveFields() {
-
-			GrpcFormData formData = MAPPER_INSTANCE.mapToFormData(Map.of("key", Map.of("subKey", "value")));
-
-			assertThat(formData.getFieldList()).isEmpty();
-		}
-
-		@Test
-		void shouldHaveSubFormField() {
-
-			GrpcFormData formData = MAPPER_INSTANCE.mapToFormData(Map.of("key", Map.of("subKey", "value")));
-
-			assertThat(formData.getForm(0).getFieldList()).hasSize(1);
-			assertThat(formData.getForm(0).getTitle()).isEqualTo("key");
-			assertThat(formData.getForm(0).getField(0).getName()).isEqualTo("subKey");
-			assertThat(formData.getForm(0).getField(0).getValue()).isEqualTo("value");
-		}
-	}
-
-	@DisplayName("Mapped SubFormField")
-	@Nested
-	class TestSubFormFieldMapping {
-
-		private final GrpcSubForm subForm = GrpcSubFormTestFactory.create();
-
-		@Test
-		void shouldContainField() {
-			var mapped = MAPPER_INSTANCE.mapSubFormFields(subForm.getFieldList());
-
-			assertThat(mapped).containsKey(GrpcSubFormTestFactory.FIELD_NAME);
-		}
-
-		@Test
-		void shouldContainValue() {
-			var mapped = MAPPER_INSTANCE.mapSubFormFields(subForm.getFieldList());
-
-			assertThat(mapped).containsEntry(GrpcSubFormTestFactory.FIELD_NAME, GrpcSubFormTestFactory.FIELD_VALUE);
-		}
-
-		@Nested
-		class TestCombiner {
-			@Test
-			void missingInMap2ShouldContainValue() {
-				Map<String, Object> map1 = Map.of("TEST", "VALUE1");
-				Map<String, Object> map2 = Map.of();
-
-				var combined = MAPPER_INSTANCE.combiner(map1, map2);
-
-				assertThat(combined).containsEntry("TEST", "VALUE1");
-			}
-
-			@Test
-			void missingInMap1ShouldContainValue() {
-				Map<String, Object> map1 = new HashMap<>();
-				Map<String, Object> map2 = Map.of("TEST", "VALUE1");
-
-				var combined = MAPPER_INSTANCE.combiner(map1, map2);
-
-				assertThat(combined).containsEntry("TEST", "VALUE1");
-			}
-
-			@Test
-			void inBothMapShouldCombineToList() {
-				Map<String, Object> map1 = new HashMap<>(Map.of("TEST", "VALUE1"));
-				Map<String, Object> map2 = Map.of("TEST", "VALUE2");
-
-				var combined = MAPPER_INSTANCE.combiner(map1, map2);
-
-				assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2"));
-			}
-
-			@Test
-			void listInMap2ShouldStayAList() {
-				Map<String, Object> map1 = Map.of("TEST", List.of("VALUE1", "VALUE2"));
-				Map<String, Object> map2 = Map.of();
-
-				var combined = MAPPER_INSTANCE.combiner(map1, map2);
-
-				assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2"));
-			}
-
-			@Test
-			void valueInMap1ShouldBeAddedToList() {
-				Map<String, Object> map1 = new HashMap<>(Map.of("TEST", "VALUE1"));
-				Map<String, Object> map2 = Map.of("TEST", List.of("VALUE2", "VALUE3"));
-
-				var combined = MAPPER_INSTANCE.combiner(map1, map2);
-
-				assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2", "VALUE3"));
-			}
-
-			@Test
-			void valueInMap2ShouldBeAddedToList() {
-				Map<String, Object> map1 = new HashMap<>(Map.of("TEST", List.of("VALUE1", "VALUE2")));
-				Map<String, Object> map2 = Map.of("TEST", "VALUE3");
-
-				var combined = MAPPER_INSTANCE.combiner(map1, map2);
-
-				assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2", "VALUE3"));
-			}
-
-			@Test
-			void listInMap1ShouldStayAList() {
-				Map<String, Object> map1 = new HashMap<>();
-				Map<String, Object> map2 = Map.of("TEST", List.of("VALUE1", "VALUE2"));
-
-				var combined = MAPPER_INSTANCE.combiner(map1, map2);
-
-				assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2"));
-			}
-
-			@Test
-			void listInBothMapsShouldByCombined() {
-				Map<String, Object> map1 = new HashMap<>(Map.of("TEST", List.of("VALUE1", "VALUE2")));
-				Map<String, Object> map2 = Map.of("TEST", List.of("VALUE3", "VALUE4"));
-
-				var combined = MAPPER_INSTANCE.combiner(map1, map2);
-
-				assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2", "VALUE3", "VALUE4"));
-			}
-		}
-	}
-
-	@Nested
-	class TestMapStringListsToFields {
-
-		@Test
-		void emptyMapShouldNotBeMapped() {
-
-			List<GrpcFormField> fields = MAPPER_INSTANCE.mapStringListsToFields(Collections.emptyMap());
-
-			assertThat(fields).isEmpty();
-		}
-
-		@Test
-		void simpleValueShouldNotBeMapped() {
-
-			List<GrpcFormField> fields = MAPPER_INSTANCE.mapStringListsToFields(Map.of("a", "b"));
-
-			assertThat(fields).isEmpty();
-		}
-
-		@Test
-		void listObjectValuesShouldBeMapped() {
-
-			List<GrpcFormField> fields = MAPPER_INSTANCE.mapStringListsToFields(Map.of("key", List.of("value1", "value2")));
-
-			assertThat(fields).hasSize(2);
-			assertThat(fields.get(0).getName()).isEqualTo("key");
-			assertThat(fields.get(0).getValue()).isEqualTo("value1");
-
-			assertThat(fields.get(1).getName()).isEqualTo("key");
-			assertThat(fields.get(1).getValue()).isEqualTo("value2");
-		}
-	}
-
-	@Nested
-	class TestMapObjectListsToFields {
-
-		@Test
-		void simpleValueShouldNotBeMapped() {
-
-			List<GrpcSubForm> fields = MAPPER_INSTANCE.mapObjectListsToFields(Map.of("a", "b"));
-
-			assertThat(fields).isEmpty();
-		}
-
-		@Test
-		void listOfSimpleValueShouldNotBeMapped() {
-
-			List<GrpcSubForm> fields = MAPPER_INSTANCE.mapObjectListsToFields(Map.of("a", List.of("l1", "l2")));
-
-			assertThat(fields).isEmpty();
-		}
-
-		@Test
-		void listOfObjectsShouldBeMappedToSubForms() {
-
-			List<GrpcSubForm> fields = MAPPER_INSTANCE
-					.mapObjectListsToFields(Map.of("key", List.of(Collections.emptyMap(), Collections.emptyMap())));
-
-			assertThat(fields).hasSize(2);
-		}
-
-		@Test
-		void listOfObjectsShouldMappedToSubFormTitle() {
-
-			List<GrpcSubForm> fields = MAPPER_INSTANCE
-					.mapObjectListsToFields(Map.of("key", List.of(Collections.emptyMap(), Collections.emptyMap())));
-
-			assertThat(fields.get(0).getTitle()).isEqualTo("key");
-			assertThat(fields.get(1).getTitle()).isEqualTo("key");
-		}
-
-		@Test
-		void listOfObjectsShouldBeMapped() {
-
-			List<GrpcSubForm> fields = MAPPER_INSTANCE
-					.mapObjectListsToFields(Map.of("key", List.of(Map.of("a1", "a2"))));
-
-			assertThat(fields.get(0).getFieldCount()).isEqualTo(1);
-			assertThat(fields.get(0).getField(0).getName()).isEqualTo("a1");
-			assertThat(fields.get(0).getField(0).getValue()).isEqualTo("a2");
-		}
-
-		@Test
-		void doubleNestedListObjectValuesShouldBeMapped() {
-			GrpcFormData formData = MAPPER_INSTANCE
-					.mapToFormData(Map.of("key1", Map.of("key2", List.of("value1", "value2"))));
-
-			assertThat(formData.getForm(0).getFieldCount()).isEqualTo(2);
-		}
-
-		@Test
-		void multipleNestedListObjectValuesShouldBeMapped() {
-			GrpcFormData formData = MAPPER_INSTANCE
-					.mapToFormData(Map.of("key1", Map.of("key2", Map.of("key3", List.of("value1", "value2")))));
-
-			assertThat(formData.getForm(0).getSubForm(0).getFieldCount()).isEqualTo(2);
-		}
-	}
-
-	@Nested
-	class TestMapListOfMixedValuesInFormData {
-
-		@Test
-		void shouldMapListOfStrings() {
-
-			GrpcFormData formData = MAPPER_INSTANCE
-					.mapToFormData(Map.of("key", List.of("value1", "value2", Map.of("internKey1", "internValue1"))));
-
-			assertThat(formData.getFieldCount()).isEqualTo(2);
-			assertThat(formData.getFormCount()).isEqualTo(1);
-		}
-	}
-}
diff --git a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectMapperTest.java b/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectMapperTest.java
deleted file mode 100644
index 87ec689e09774e547e3dd4e07f9abecf712b3706..0000000000000000000000000000000000000000
--- a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectMapperTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.kop.pluto.common.grpc;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.Map;
-
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.mapstruct.factory.Mappers;
-
-import de.itvsh.ozg.pluto.common.GrpcObject;
-
-class GrpcObjectMapperTest {
-
-	private final GrpcObjectMapper mapper = Mappers.getMapper(GrpcObjectMapper.class);
-
-	@Test
-	void shouldMapStringMapToGrpc() {
-		var grpcObject = mapper.fromMap(GrpcObjectTestFactory.STRING_MAP);
-
-		assertThat(grpcObject).isNotNull();
-		assertThat(grpcObject.getPropertyCount()).isEqualTo(1);
-		assertThat(grpcObject.getProperty(0).getName()).isEqualTo(GrpcObjectTestFactory.PROPERTY_NAME);
-		assertThat(getFirstValueOfFirstProperty(grpcObject)).isEqualTo(GrpcObjectTestFactory.PROPERTY_NAME_VALUE);
-	}
-
-	@Test
-	void shouldMapLongMapToGrpc() {
-		var grpcObject = mapper.fromMap(GrpcObjectTestFactory.LONG_MAP);
-
-		assertThat(getFirstValueOfFirstProperty(grpcObject)).isEqualTo(GrpcObjectTestFactory.PROPERTY_LONG_VALUE.toString());
-	}
-
-	@Test
-	void shouldMapIntegerMapToGrpc() {
-		var grpcObject = mapper.fromMap(GrpcObjectTestFactory.INTEGER_MAP);
-
-		assertThat(getFirstValueOfFirstProperty(grpcObject)).isEqualTo(GrpcObjectTestFactory.PROPERTY_INT_VALUE.toString());
-	}
-
-	@Test
-	void shouldMapBooleanMapToGrpc() {
-		var grpcObject = mapper.fromMap(GrpcObjectTestFactory.BOOLEAN_MAP);
-
-		assertThat(getFirstValueOfFirstProperty(grpcObject)).isEqualTo(GrpcObjectTestFactory.PROPERTY_BOOLEAN_VALUE.toString());
-	}
-
-	@Test
-	void shouldMapLocalDateMapToGrpc() {
-		var grpcObject = mapper.fromMap(GrpcObjectTestFactory.LOCAL_DATE_MAP);
-
-		assertThat(getFirstValueOfFirstProperty(grpcObject)).isEqualTo(GrpcObjectTestFactory.PROPERTY_LOCAL_DATE_VALUE.toString());
-	}
-
-	@Test
-	void shouldMapZonedDateTimeMapToGrpc() {
-		var grpcObject = mapper.fromMap(GrpcObjectTestFactory.ZONED_DATE_TIME_MAP);
-
-		assertThat(getFirstValueOfFirstProperty(grpcObject)).isEqualTo(GrpcObjectTestFactory.PROPERTY_ZONED_DATE_TIME_VALUE.toString());
-	}
-
-	@Test
-	void shouldMapFileIdMapToGrpc() {
-		var grpcObject = mapper.fromMap(GrpcObjectTestFactory.FILE_ID_MAP);
-
-		assertThat(getFirstValueOfFirstProperty(grpcObject)).isEqualTo(GrpcObjectTestFactory.PROPERTY_FILE_ID_VALUE.toString());
-	}
-
-	@Test
-	void shouldMapFileIdListMapToGrpc() {
-		var grpcObject = mapper.fromMap(GrpcObjectTestFactory.FILE_ID_LIST_MAP);
-
-		assertThat(getFirstValueOfFirstProperty(grpcObject)).isEqualTo(GrpcObjectTestFactory.PROPERTY_FILE_ID_VALUE.toString());
-		assertThat(grpcObject.getProperty(0).getValue(1)).isEqualTo(GrpcObjectTestFactory.PROPERTY_FILE_ID_VALUE.toString());
-	}
-
-	private String getFirstValueOfFirstProperty(GrpcObject grpcObject) {
-		return grpcObject.getProperty(0).getValue(0);
-	}
-
-	@Nested
-	class TestMapFromGrpcObject {
-
-		private final GrpcObject grpcObject = GrpcObjectTestFactory.create();
-
-		@Nested
-		class Property {
-
-			@Test
-			void shouldPutAsEntryInMap() {
-				var map = mapFromGrpc();
-
-				assertThat(map).contains(GrpcObjectTestFactory.PROPERTY_AS_MAP_ENTRY);
-			}
-		}
-
-		@Nested
-		class SubObject {
-
-			@Test
-			void shouldPutNameAsKeyInMap() {
-				var map = mapFromGrpc();
-
-				assertThat(map).containsKey(GrpcObjectTestFactory.SUB_OBJECT_NAME);
-			}
-
-			@Test
-			void shouldPutPropertyAsValueInMap() {
-				var map = mapFromGrpc();
-
-				assertThat(getSubObjectMap(map, GrpcObjectTestFactory.SUB_OBJECT_NAME)).contains(GrpcObjectTestFactory.PROPERTY_AS_MAP_ENTRY);
-			}
-
-			@Nested
-			class WithSubObject {
-
-				@Test
-				void shouldPutNameAsKeyInSubObjectMap() {
-					var map = mapFromGrpc();
-
-					assertThat(getSubObjectMap(map, GrpcObjectTestFactory.SUB_OBJECT_NAME))
-							.containsKey(GrpcObjectTestFactory.SUB_OBJECT_NAME_OF_SUB_OBJECT);
-				}
-
-				@Test
-				void shouldPutPropertyAsValueInSubObjectMap() {
-					var map = mapFromGrpc();
-
-					assertThat(getSubObjectMap(getSubObjectMap(map, GrpcObjectTestFactory.SUB_OBJECT_NAME),
-							GrpcObjectTestFactory.SUB_OBJECT_NAME_OF_SUB_OBJECT)).contains(GrpcObjectTestFactory.PROPERTY_AS_MAP_ENTRY);
-				}
-			}
-
-			@SuppressWarnings("unchecked")
-			private Map<String, Object> getSubObjectMap(Map<String, Object> map, String key) {
-				return (Map<String, Object>) map.get(key);
-			}
-		}
-
-		private Map<String, Object> mapFromGrpc() {
-			return mapper.mapFromGrpc(grpcObject);
-		}
-	}
-}
diff --git a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectTestFactory.java b/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectTestFactory.java
deleted file mode 100644
index 9e0f770b22a5b0e8283e23bd19a3fbb9a67aa407..0000000000000000000000000000000000000000
--- a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcObjectTestFactory.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.kop.pluto.common.grpc;
-
-import java.time.LocalDate;
-import java.time.ZonedDateTime;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import com.thedeanda.lorem.LoremIpsum;
-
-import de.itvsh.kop.common.binaryfile.FileId;
-import de.itvsh.ozg.pluto.common.GrpcObject;
-import de.itvsh.ozg.pluto.common.GrpcProperty;
-import de.itvsh.ozg.pluto.common.GrpcSubObject;
-
-public class GrpcObjectTestFactory {
-
-	public static final String PROPERTY_NAME = "propertyName";
-	public static final String PROPERTY_NAME_VALUE = "propertyNameValue";
-
-	public static final Integer PROPERTY_INT_VALUE = Integer.MAX_VALUE;
-
-	public static final Long PROPERTY_LONG_VALUE = 42L;
-
-	public static final Boolean PROPERTY_BOOLEAN_VALUE = Boolean.TRUE;
-
-	public static final Date PROPERTY_DATE_VALUE = new Date();
-
-	public static final LocalDate PROPERTY_LOCAL_DATE_VALUE = LocalDate.now();
-
-	public static final ZonedDateTime PROPERTY_ZONED_DATE_TIME_VALUE = ZonedDateTime.now();
-
-	public static final FileId PROPERTY_FILE_ID_VALUE = FileId.createNew();
-
-	public static final List<FileId> PROPERTY_FILE_ID_LIST_VALUE = List.of(PROPERTY_FILE_ID_VALUE, PROPERTY_FILE_ID_VALUE);
-	public static final Map<String, Object> STRING_MAP = Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE);
-	public static final Map<String, Object> INTEGER_MAP = Map.of(PROPERTY_NAME, PROPERTY_INT_VALUE);
-	public static final Map<String, Object> LONG_MAP = Map.of(PROPERTY_NAME, PROPERTY_LONG_VALUE);
-	public static final Map<String, Object> BOOLEAN_MAP = Map.of(PROPERTY_NAME, PROPERTY_BOOLEAN_VALUE);
-	public static final Map<String, Object> DATE_MAP = Map.of(PROPERTY_NAME, PROPERTY_DATE_VALUE);
-	public static final Map<String, Object> LOCAL_DATE_MAP = Map.of(PROPERTY_NAME, PROPERTY_LOCAL_DATE_VALUE);
-	public static final Map<String, Object> ZONED_DATE_TIME_MAP = Map.of(PROPERTY_NAME, PROPERTY_ZONED_DATE_TIME_VALUE);
-	public static final Map<String, Object> FILE_ID_MAP = Map.of(PROPERTY_NAME, PROPERTY_FILE_ID_VALUE);
-	public static final Map<String, Object> FILE_ID_LIST_MAP = Map.of(PROPERTY_NAME, PROPERTY_FILE_ID_LIST_VALUE);
-
-	public static final String SUB_OBJECT_NAME = LoremIpsum.getInstance().getWords(1);
-	public static final String SUB_OBJECT_NAME_OF_SUB_OBJECT = LoremIpsum.getInstance().getWords(1);
-	public static final Map.Entry<String, Object> PROPERTY_AS_MAP_ENTRY = Map.entry(PROPERTY_NAME, PROPERTY_NAME_VALUE);
-
-	public static GrpcObject create() {
-		return createBuilder().build();
-	}
-
-	public static GrpcObject.Builder createBuilder() {
-		return GrpcObject.newBuilder()
-				.addProperty(GrpcProperty.newBuilder().setName(PROPERTY_NAME).addValue(PROPERTY_NAME_VALUE).build())
-				.addSubObject(GrpcSubObject.newBuilder()
-						.setName(SUB_OBJECT_NAME)
-						.addProperty(GrpcProperty.newBuilder().setName(PROPERTY_NAME).addValue(PROPERTY_NAME_VALUE).build())
-						.addSubObject(GrpcSubObject.newBuilder()
-								.setName(SUB_OBJECT_NAME_OF_SUB_OBJECT)
-								.addProperty(GrpcProperty.newBuilder().setName(PROPERTY_NAME).addValue(PROPERTY_NAME_VALUE).build()))
-						.build());
-	}
-
-	public static GrpcObject fromStringMap(Map<String, String> map) {
-		var builder = GrpcObject.newBuilder();
-		map.entrySet().forEach(entry -> builder.addProperty(
-				GrpcProperty.newBuilder().setName(entry.getKey()).addValue(entry.getValue()).build())
-				.build());
-		return builder.build();
-	}
-}
\ No newline at end of file
diff --git a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcSubFormTestFactory.java b/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcSubFormTestFactory.java
deleted file mode 100644
index 987dfc06b25cc01eba8f7ceaddb79ff2f0aed4b2..0000000000000000000000000000000000000000
--- a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcSubFormTestFactory.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.itvsh.kop.pluto.common.grpc;
-
-import de.itvsh.ozg.pluto.vorgang.GrpcFormField;
-import de.itvsh.ozg.pluto.vorgang.GrpcSubForm;
-
-public class GrpcSubFormTestFactory {
-
-	public static final String TITLE = "kontakt";
-
-	public static final String FIELD_NAME = "name";
-	public static final String FIELD_VALUE = "Thea";
-
-	public static final String SUBFORM_NAME = "kontakt";
-	public static final String SUBFORM_FIELD_NAME = "E-Mail";
-	public static final String SUBFORM_FIELD_VALUE = "thea@mailinator.de";
-
-	public static GrpcSubForm create() {
-		return createBuilder().build();
-	}
-
-	public static GrpcSubForm.Builder createBuilder() {
-		return GrpcSubForm.newBuilder()
-				.setTitle(TITLE)
-				.addField(GrpcFormField.newBuilder().setName(FIELD_NAME).setValue(FIELD_VALUE).build())
-				.addSubForm(GrpcSubForm.newBuilder().setTitle(SUBFORM_NAME).addField(
-						GrpcFormField.newBuilder().setName(SUBFORM_FIELD_NAME).setValue(SUBFORM_FIELD_VALUE).build()));
-	}
-}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d6657018e08ad435f293bbc589dce1b987fb8f2e..de22050f5abdb3382ff9afd156652a62e7bfc164 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -24,25 +24,66 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 
 	<modelVersion>4.0.0</modelVersion>
-	<groupId>de.itvsh.ozg</groupId>
-	<artifactId>pluto</artifactId>
-	<version>1.0.0</version>
+	<groupId>de.ozgcloud.vorgang</groupId>
+	<artifactId>vorgang-manager</artifactId>
+	<version>2.4.0</version>
 
-	<name>Pluto Parent</name>
+	<name>OZG-Cloud Vorgang Manager</name>
 	<packaging>pom</packaging>
 
+	<properties>
+		<ozgcloud.license.version>1.6.0</ozgcloud.license.version>
+	</properties>
+
 	<modules>
-		<module>pluto-interface</module>
-		<module>pluto-server</module>
-		<module>mail-service</module>
-		<module>pluto-utils</module>
+		<module>vorgang-manager-interface</module>
+		<module>vorgang-manager-server</module>
+		<module>nachrichten-manager</module>
+		<module>vorgang-manager-utils</module>
 		<module>notification-manager</module>
+		<module>vorgang-manager-command</module>
+		<module>bescheid-manager</module>
+		<module>vorgang-manager-base</module>
+		<module>nachrichten-bayernid-proxy</module>
 	</modules>
 
+	<build>
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>com.mycila</groupId>
+					<artifactId>license-maven-plugin</artifactId>
+					<version>4.1</version>
+					<configuration>
+						<mapping>
+							<config>SCRIPT_STYLE</config>
+						</mapping>
+						<licenseSets>
+							<licenseSet>
+								<header>license/eupl_v1_2_de/header.txt</header>
+								<excludes>
+									<exclude>**/README</exclude>
+									<exclude>src/test/resources/**</exclude>
+									<exclude>src/main/resources/**</exclude>
+								</excludes>
+							</licenseSet>
+						</licenseSets>
+					</configuration>
+					<dependencies>
+						<dependency>
+							<groupId>de.ozgcloud.common</groupId>
+							<artifactId>ozgcloud-common-license</artifactId>
+							<version>${ozgcloud.license.version}</version>
+						</dependency>
+					</dependencies>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+	</build>
+
 	<distributionManagement>
 		<repository>
 			<id>ozg-nexus</id>
@@ -56,4 +97,3 @@
 		</snapshotRepository>
 	</distributionManagement>
 </project>
-	
\ No newline at end of file
diff --git a/release-erstellen.sh b/release-erstellen.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6d07a5942189a50e71350740fe8d76cfaf457223
--- /dev/null
+++ b/release-erstellen.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+
+if [ "$#" -ne 1 ]; then
+    echo "Aufruf: release-erstellen.sh JA"
+    echo "Als Parameter bitte 'JA' eintragen zur Sicherheit"
+    exit 1
+fi
+
+
+## alle -SNAPSHOT in pom.xmls entfernen
+SED_PARAMS="-i"
+if [[ "$OSTYPE" =~ ^darwin ]]; then
+    SED_PARAMS="$SED_PARAMS '' -e"
+fi
+find . -name pom.xml -exec sed $SED_PARAMS 's/-SNAPSHOT//g' {} +
+
+## release version auslesen
+NEWVERSION=$(xmlstarlet sel -N w="http://maven.apache.org/POM/4.0.0" -t -v '//w:project/w:version' -n pom.xml)
+
+echo
+echo "NEXT STEPS:"
+echo "***********"
+echo "Änderungen prüfen"
+echo "git commit -a -m 'release version "$NEWVERSION"'"
+echo "git push"
+echo "git tag "$NEWVERSION
+echo "git push --tags"
diff --git a/release-startdev.sh b/release-startdev.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a2297636af305a40581f86a1123ffa238792a211
--- /dev/null
+++ b/release-startdev.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+
+#set -x
+
+if [ "$#" -ne 1 ]; then
+    echo "Aufruf: ozg-release-startdev.sh NEWVERSION"
+    exit 1
+fi
+
+NEWVERSION=$1
+
+echo
+
+# pom.xml:main -> project.version setzen
+# projectname/pom.xml:parent -> project.parent.version setzen
+# projectname/pom.xml:parent,main -> project.parent.version und project.version setzen
+#
+PROJECTS="pom.xml:main 
+          vorgang-manager-server/pom.xml:main
+          vorgang-manager-interface/pom.xml:main
+          vorgang-manager-utils/pom.xml:main
+          nachrichten-manager/pom.xml:main
+          notification-manager/pom.xml:main
+          vorgang-manager-command/pom.xml:main
+          vorgang-manager-base/pom.xml:main
+          bescheid-manger/pom.xml:main
+        "
+
+for PROJECT in $PROJECTS;
+do
+  POMFILE=$(echo $PROJECT | cut -d':' -f1)
+  ACTIONS=$(echo $PROJECT | cut -d':' -f2)
+
+  ## Auf SNAPSHOT Versionen testen
+  if fgrep -q "SNAPSHOT" $POMFILE; then
+    RED='\033[0;31m'
+    NC='\033[0m'
+    echo "${RED}ERROR: Datei "$POMFILE" enthält noch SNAPSHOT Versionen, das sollte hier nicht passieren.${NC}"
+    exit 1
+  fi
+echo $ACTIONS
+  ## Versionen setzen
+  if [[ $ACTIONS == "main" ]] ; then
+    xmlstarlet ed --pf -L -N w="http://maven.apache.org/POM/4.0.0" -u '//w:project/w:version' -v $NEWVERSION $POMFILE
+  fi
+
+  if [[ $ACTIONS == "parent" ]]; then
+    xmlstarlet ed --pf -L -N w="http://maven.apache.org/POM/4.0.0" -u '//w:project/w:parent/w:version' -v $NEWVERSION $POMFILE
+  fi
+done
+
+
+
+echo
+echo "NEXT STEPS:"
+echo "***********"
+echo "Änderungen prüfen"
+echo "git commit -a -m 'start development "$NEWVERSION"'"
+echo "git push"
+
diff --git a/run_helm_test.sh b/run_helm_test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..83200aa4005c4dbf7b4cfb2e8d366d5eb5ceba8b
--- /dev/null
+++ b/run_helm_test.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+
+set -e
+set -x
+
+helm template  ./src/main/helm/ -f src/test/helm-linter-values.yaml
+helm lint -f src/test/helm-linter-values.yaml ./src/main/helm/
+cd src/main/helm && helm unittest -f '../../test/helm/**/*test.yaml'  .
+
diff --git a/src/main/helm/Chart.yaml b/src/main/helm/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f7a9cfae32b7ce3fc826e27ad44f2e2f18c9e612
--- /dev/null
+++ b/src/main/helm/Chart.yaml
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+appVersion: "1.0"
+description: A Helm chart for Vorgang-Manager
+name: vorgang-manager
+version: 0.0.0-MANAGED-BY-JENKINS
+icon: https://simpleicons.org/icons/helm.svg
diff --git a/src/main/helm/README.md b/src/main/helm/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..409f1dc37a7da504ef0df6073288809b08e0c277
--- /dev/null
+++ b/src/main/helm/README.md
@@ -0,0 +1,41 @@
+# Vorgang-Manager
+
+Das helm chart zur Installation des Vorgang-Managers.
+
+## FAQ
+
+### Benutzung beliebiger environment Werte
+
+In jedem der Projekte kann man beliebige weitere environments setzen. Dazu muss man in der jeweiligen values.yaml unter env.customList ein name value Paar setzen:
+
+```yaml
+env:
+  customList:
+    - name: Dinge
+      value: true
+    - name: ...
+      value: ...
+```
+
+Um beispielsweise dem Spring eine Variable zu übergeben ``mongock.enabled=false`` kann man Folgendes konfigurieren:
+
+```yaml
+env:
+  customList:
+    - name: mongock_enabled
+      value: "false"
+```
+
+### Nutzen einer externen MongoDB
+
+Möchte man Vorgang-Manager mit einer externen MongoDB verbinden, so muss unter `Datenbank` die 
+`Nutze externe Datenbank` Checkbox gesetzt sein und im Namespace muss sich ein Opaque Secret mit 
+Namen `vorgang-manager-database-spring` befinden.
+
+In dem Secret müssen folgende Felder vorhanden sein.
+
+```yaml
+spring_data_mongodb_authentication-database: <authentication-database> # sollte admin sein
+spring_data_mongodb_database: KOP_DB_SH_<Bezeichner in upper-case>
+spring_data_mongodb_uri: mongodb://KOP_User_SH_<Bezeichner in upper-case>:<Password>@<IP-DB-1>:<PORT-DB-1>,<IP-DB-2>:<PORT-DB-2>,<IP-DB-3>:<PORT-DB-3>/<authentication-database>?ssl=false
+```
\ No newline at end of file
diff --git a/src/main/helm/templates/_helpers.tpl b/src/main/helm/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..4ff4baebdb883989d883c4eb962aa7a347ece030
--- /dev/null
+++ b/src/main/helm/templates/_helpers.tpl
@@ -0,0 +1,99 @@
+{{/* vim: set filetype=mustache: */}}
+
+{{/* Namespace */}}
+{{- define "app.namespace" -}}
+{{- if gt (len (.Release.Namespace)) 63 -}}
+{{- fail (printf ".Release.Namespace %s ist zu lang (max. 63 Zeichen)" .Release.Namespace) -}}
+{{- end -}}
+{{ printf "%s" .Release.Namespace }}
+{{- end -}}
+
+{{/* Chart: Name + Version */}}
+{{- define "app.chart" -}}
+{{- if gt (len (printf "%s-%s" .Chart.Name .Chart.Version)) 63 -}}
+{{- fail (printf ".Chart.Name-.Chart.Version %s-%s ist zu lang (max. 63 Zeichen)" .Chart.Name .Chart.Version) -}}
+{{- end -}}
+{{ printf "%s-%s" .Chart.Name .Chart.Version }}
+{{- end -}}
+
+{{/* Managed-by -> On Helm, this value is always Helm */}}
+{{- define "app.managedBy" -}}
+{{- if gt (len (.Release.Service)) 63 -}}
+{{- fail (printf ".Release.Service %s ist zu lang (max. 63 Zeichen)" .Release.Service) -}}
+{{- end -}}
+{{ printf "%s" .Release.Service }}
+{{- end -}}
+
+{{/* Default Labels: Helm recommended best-practice labels https://helm.sh/docs/chart_best_practices/labels/ */}}
+{{- define "app.defaultLabels" }}
+app.kubernetes.io/instance: vorgang-manager
+app.kubernetes.io/managed-by: {{ include "app.managedBy" . }}
+app.kubernetes.io/name: {{ .Release.Name }}
+app.kubernetes.io/namespace: {{ include "app.namespace" . }}
+app.kubernetes.io/part-of: ozgcloud
+app.kubernetes.io/version: {{ .Chart.Version }}
+helm.sh/chart: {{ include "app.chart" . }}
+{{- end -}}
+
+{{- define "app.matchLabels" }}
+app.kubernetes.io/name: {{ .Release.Name }}
+app.kubernetes.io/namespace: {{ include "app.namespace" . }}
+{{- end -}}
+
+{{- define "app.imagePullSecret" }}
+{{- with .Values.imageCredentials }}
+{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }}
+{{- end }}
+{{- end }}
+
+{{- define "app.envSpringProfiles" }}
+{{- if (.Values.env).overrideSpringProfiles -}}
+{{ printf "%s" (.Values.env).overrideSpringProfiles }}
+{{- else -}}
+{{ printf "oc, %s" (include "app.ozgcloudEnvironment" . ) }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.ozgcloudEnvironment" -}}
+{{- required "ozgcloud.environment muss angegeben sein" (.Values.ozgcloud).environment -}}
+{{- end -}}
+
+{{- define "app.vorgangManagerDatabase" -}}
+{{- if (.Values.database).databaseName -}}
+{{  .Values.database.databaseName }}
+{{- else -}}
+{{ printf "vorgang-manager-database" }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.grpc_client_user-manager_address" -}}
+{{ printf "%s.%s:9000" .Values.usermanagerName .Release.Namespace }}
+{{- end -}}
+
+{{- define "app.ozgcloud_migration_user-manager_address" -}}
+{{ printf "http://%s.%s:8080/migration/user" .Values.usermanagerName .Release.Namespace }}
+{{- end -}}
+
+{{- define "app.ozgcloud_vorgangmanager_address" -}}
+{{ printf "dns://%s.%s:9090" .Values.vorgangmanagerName .Release.Namespace }}
+{{- end -}}
+
+{{- define "app.databaseTlsCert" -}}
+{{- if ((.Values.database).tls).secretName -}}
+{{  .Values.database.tls.secretName }}
+{{- else -}}
+{{  printf "ozg-mongodb-tls-cert" }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.databaseSecretName" -}}
+{{- if (.Values.database).secretName -}}
+{{  .Values.database.secretName }}
+{{- else -}}
+{{  printf "ozg-mongodb-admin-vorgang-manager-user" }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.serviceAccountName" -}}
+{{ printf "%s" ( (.Values.serviceAccount).name | default "vorgang-manager-service-account" ) }}
+{{- end -}}
\ No newline at end of file
diff --git a/src/main/helm/templates/configmap_bindings_type.yaml b/src/main/helm/templates/configmap_bindings_type.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..102f45fa9f58e7cfbd88bbac179b0796fbff7ece
--- /dev/null
+++ b/src/main/helm/templates/configmap_bindings_type.yaml
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: bindings-type
+  namespace: {{ include "app.namespace" . }}
+data:
+  type: |
+    ca-certificates
\ No newline at end of file
diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a5df086fa7c7b0baf772e7dfc8bf4096d3b463d6
--- /dev/null
+++ b/src/main/helm/templates/deployment.yaml
@@ -0,0 +1,333 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ .Release.Name }}
+  namespace: {{ include "app.namespace" . }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+spec:
+  progressDeadlineSeconds: 600
+  replicas: {{ .Values.replicaCount }}
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      {{- include "app.matchLabels" . | indent 6 }}
+  strategy:
+    rollingUpdate:
+      maxSurge: 1
+      maxUnavailable: 0
+    type: RollingUpdate
+  template:
+    metadata:
+      labels:
+        {{- include "app.defaultLabels" . | indent 8 }}
+        component: vorgang-manager
+    spec:
+      {{- if (.Values.serviceAccount).create }}
+      serviceAccountName: {{ include "app.serviceAccountName" . }}
+      {{- end }}
+      topologySpreadConstraints:
+      - maxSkew: 1
+        topologyKey: kubernetes.io/hostname
+        whenUnsatisfiable: ScheduleAnyway
+        labelSelector:
+          matchLabels:
+            app.kubernetes.io/name: {{ .Release.Name }}
+      containers:
+      - env:
+          - name: SERVICE_BINDING_ROOT
+            value: "/bindings"
+          - name: spring_profiles_active
+            value: {{ include "app.envSpringProfiles" . }}
+          - name: ozgcloud_nachrichten-manager_url
+            value: {{ include "app.ozgcloud_vorgangmanager_address" . }}
+          {{- if .Values.env.ozgcloudAktenzeichen.enabled }}
+          - name: ozgcloud_aktenzeichen
+            value: {{ .Values.env.ozgcloudAktenzeichen.value | default "de.ozgcloud.vorgang.vorgang.AktenzeichenProviderEA" }}
+          {{- end }}
+          {{- if (.Values.ozgcloudProxyApi).url }}
+          - name: ozgcloud_osi_postfach_proxyapi_url
+            value: {{ .Values.ozgcloudProxyApi.url }}
+          {{- end }}
+          {{- if (.Values.ozgcloudProxyApi).realm }}
+          - name: ozgcloud_osi_postfach_proxyapi_realm
+            value: {{ .Values.ozgcloudProxyApi.realm }}
+          {{- end }}
+          - name: ozgcloud_osi_postfach_scheduler_enabled
+            value: "{{ ((.Values.ozgcloudProxyApi).scheduler).enabled | default false }}"
+          - name: ozgcloud_osi_postfach_scheduler_fixedDelay
+            value: "{{ ((.Values.ozgcloudProxyApi).scheduler).fixedDelay | default 300000 }}"
+          {{- if ((.Values.osipostfach).httpproxy).enabled }}
+          - name: ozgcloud_osi_postfach_http-proxy_host
+            value: {{ .Values.osipostfach.httpproxy.host }}
+          - name: ozgcloud_osi_postfach_http-proxy_port
+            value: "{{ .Values.osipostfach.httpproxy.port }}"
+          - name: ozgcloud_osi_postfach_http-proxy_authenticationRequired
+            value: "{{ .Values.osipostfach.httpproxy.auth.required }}"
+          {{- if .Values.osipostfach.httpproxy.auth.required }}
+          - name: ozgcloud_osi_postfach_http-proxy_username
+            value: {{ .Values.osipostfach.httpproxy.auth.username }}
+          - name: ozgcloud_osi_postfach_http-proxy_password
+            value: {{ .Values.osipostfach.httpproxy.auth.password }}
+          {{- end }}
+          {{- end }}
+          {{- if (.Values.rabbitmq).enabled }}
+          - name: spring_rabbitmq_username
+            valueFrom:
+              secretKeyRef:
+                name: rabbitmq-credentials
+                key: username
+                optional: false
+          - name: spring_rabbitmq_password
+            valueFrom:
+              secretKeyRef:
+                name: rabbitmq-credentials
+                key: password
+                optional: false
+          {{- end }}
+          {{- if (.Values.elasticsearch).enabled  }}
+          - name: ozgcloud_elasticsearch_address
+            valueFrom:
+              secretKeyRef:
+                name: {{ coalesce .Values.elasticsearch.secretName "elasticsearch-credentials" }}
+                key: address
+                optional: false
+          - name: ozgcloud_elasticsearch_username
+            valueFrom:
+              secretKeyRef:
+                name: {{ coalesce .Values.elasticsearch.secretName "elasticsearch-credentials" }}
+                key: username
+                optional: false
+          - name: ozgcloud_elasticsearch_password
+            valueFrom:
+              secretKeyRef:
+                name: {{ coalesce .Values.elasticsearch.secretName "elasticsearch-credentials" }}
+                key: password
+                optional: false
+          - name: ozgcloud_elasticsearch_index
+            valueFrom:
+              secretKeyRef:
+                name: {{ coalesce .Values.elasticsearch.secretName "elasticsearch-credentials" }}
+                key: index
+                optional: false
+          - name: spring_ssl_bundle_pem_es-root-ca_truststore_certificate
+            value: "/bindings/ca-certificates/es-root-ca.pem"
+          {{- end }}
+          {{- with (.Values.env).customList }}
+{{ toYaml . | indent 10 }}
+          {{- end }}
+          - name: grpc_client_user-manager_address
+            value: {{ include "app.grpc_client_user-manager_address" . }}
+          - name: grpc_client_user-manager_negotiationType
+            value: {{ (.Values.userManager).grpcClientNegotiationType | default "TLS" }}
+          - name: grpc_client_info-manager_address
+            value:  {{ ((.Values.ozgcloud).infoManager).address }}
+
+          - name: ozgcloud_user-manager_url
+            value: {{ include "app.ozgcloud_migration_user-manager_address" . }}
+          - name: ozgcloud_zufi-manager_address
+            value: {{ .Values.zufiManager.address }}
+          {{- if not (.Values.database).useExternal }}
+          - name: spring_data_mongodb_uri
+            valueFrom:
+              secretKeyRef:
+                name: {{ include "app.databaseSecretName" . }}
+                key: connectionString.standardSrv
+                optional: false
+          - name: spring_data_mongodb_database
+            value: {{ include "app.vorgangManagerDatabase" . }}
+          {{- end }}
+
+          {{- if ((.Values.ozgcloud).bayernid).enabled }}
+          - name: ozgcloud_bayernid_enabled
+            value: {{ quote .Values.ozgcloud.bayernid.enabled }}
+          - name: grpc_client_bayern-id_address
+            value: {{ quote (required "ozgcloud.bayernid.proxy.address must be set if ozgcloud.bayernid is enabled" (((.Values.ozgcloud).bayernid).proxy).address) }}
+          - name: grpc_client_bayern-id_negotiationType
+            value: {{ (((.Values.ozgcloud).bayernid).proxy).negotiationType | default "PLAINTEXT" }}
+          - name: ozgcloud_bayernid_absender_name
+            value: {{ quote (required "ozgcloud.bayernid.absender.name must be set if ozgcloud.bayernid is enabled" (((.Values.ozgcloud).bayernid).absender).name) }}
+          - name: ozgcloud_bayernid_absender_anschrift
+            value: {{ quote (required "ozgcloud.bayernid.absender.anschrift must be set if ozgcloud.bayernid is enabled" (((.Values.ozgcloud).bayernid).absender).anschrift) }}
+          - name: ozgcloud_bayernid_absender_dienst
+            value: {{ quote (required "ozgcloud.bayernid.absender.dienst must be set if ozgcloud.bayernid is enabled" (((.Values.ozgcloud).bayernid).absender).dienst) }}
+          - name: ozgcloud_bayernid_absender_mandant
+            value: {{ quote (required "ozgcloud.bayernid.absender.mandant must be set if ozgcloud.bayernid is enabled" (((.Values.ozgcloud).bayernid).absender).mandant) }}
+          - name: ozgcloud_bayernid_absender_gemeindeSchluessel
+            value: {{ quote (required "ozgcloud.bayernid.absender.gemeindeSchluessel must be set if ozgcloud.bayernid is enabled" (((.Values.ozgcloud).bayernid).absender).gemeindeSchluessel) }}
+          {{- end }}
+
+
+          {{- if (.Values.ozgcloud).processors}}
+          {{- range $processor_index, $processor := (.Values.ozgcloud).processors }}
+          - name: ozgcloud_processors_{{ $processor_index }}_address
+            value: {{ $processor.address }}
+          - name: ozgcloud_processors_{{ $processor_index }}_name
+            value: {{ $processor.name }}
+          {{- if ($processor).forms}}
+          {{- range $form_index, $form := ($processor).forms }}
+          - name: ozgcloud_processors_{{ $processor_index }}_forms_{{ $form_index }}_formEngineName
+            value: {{ $form.formEngineName }}
+          - name: ozgcloud_processors_{{ $processor_index }}_forms_{{ $form_index }}_formId
+            value: {{ $form.formId }}
+          {{- end }}
+          {{- end}}
+          {{- end }}
+          {{- end}}
+        {{- if or (.Values.database).useExternal (.Values.ozgcloudProxyApi).apikey }}
+        envFrom:
+          {{- if (.Values.database).useExternal }}
+          - secretRef:
+              name: vorgang-manager-database-spring
+          {{- end }}
+          {{- if (.Values.ozgcloudProxyApi).apikey }}
+          - secretRef:
+              name: vorgang-manager-ozgcloud-proxyapi
+          {{- end }}
+        {{- end }}
+        image: "{{ .Values.image.repo }}/{{ .Values.image.name }}:{{ coalesce (.Values.image).tag "latest" }}"
+        imagePullPolicy: Always
+        name: vorgang-manager
+        ports:
+          - containerPort: 9090
+            name: grpc-9090
+            protocol: TCP
+          - containerPort: 8081
+            name: metrics
+            protocol: TCP
+        readinessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /actuator/health/readiness
+            port: 8081
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 3
+        startupProbe:
+          httpGet:
+            path: /actuator/health/readiness
+            port: 8081
+            scheme: HTTP
+          failureThreshold: 10
+          initialDelaySeconds: 30
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 5
+        {{- if .Values.enableLivenessProbe }}
+        livenessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /actuator/health/liveness
+            port: 8081
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 3
+        {{- end }}
+        resources:
+        {{- with .Values.resources }}
+{{ toYaml . | indent 10 }}
+        {{- end }}
+        securityContext:
+          allowPrivilegeEscalation: false
+          privileged: false
+          readOnlyRootFilesystem: false
+          runAsNonRoot: true
+          {{- with (.Values.securityContext).runAsUser }}
+          runAsUser: {{ . }}
+          {{- end }}
+          {{- with (.Values.securityContext).runAsGroup }}
+          runAsGroup: {{ . }}
+          {{- end }}
+          {{- with (.Values.securityContext).capabilities }}
+          capabilities:
+{{ toYaml . | indent 12 }}
+          {{- end }}
+        stdin: true
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+        tty: true
+        volumeMounts:
+          - name: bindings
+            mountPath: "/bindings/ca-certificates/type"
+            subPath: type
+            readOnly: true
+          {{- if (.Values.elasticsearch).enabled }}
+          - name: es-root-ca
+            mountPath: "/bindings/ca-certificates/es-root-ca.pem"
+            subPath: ca.crt
+            readOnly: true
+          {{- end }}
+          - name: mongodb-root-ca
+            mountPath: "/bindings/ca-certificates/mongodb-root-ca.pem"
+            subPath: ca.crt
+            readOnly: true
+          {{- if not .Values.disableUserManagerGrpcTls }}
+          - name: user-manager-tls-certificate
+            mountPath: "/bindings/ca-certificates/user-manager-tls-ca.pem"
+            subPath: ca.crt
+            readOnly: true
+          {{- end }}
+      volumes:
+        - name: bindings
+          configMap:
+            name: bindings-type
+        {{- if (.Values.elasticsearch).enabled }}
+        - name: es-root-ca
+          secret:
+            secretName: {{ .Values.elasticsearch.certificateSecretName }}
+            optional: false
+        {{- end }}
+        - name: mongodb-root-ca
+          secret:
+            secretName: {{ include "app.databaseTlsCert" . }}
+            optional: true
+        {{- if not .Values.disableUserManagerGrpcTls }}
+        - name: user-manager-tls-certificate
+          secret:
+             secretName: user-manager-tls-cert
+        {{- end }}
+      dnsConfig: {}
+      dnsPolicy: ClusterFirst
+      imagePullSecrets:
+      {{- if .Values.imagePullSecret }}
+      - name: {{ .Values.imagePullSecret }}
+      {{ else }}
+      - name: vorgang-manager-image-pull-secret
+      {{- end }}
+      restartPolicy: Always
+      {{- with .Values.hostAliases }}
+      hostAliases:
+{{ toYaml . | indent 8 }}
+      {{- end }}
+      schedulerName: default-scheduler
+      {{- with .Values.podSecurityContext }}
+      securityContext:
+{{ toYaml . | indent 8 }}
+      {{- end }}
+      terminationGracePeriodSeconds: 30
diff --git a/src/main/helm/templates/elasticsearch_cr.yaml b/src/main/helm/templates/elasticsearch_cr.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..251b7a3dcf1402e68c21bcc279c363cb7c5cf329
--- /dev/null
+++ b/src/main/helm/templates/elasticsearch_cr.yaml
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if and (not (.Values.elasticsearch).disableOzgCloudOperator) (.Values.elasticsearch).enabled  }}
+apiVersion: operator.ozgcloud.de/v1
+kind: OzgCloudElasticsearch
+metadata:
+  name: vorgang-manager-elasticsearch-cr
+  namespace: {{ include "app.namespace" $ }}
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/image-pull-secret.yaml b/src/main/helm/templates/image-pull-secret.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d6bc5e39fbca90fd33a0159aa1567d4c9f2d381d
--- /dev/null
+++ b/src/main/helm/templates/image-pull-secret.yaml
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if not (.Values.imagePullSecret) }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: vorgang-manager-image-pull-secret
+  namespace: {{ include "app.namespace" . }}
+type: kubernetes.io/dockerconfigjson
+data:
+  .dockerconfigjson: {{ include "app.imagePullSecret" . }}
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/network_policy.yaml b/src/main/helm/templates/network_policy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d93becbc02bad29f852daaab6e4ea62d4eab0a2a
--- /dev/null
+++ b/src/main/helm/templates/network_policy.yaml
@@ -0,0 +1,105 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if not (.Values.networkPolicy).disabled }} 
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+  name: network-policy-vorgang-manager
+  namespace: {{ .Release.Namespace }}
+spec:
+  podSelector:
+    matchLabels:
+      component: vorgang-manager
+  policyTypes:
+    - Ingress
+    - Egress
+  ingress:
+  - ports:
+    - port: 9090
+    from:
+    - podSelector: 
+        matchLabels:
+          component: alfa
+    - podSelector: 
+        matchLabels:
+          ozg-component: eingangsadapter
+{{- with (.Values.networkPolicy).additionalIngressConfig }}
+{{ toYaml . | indent 2 }}
+{{- end }}
+  egress:
+  - to:
+    - namespaceSelector:
+        matchLabels:
+          kubernetes.io/metadata.name: elastic-system
+      podSelector:
+        matchLabels:
+          elasticsearch.k8s.elastic.co/cluster-name : ozg-search-cluster
+    ports:
+      - port: 9200
+        protocol: TCP
+  - to:
+    - podSelector:
+        matchLabels:
+          component: ozgcloud-mongodb
+    ports:
+      - port: 27017
+        protocol: TCP
+  - to:
+    - podSelector: 
+        matchLabels:
+          component: user-manager
+    ports:
+      - port: 9000
+        protocol: TCP
+{{- if ((.Values.ozgcloud).bayernid).enabled }}
+  - to:
+    - podSelector: 
+        matchLabels:
+          component: bayernid-proxy
+      namespaceSelector:
+        matchLabels:
+          kubernetes.io/metadata.name: {{ required "ozgcloud.bayernid.proxy.namespace must be set if bayernid is enabled" (((.Values.ozgcloud).bayernid).proxy).namespace }}
+    ports:
+      - port: 9090
+        protocol: TCP 
+{{- end }}
+  - to:
+    - namespaceSelector:
+        matchLabels:
+          kubernetes.io/metadata.name: {{ required "networkPolicy.dnsServerNamespace must be set" (.Values.networkPolicy).dnsServerNamespace }}
+    ports:
+      - port: 53
+        protocol: UDP
+      - port: 53
+        protocol: TCP
+      - port: 5353
+        protocol: UDP
+      - port: 5353
+        protocol: TCP
+{{- with (.Values.networkPolicy).additionalEgressConfig }}
+{{ toYaml . | indent 2 }}
+{{- end }}
+
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_read_role.yaml b/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_read_role.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..db4517bebdfddc25916c8839be7f0f9dc733e2fe
--- /dev/null
+++ b/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_read_role.yaml
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if and (not (.Values.elasticsearch).disableOzgCloudOperator) (.Values.elasticsearch).enabled }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: ozgcloud-elasticsearch-operator-secrets-read-role
+  namespace: {{ .Release.Namespace }}
+rules:
+  - apiGroups:
+      - ""
+    resourceNames:
+      - elasticsearch-credentials
+      - elasticsearch-certificate
+    resources:
+      - secrets
+    verbs:
+      - get
+      - list
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_read_role_binding.yaml b/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_read_role_binding.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b9dae5c48c9e075212e8a6932c70f399129f54dd
--- /dev/null
+++ b/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_read_role_binding.yaml
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if and (not (.Values.elasticsearch).disableOzgCloudOperator) (.Values.elasticsearch).enabled }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: ozgcloud-elasticsearch-operator-secrets-read-role-binding
+  namespace: {{ .Release.Namespace }}
+subjects:
+  - kind: ServiceAccount
+    name: ozgcloud-elasticsearch-operator-serviceaccount
+    namespace: {{ required "elasticsearch.operatorNamespace muss angegeben sein" .Values.elasticsearch.operatorNamespace }}
+roleRef:
+  kind: Role
+  name: ozgcloud-elasticsearch-operator-secrets-read-role
+  apiGroup: rbac.authorization.k8s.io
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_write_role.yaml b/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_write_role.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8a1d630ed35c63af081a7b5ef3530fb5a331aad9
--- /dev/null
+++ b/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_write_role.yaml
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if and (not (.Values.elasticsearch).disableOzgCloudOperator) (.Values.elasticsearch).enabled  }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: ozgcloud-elasticsearch-operator-secrets-write-role-vorgang-manager
+  namespace: {{ include "app.namespace" $ }}
+rules:
+  - apiGroups:
+      - ""
+    resources:
+      - secrets
+    verbs:
+      - create
+{{- end }}
diff --git a/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_write_role_binding.yaml b/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_write_role_binding.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..899cae5a6002a0c169dcd3ad1a4486d9a7105175
--- /dev/null
+++ b/src/main/helm/templates/ozgcloud_elasticsearch_operator_secrets_write_role_binding.yaml
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if and (not (.Values.elasticsearch).disableOzgCloudOperator) (.Values.elasticsearch).enabled }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: ozgcloud-elasticsearch-operator-secrets-write-role-binding-vorgang-manager
+  namespace: {{ include "app.namespace" . }}
+subjects:
+  - kind: ServiceAccount
+    name: ozgcloud-elasticsearch-operator-serviceaccount
+    namespace: {{ required "elasticsearch.operatorNamespace muss angegeben sein" .Values.elasticsearch.operatorNamespace }}
+roleRef:
+  kind: Role
+  name: ozgcloud-elasticsearch-operator-secrets-write-role-vorgang-manager
+  apiGroup: rbac.authorization.k8s.io
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/rabbitmq_exchange.yaml b/src/main/helm/templates/rabbitmq_exchange.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c1e4831c7558edbcab5431dfaa60b6b0004c29cc
--- /dev/null
+++ b/src/main/helm/templates/rabbitmq_exchange.yaml
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if (.Values.rabbitmq).enabled }}
+---
+apiVersion: rabbitmq.com/v1beta1
+kind: Exchange
+metadata:
+  name: {{ include "app.namespace" . }}
+  namespace: {{ include "app.namespace" . }}
+spec:
+  name: {{ include "app.namespace" . }}-exchange
+  type: direct
+  autoDelete: false
+  durable: true
+  rabbitmqClusterReference:
+    name: ozg-mq-cluster
+    namespace: rabbitmq-system
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/rabbitmq_permissions.yaml b/src/main/helm/templates/rabbitmq_permissions.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b336d01b04a3819e0b00247fa6e138bf30af06c7
--- /dev/null
+++ b/src/main/helm/templates/rabbitmq_permissions.yaml
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if (.Values.rabbitmq).enabled }}
+---
+apiVersion: rabbitmq.com/v1beta1
+kind: Permission
+metadata:
+  name: {{ include "app.namespace" . }}
+  namespace: {{ include "app.namespace" . }}
+spec:
+  vhost: "/"
+  user: "{{ include "app.namespace" . }}"
+  permissions:
+    write: "{{ include "app.namespace" . }}-.*"
+    configure: ".*"
+    read: "{{ include "app.namespace" . }}-.*"
+  rabbitmqClusterReference:
+    name: ozg-mq-cluster
+    namespace: rabbitmq-system
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/rabbitmq_queue.yaml b/src/main/helm/templates/rabbitmq_queue.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..609aacf1cf53dd29d77346f33582c702dd7ab6e8
--- /dev/null
+++ b/src/main/helm/templates/rabbitmq_queue.yaml
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if (.Values.rabbitmq).enabled }}
+{{- $tenant := .Values.prodEnv -}}
+---
+apiVersion: rabbitmq.com/v1beta1
+kind: Queue
+metadata:
+  name: {{ include "app.namespace" . }}
+  namespace: {{ include "app.namespace" . }}
+spec:
+  name: {{ include "app.namespace" . }}-queue
+  vhost: "/"
+  type: quorum
+  autoDelete: false
+  durable: true
+  rabbitmqClusterReference:
+    name: ozg-mq-cluster
+    namespace: rabbitmq-system
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/rabbitmq_secret.yaml b/src/main/helm/templates/rabbitmq_secret.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..57ce28772c148b6b9b422ea80efd85ed783f79be
--- /dev/null
+++ b/src/main/helm/templates/rabbitmq_secret.yaml
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if (.Values.rabbitmq).enabled }}
+---
+{{- if not (lookup "v1" "Secret" .Release.Namespace "rabbitmq-credentials") }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: rabbitmq-credentials
+  namespace: {{ include "app.namespace" . }}
+  annotations:
+    "helm.sh/resource-policy": "keep"
+type: Opaque
+stringData:
+  password: {{ randAlphaNum 24 | b64enc }}
+  username: {{ include "app.namespace" . }}
+{{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/rabbitmq_user.yaml b/src/main/helm/templates/rabbitmq_user.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d07a00348bb52f05a716db2b24d8f7362dc701d6
--- /dev/null
+++ b/src/main/helm/templates/rabbitmq_user.yaml
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if (.Values.rabbitmq).enabled }}
+---
+apiVersion: rabbitmq.com/v1beta1
+kind: User
+metadata:
+  name: {{ include "app.namespace" . }}
+  namespace: {{ include "app.namespace" . }}
+spec:
+  rabbitmqClusterReference:
+    name: ozg-mq-cluster
+    namespace: rabbitmq-system
+  importCredentialsSecret:
+    name: rabbitmq-credentials
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/secret_ozgcloud_proxyapi.yaml b/src/main/helm/templates/secret_ozgcloud_proxyapi.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..85769f2f5a1a5677445bfaa65c2c2b2e4e019a1e
--- /dev/null
+++ b/src/main/helm/templates/secret_ozgcloud_proxyapi.yaml
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if (.Values.ozgcloudProxyApi).apikey }}
+apiVersion: v1
+kind: Secret
+metadata:
+  name: vorgang-manager-ozgcloud-proxyapi
+  namespace: {{ .Release.Namespace }}
+type: Opaque
+data:
+  ozgcloud_osi_postfach_proxyapi_key: {{ (.Values.ozgcloudProxyApi).apikey | b64enc }}
+{{- end }} 
\ No newline at end of file
diff --git a/src/main/helm/templates/service.yaml b/src/main/helm/templates/service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ad49c6a6e4a13520acb6b782652cf76661372031
--- /dev/null
+++ b/src/main/helm/templates/service.yaml
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ .Release.Name }}
+  namespace: {{ include "app.namespace" . }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+    component: vorgang-manager-service
+spec:
+  type: ClusterIP
+  ports:
+    - name: grpc-9090
+      port: 9090
+      protocol: TCP
+    - name: metrics
+      port: 8081
+      protocol: TCP
+  selector:
+    {{- include "app.matchLabels" . | indent 4 }}
+    component: vorgang-manager
diff --git a/src/main/helm/templates/service_account.yaml b/src/main/helm/templates/service_account.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3bac8e223d1fd108b386d1f06ed4e9fb2284a67c
--- /dev/null
+++ b/src/main/helm/templates/service_account.yaml
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+{{- if (.Values.serviceAccount).create }}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "app.serviceAccountName" . }}
+  namespace: {{ include "app.namespace" . }}
+{{- end }}
\ No newline at end of file
diff --git a/src/main/helm/templates/service_monitor.yaml b/src/main/helm/templates/service_monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9cb70ea55a31a970d210984c0150b027818e03df
--- /dev/null
+++ b/src/main/helm/templates/service_monitor.yaml
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  name: {{ .Release.Name }}
+  namespace: {{ include "app.namespace" . }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+    component: vorgang-manager-service-monitor
+spec:
+  endpoints:
+  - port: metrics
+    path: /actuator/prometheus
+  namespaceSelector:
+    matchNames:
+    - {{ include "app.namespace" . }}
+  selector:
+    matchLabels:
+      {{- include "app.matchLabels" . | indent 6 }}
+      component: vorgang-manager-service
\ No newline at end of file
diff --git a/src/main/helm/templates/tests/test-service-connection.yaml b/src/main/helm/templates/tests/test-service-connection.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..036fa6f558ceff0b1cffaccfa9c0f791e9e2bc9c
--- /dev/null
+++ b/src/main/helm/templates/tests/test-service-connection.yaml
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+kind: Pod
+metadata:
+  name: "{{ .Release.Name }}-test-connection"
+  labels:
+    {{- include "app.defaultLabels" . | nindent 4 }}
+  annotations:
+    "helm.sh/hook": test
+spec:
+  containers:
+    - name: wget
+      image: busybox
+      command: ['wget']
+      args: ['{{ .Release.Name }}:9090']
+  restartPolicy: Never
diff --git a/src/main/helm/values.yaml b/src/main/helm/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0d6d44c9be8ff287667833e19acddf066c5d75ba
--- /dev/null
+++ b/src/main/helm/values.yaml
@@ -0,0 +1,64 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+cluster_env: ""
+
+baseUrl: test.sh.ozg-cloud.de
+
+replicaCount: 2
+
+# ozgcloud:
+#   environment: dev
+
+image:
+  repo: docker.ozg-sh.de
+  name: vorgang-manager
+  tag: latest # [default: latest]
+
+env:
+#   overrideSpringProfiles: "oc,prod"
+  ozgcloudAktenzeichen:
+    enabled: false # [default: false]
+    value: de.ozgcloud.vorgang.vorgang.AktenzeichenProviderEA
+  # customList: # add name value pair for additional environments
+  #   - name: Dinge
+  #     value: true
+
+# customDatabaseCredentials:
+#   authenticationDatabase: admin
+#   database: sh-kiel-dev
+#   host: mongodb.sh-land
+#   password: 
+#   username: sh-kiel-vorgang-manager-dev
+
+
+vorgangmanagerName: vorgang-manager
+
+usermanagerName: user-manager
+
+zufiManager:
+  address: dns://zufi.zufi-manager:9090
+
+elasticsearch:
+    certificateSecretName: elasticsearch-certificate
diff --git a/src/test/helm-linter-values.yaml b/src/test/helm-linter-values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..097de8428b62131a5b06abb258acfaa5ffba3eec
--- /dev/null
+++ b/src/test/helm-linter-values.yaml
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+ozgcloud:
+  environment: test
+  infoManager:
+    address: https://info-manager.my-wonderful-domain.local:9000
+
+networkPolicy:
+  dnsServerNamespace: test-dns-namespace
\ No newline at end of file
diff --git a/src/test/helm/configmap_bindings_type_test.yaml b/src/test/helm/configmap_bindings_type_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1c592b4972fa231b2f49a1e0e0c66ca5779c25af
--- /dev/null
+++ b/src/test/helm/configmap_bindings_type_test.yaml
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: Certificate ConfigMap Binding
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/configmap_bindings_type.yaml
+tests:
+  - it: validate configMap values
+    asserts:
+      - isKind:
+          of: ConfigMap
+      - equal:
+          path: metadata.name
+          value: bindings-type
+      - equal:
+          path: metadata.namespace
+          value: sh-helm-test
+      - equal:
+          path: data
+          value:
+            type: | 
+              ca-certificates
\ No newline at end of file
diff --git a/src/test/helm/deployment_63_chars_test.yaml b/src/test/helm/deployment_63_chars_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3db76de4f0401edbccf45fffe3671b2525e2c2cb
--- /dev/null
+++ b/src/test/helm/deployment_63_chars_test.yaml
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deyploment less than 63 chars
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+  
+chart:
+  name: vorgang-manager
+
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+
+tests:
+  - it: should fail on .Release.Namespace length longer than 63 characters
+    release:
+      namespace: test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890
+    asserts:
+      - failedTemplate:
+          errorMessage: .Release.Namespace test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 ist zu lang (max. 63 Zeichen)
+  - it: should not fail on .Release.Namespace length less than 63 characters
+    asserts:
+      - notFailedTemplate: {}
+  - it: should fail on .Chart.Name-.Chart.Version length longer than 63 characters
+    chart:
+      version: 1.0-test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890
+    asserts:
+      - failedTemplate:
+          errorMessage: .Chart.Name-.Chart.Version vorgang-manager-1.0-test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 ist zu lang (max. 63 Zeichen)
+  - it: should not fail on .Chart.Name-.Chart.Version length less than 63 characters
+    asserts:
+      - notFailedTemplate: {}
\ No newline at end of file
diff --git a/src/test/helm/deployment_bayernid_test.yaml b/src/test/helm/deployment_bayernid_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a3d32c920c75e05ecd3c4ffbb31860ea12e10435
--- /dev/null
+++ b/src/test/helm/deployment_bayernid_test.yaml
@@ -0,0 +1,183 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment bayernid
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+    bayernid:
+      enabled: true
+      proxy:
+        address: https://proxy.address.local
+      absender:
+        postkorbId: "postkorbId"
+        name: "name"
+        anschrift: "anschrift"
+        dienst: "dienst"
+        mandant: "mandant"
+        gemeindeSchluessel: "gemeindeSchluessel"
+tests:
+  - it: should enable bayernid
+    templates:
+      - templates/deployment.yaml
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_bayernid_enabled
+            value: "true"
+
+  - it: should set absender name
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_bayernid_absender_name
+            value: "name"
+  - it: should fail if absender name is not set
+    set:
+      ozgcloud:
+        bayernid:
+          absender:
+            name:
+    asserts:
+      - failedTemplate:
+          errorMessage: "ozgcloud.bayernid.absender.name must be set if ozgcloud.bayernid is enabled"
+
+  - it: should set absender anschrift
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_bayernid_absender_anschrift
+            value: "anschrift"
+  - it: should fail if absender anschrift is not set
+    set:
+      ozgcloud:
+        bayernid:
+          absender:
+            anschrift:
+    asserts:
+      - failedTemplate:
+          errorMessage: "ozgcloud.bayernid.absender.anschrift must be set if ozgcloud.bayernid is enabled"
+
+  - it: should set absender dienst
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_bayernid_absender_dienst
+            value: "dienst"
+  - it: should fail if absender dienst is not set
+    set:
+      ozgcloud:
+        bayernid:
+          absender:
+            dienst:
+    asserts:
+      - failedTemplate:
+          errorMessage: "ozgcloud.bayernid.absender.dienst must be set if ozgcloud.bayernid is enabled"
+
+  - it: should set absender mandant
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_bayernid_absender_mandant
+            value: "mandant"
+  - it: should fail if absender mandant is not set
+    set:
+      ozgcloud:
+        bayernid:
+          absender:
+            mandant:
+    asserts:
+      - failedTemplate:
+          errorMessage: "ozgcloud.bayernid.absender.mandant must be set if ozgcloud.bayernid is enabled"
+
+
+  - it: should contains absender gemeindeSchluessel
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_bayernid_absender_gemeindeSchluessel
+            value: "gemeindeSchluessel"
+  - it: should fail if absender gemeindeSchluessel is not set
+    set:
+      ozgcloud:
+        bayernid:
+          absender:
+            gemeindeSchluessel:
+    asserts:
+      - failedTemplate:
+          errorMessage: "ozgcloud.bayernid.absender.gemeindeSchluessel must be set if ozgcloud.bayernid is enabled"
+
+
+  - it: should set the bayernid proxy grpc address
+    set:
+      ozgcloud:
+        bayernid:
+          proxy:
+            address: https://bayernid-proxy.my-wonderful-domain.local:9000
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_bayern-id_address
+            value: https://bayernid-proxy.my-wonderful-domain.local:9000
+  - it: should fail if bayernid proxy is enabled but proxy address is not configured
+    set:
+      ozgcloud:
+        bayernid:
+          proxy:
+            address: 
+    asserts:
+      - failedTemplate:
+          errorMessage: "ozgcloud.bayernid.proxy.address must be set if ozgcloud.bayernid is enabled"
+
+  - it: should set the bayernid proxy grpc negotiationType
+    set:
+      ozgcloud:
+        bayernid:
+          proxy:
+            negotiationType: NOT_DEFAULT
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_bayern-id_negotiationType
+            value: NOT_DEFAULT
+  - it: should set the bayernid proxy grpc default
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_bayern-id_negotiationType
+            value: PLAINTEXT
\ No newline at end of file
diff --git a/src/test/helm/deployment_bindings_test.yaml b/src/test/helm/deployment_bindings_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..89d32dd2448c931cc6cfa2f80ca49963e5b8d480
--- /dev/null
+++ b/src/test/helm/deployment_bindings_test.yaml
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment user-manager bindings
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: should have volumes
+    template: deployment.yaml
+    set: 
+       usermanagerName: user-manager
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: user-manager-tls-certificate
+            mountPath: "/bindings/ca-certificates/user-manager-tls-ca.pem"
+            subPath: ca.crt
+            readOnly: true
+  - it: should have volume for user-manager-tls-certificate
+    template: deployment.yaml
+    set: 
+       usermanagerName: user-manager
+    asserts:
+      - contains:
+           path: spec.template.spec.volumes
+           content:
+              name: user-manager-tls-certificate
+              secret:
+                 secretName: user-manager-tls-cert
diff --git a/src/test/helm/deployment_container_security_context_test.yaml b/src/test/helm/deployment_container_security_context_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..67deb1451228b51efdccf92ef325da750fccee6e
--- /dev/null
+++ b/src/test/helm/deployment_container_security_context_test.yaml
@@ -0,0 +1,91 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check default values
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.privileged
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.runAsNonRoot
+          value: true
+      - isNull:
+          path: spec.template.spec.containers[0].securityContext.runAsUser
+      - isNull:
+          path: spec.template.spec.containers[0].securityContext.runAsGroup
+      - isNull:
+          path: spec.template.spec.containers[0].securityContext.capabilities
+      - isNull:
+          path: spec.template.spec.securityContext.fsGroup
+  - it: check runAsUser
+    set:
+      securityContext.runAsUser: 1000
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.runAsUser
+          value: 1000
+  - it: check runAsGroup
+    set:
+      securityContext.runAsGroup: 1000
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.runAsGroup
+          value: 1000
+  - it: check fsGroup
+    set:
+      podSecurityContext.fsGroup: 1000
+    asserts:
+      - equal:
+          path: spec.template.spec.securityContext.fsGroup
+          value: 1000
+  - it: check capabilities
+    set:
+      securityContext:
+        capabilities:
+          drop:
+            - ALL
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.capabilities
+          value:
+            drop:
+              - ALL
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_labels_test.yaml b/src/test/helm/deployment_defaults_labels_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..048815c46921dd0eea3d612b56597d34c8018ab1
--- /dev/null
+++ b/src/test/helm/deployment_defaults_labels_test.yaml
@@ -0,0 +1,71 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+  - templates/service.yaml
+  - templates/service_monitor.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check default labels
+    asserts:
+      - equal:
+          path: metadata.labels["app.kubernetes.io/instance"]
+          value: vorgang-manager
+      - equal:
+          path: metadata.labels["app.kubernetes.io/name"]
+          value: vorgang-manager
+      - equal:
+          path: metadata.labels["app.kubernetes.io/part-of"]
+          value: ozgcloud
+      - equal:
+          path: metadata.labels["app.kubernetes.io/namespace"]
+          value: sh-helm-test
+  - it: check component label for deployment
+    templates:
+      - templates/deployment.yaml
+    asserts:
+      - equal:
+          path: spec.template.metadata.labels["component"]
+          value: vorgang-manager
+  - it: check component label for service
+    templates:
+      - templates/service.yaml
+    asserts:
+      - equal:
+          path: metadata.labels["component"]
+          value: vorgang-manager-service
+  - it: check component label for service monitor
+    templates:
+      - templates/service_monitor.yaml
+    asserts:
+      - equal:
+          path: metadata.labels["component"]
+          value: vorgang-manager-service-monitor
\ No newline at end of file
diff --git a/src/test/helm/deployment_env_test.yaml b/src/test/helm/deployment_env_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c681fa6fec54afbbcd2f86aeb2427444fa3614f7
--- /dev/null
+++ b/src/test/helm/deployment_env_test.yaml
@@ -0,0 +1,122 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test environments
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check customList
+    template: deployment.yaml
+    set:
+      env.customList:
+        - name: my_test_environment_name
+          value: "A test value"
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
+
+  - it: check customList test value is not set by default
+    template: deployment.yaml
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
+
+  - it: should have processor configuration
+    template: deployment.yaml
+    set:
+      ozgcloud:
+        environment: dev
+        processors:
+          - address: http://geil
+            name: processor_1
+            forms:
+              - formEngineName: AFM
+                formId: odp_wahlhelfer/odp_wahlhelfer
+              - formEngineName: formEngineTest1
+                formId: ID2
+          - address: http://noch-geiler
+            name: processor_2
+            forms:
+              - formEngineName: FormSolutions
+                formId: form-test
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_0_address
+            value: http://geil
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_0_name
+            value: processor_1
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_0_forms_0_formEngineName
+            value: AFM
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_0_forms_0_formId
+            value: odp_wahlhelfer/odp_wahlhelfer
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_0_forms_1_formEngineName
+            value: formEngineTest1
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_0_forms_1_formId
+            value: ID2
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_1_address
+            value: http://noch-geiler
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_1_name
+            value: processor_2
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_1_forms_0_formId
+            value: form-test
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_processors_1_forms_0_formEngineName
+            value: FormSolutions
\ No newline at end of file
diff --git a/src/test/helm/deployment_grpc_info_manager_address_test.yaml b/src/test/helm/deployment_grpc_info_manager_address_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..11542072c3ac471655983e96221d368c677d49aa
--- /dev/null
+++ b/src/test/helm/deployment_grpc_info_manager_address_test.yaml
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test info-manager address
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should set the grpc info-manager client address
+    set:
+      ozgcloud:
+        environment: dev
+        infoManager: 
+          address: https://info-manager.my-wonderful-domain.local:9000
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_info-manager_address
+            value: https://info-manager.my-wonderful-domain.local:9000
diff --git a/src/test/helm/deployment_grpc_user_manager_address_test.yaml b/src/test/helm/deployment_grpc_user_manager_address_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..00b11f94bd662a9c3956b6a42daaf5957b5a18c1
--- /dev/null
+++ b/src/test/helm/deployment_grpc_user_manager_address_test.yaml
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test user-manager address
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: should set the grpc user-manager client address
+    templates:
+      - templates/deployment.yaml  
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_user-manager_address
+            value: user-manager.sh-helm-test:9000
+  - it: should contain default user-manager grpc negotiationType tls
+    templates:
+      - templates/deployment.yaml
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_user-manager_negotiationType
+            value: TLS
+  - it: should contain user-manager grpc negotiationType plaintext
+    templates:
+      - templates/deployment.yaml
+    set:
+      userManager.grpcClientNegotiationType: PLAINTEXT
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_user-manager_negotiationType
+            value: PLAINTEXT
\ No newline at end of file
diff --git a/src/test/helm/deployment_host_aliases_test.yaml b/src/test/helm/deployment_host_aliases_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1e74b91e27b561d7980049f670d6bb8875ad45b8
--- /dev/null
+++ b/src/test/helm/deployment_host_aliases_test.yaml
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment host aliases
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: should not set hostAliases
+    asserts:
+      - isNull:
+          path: spec.template.spec.hostAliases
+  - it: should set hostAliases
+    set:
+      hostAliases:
+        - ip: "127.0.0.1"
+          hostname:
+          - "eins"
+          - "zwei"
+    asserts:
+      - contains:
+          path: spec.template.spec.hostAliases
+          content:
+            ip: "127.0.0.1"
+            hostname:
+            - "eins"
+            - "zwei"
diff --git a/src/test/helm/deployment_imagepull_secret_test.yaml b/src/test/helm/deployment_imagepull_secret_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..501eddd6e00809fa24b10a326be4a2817a236374
--- /dev/null
+++ b/src/test/helm/deployment_imagepull_secret_test.yaml
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: should use default imagePull secret
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.imagePullSecrets[0].name
+          value: vorgang-manager-image-pull-secret
+  - it: should set the imagePull secret
+    set:
+      imagePullSecret: image-pull-secret
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.imagePullSecrets[0].name
+          value: image-pull-secret
\ No newline at end of file
diff --git a/src/test/helm/deployment_liveness_probe_test.yaml b/src/test/helm/deployment_liveness_probe_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c8bf126ecd1a24d8768a00d45f1c3e3921630bab
--- /dev/null
+++ b/src/test/helm/deployment_liveness_probe_test.yaml
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment livenessProbe
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: livenessProbe should be disabled by default
+    template: deployment.yaml
+    asserts:
+      - notExists:
+          path: spec.template.spec.containers[0].livenessProbe
+
+  - it: enable livenessProbe
+    template: deployment.yaml
+    set:
+      enableLivenessProbe: true
+    asserts:
+      - isSubset:
+          path: spec.template.spec.containers[0].livenessProbe
+          content:
+            failureThreshold: 3
+            httpGet:
+              path: /actuator/health/liveness
+              port: 8081
+              scheme: HTTP
+            periodSeconds: 10
+            successThreshold: 1
+            timeoutSeconds: 3
diff --git a/src/test/helm/deployment_mongodb_test.yaml b/src/test/helm/deployment_mongodb_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..882184dd4ef7e3391c06d847e4cbe66417d923be
--- /dev/null
+++ b/src/test/helm/deployment_mongodb_test.yaml
@@ -0,0 +1,148 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment test mongodb environments
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check mongodb default env
+    template: deployment.yaml
+    release:
+      name: vorgang-manager
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_data_mongodb_uri
+            valueFrom: 
+              secretKeyRef:
+                name: ozg-mongodb-admin-vorgang-manager-user
+                key: connectionString.standardSrv
+                optional: false
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_data_mongodb_database
+            value: vorgang-manager-database
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: mongodb-root-ca
+            secret:
+              secretName: ozg-mongodb-tls-cert
+              optional: true
+
+  - it: check external mongodb
+    template: deployment.yaml
+    release:
+      name: vorgang-manager
+    set:
+      database.useExternal: true
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_data_mongodb_uri
+            valueFrom: 
+              secretKeyRef:
+                name: vorgang-manager-database-admin-vorgang-manager-database-user
+                key: connectionString.standardSrv
+                optional: false
+      - isNull:
+          path: metadata.annotations      
+      - contains:
+          path: spec.template.spec.containers[0].envFrom
+          content:
+            secretRef:
+              name: vorgang-manager-database-spring
+
+  - it: check mongodb set secretname
+    template: deployment.yaml
+    release:
+      name: vorgang-manager
+    set:
+      database.secretName: secret-database-admin-vorgang-manager-user
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_data_mongodb_uri
+            valueFrom: 
+              secretKeyRef:
+                name: secret-database-admin-vorgang-manager-user
+                key: connectionString.standardSrv
+                optional: false
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_data_mongodb_database
+            value: vorgang-manager-database
+
+  - it: check mongodb root ca mount
+    template: deployment.yaml
+    release:
+      name: vorgang-manager
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: mongodb-root-ca
+            mountPath: "/bindings/ca-certificates/mongodb-root-ca.pem"
+            subPath: ca.crt
+            readOnly: true
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: mongodb-root-ca
+            secret:
+              secretName: ozg-mongodb-tls-cert
+              optional: true
+
+  - it: check mongodb tls set tls cert name
+    template: deployment.yaml
+    release:
+      name: vorgang-manager
+    set:
+      database:
+        tls:
+          enabled: true
+          secretName: secret-tls-cert
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: mongodb-root-ca
+            mountPath: "/bindings/ca-certificates/mongodb-root-ca.pem"
+            subPath: ca.crt
+            readOnly: true
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: mongodb-root-ca
+            secret:
+              secretName: secret-tls-cert
+              optional: true
\ No newline at end of file
diff --git a/src/test/helm/deployment_nachrichten_manager_address_test.yaml b/src/test/helm/deployment_nachrichten_manager_address_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4a8132270e6156ad9cd5e88762b056e44b8b417c
--- /dev/null
+++ b/src/test/helm/deployment_nachrichten_manager_address_test.yaml
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test environments
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check if nachrichten-manager address is correct
+    templates:
+      - templates/deployment.yaml 
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_nachrichten-manager_url
+            value:  dns://vorgang-manager.sh-helm-test:9090
diff --git a/src/test/helm/deployment_rabbitmq_test.yaml b/src/test/helm/deployment_rabbitmq_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..23113a67991285651acfc0ba483cae3836c713a6
--- /dev/null
+++ b/src/test/helm/deployment_rabbitmq_test.yaml
@@ -0,0 +1,98 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment test rabbitmq environments
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check rabbitmq spring env
+    template: deployment.yaml
+    set:
+      rabbitmq.enabled: true
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_rabbitmq_username
+            valueFrom: 
+              secretKeyRef:
+                name: rabbitmq-credentials
+                key: username
+                optional: false
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_rabbitmq_password
+            valueFrom: 
+              secretKeyRef:
+                name: rabbitmq-credentials
+                key: password
+                optional: false
+  - it: check rabbitmq spring env is not set by default
+    template: deployment.yaml
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_rabbitmq_username
+            valueFrom: 
+              secretKeyRef:
+                name: rabbitmq-credentials
+                key: username
+                optional: false
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_rabbitmq_password
+            valueFrom: 
+              secretKeyRef:
+                name: rabbitmq-credentials
+                key: password
+                optional: false
+  - it: check rabbitmq spring env is not set
+    template: deployment.yaml
+    set:
+      rabbitmq.enabled: false
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_rabbitmq_username
+            valueFrom: 
+              secretKeyRef:
+                name: rabbitmq-credentials
+                key: username
+                optional: false
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_rabbitmq_password
+            valueFrom: 
+              secretKeyRef:
+                name: rabbitmq-credentials
+                key: password
+                optional: false
diff --git a/src/test/helm/deployment_resources_test.yaml b/src/test/helm/deployment_resources_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..15381543f8f339d2d5088791b178c02d19fdd664
--- /dev/null
+++ b/src/test/helm/deployment_resources_test.yaml
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment
+release:
+  name: vorgang-manager
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: test resources
+    template: deployment.yaml
+    set:
+      resources:
+        limits:
+          cpu: 11m
+          memory: 22Mi
+        requests:
+          cpu: 33m
+          memory: 44Mi
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.cpu
+          value: 11m
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.memory
+          value: 22Mi
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.cpu
+          value: 33m
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.memory
+          value: 44Mi
+  - it: no resources defined
+    template: deployment.yaml
+    asserts:
+      - isEmpty:
+          path: spec.template.spec.containers[0].resources
+
diff --git a/src/test/helm/deployment_service_account_test.yaml b/src/test/helm/deployment_service_account_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a3d515faa74002fc6c7d91210edaf4a22cf3f133
--- /dev/null
+++ b/src/test/helm/deployment_service_account_test.yaml
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment service account
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: should use service account with default name
+    set:
+      serviceAccount:
+        create: true
+    asserts:
+      - equal:
+          path: spec.template.spec.serviceAccountName
+          value: vorgang-manager-service-account
+  - it: should use service account with name
+    set:
+      serviceAccount:
+        create: true
+        name: helm-service-account
+    asserts:
+      - equal:
+          path: spec.template.spec.serviceAccountName
+          value: helm-service-account
+  - it: should use default service account
+    asserts:
+      - isNull:
+          path: spec.template.spec.serviceAccountName
\ No newline at end of file
diff --git a/src/test/helm/deployment_springProfile_test.yaml b/src/test/helm/deployment_springProfile_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..eaffba28f904dc8dedb2c0409fc9bd6531459d7f
--- /dev/null
+++ b/src/test/helm/deployment_springProfile_test.yaml
@@ -0,0 +1,61 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test spring profiles
+release:
+  name: vorgang-manager
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: is kind of Deployment
+    set:
+      env.overrideSpringProfiles: oc,stage,ea
+    templates:
+      - templates/deployment.yaml
+    asserts:
+      - isKind:
+          of: Deployment
+  - it: should override spring profiles
+    set:
+      env.overrideSpringProfiles: oc,stage,ea
+    templates:
+      - templates/deployment.yaml
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc,stage,ea
+  - it: should generate spring profiles
+    templates:
+      - templates/deployment.yaml  
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc, dev
\ No newline at end of file
diff --git a/src/test/helm/deployment_test.yaml b/src/test/helm/deployment_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..cbc25f8095f6cb454910b53bd95a515169de1a59
--- /dev/null
+++ b/src/test/helm/deployment_test.yaml
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test Vorgangfilter general values
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: testIsDeployment
+    template: deployment.yaml
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.containers[0].image
+          value: docker.ozg-sh.de/vorgang-manager:latest
diff --git a/src/test/helm/deployment_test_ozgcloud_base_values_test.yaml b/src/test/helm/deployment_test_ozgcloud_base_values_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e10757be06cc6bb91604d429f548abc545dc6633
--- /dev/null
+++ b/src/test/helm/deployment_test_ozgcloud_base_values_test.yaml
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test ozgcloud base values
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+
+tests:
+  - it: should fail on missing environment
+    template: deployment.yaml
+    asserts:
+      - failedTemplate:
+          errorMessage: ozgcloud.environment muss angegeben sein
+  - it: should not fail on missing environment
+    template: deployment.yaml
+    set:
+      ozgcloud:
+        environment: dev
+    asserts:
+      - notFailedTemplate: {}
+
diff --git a/src/test/helm/deployment_usermanager_url_test.yaml b/src/test/helm/deployment_usermanager_url_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6bef21233752d2081cbd0e434e53ad0cad976c61
--- /dev/null
+++ b/src/test/helm/deployment_usermanager_url_test.yaml
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test environments
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check if user-manager url is correct
+    templates:
+      - templates/deployment.yaml 
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_user-manager_url
+            value:  http://user-manager.sh-helm-test:8080/migration/user
diff --git a/src/test/helm/deployment_zufimanager_address_test.yaml b/src/test/helm/deployment_zufimanager_address_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e42adafa9f76f1ec4d1e8a33f36ac4bfc7eca311
--- /dev/null
+++ b/src/test/helm/deployment_zufimanager_address_test.yaml
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test environments
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check if zufi-manager address is correct
+    templates:
+      - templates/deployment.yaml 
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_zufi-manager_address
+            value:  dns://zufi.zufi-manager:9090
diff --git a/src/test/helm/elasticsearch_cr_test.yaml b/src/test/helm/elasticsearch_cr_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b1ddbc2e164c47945c8cf5bd52dba020a87aac25
--- /dev/null
+++ b/src/test/helm/elasticsearch_cr_test.yaml
@@ -0,0 +1,76 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: Elasticsearch cr
+release:
+  name: vorgang-manager
+  namespace: by-helm-test
+templates:
+  - templates/elasticsearch_cr.yaml
+tests:
+  - it: should contain apiVersion
+    set:
+      elasticsearch:
+        enabled: true
+    asserts:
+      - isAPIVersion:
+          of: operator.ozgcloud.de/v1
+  - it: should contain kind
+    set:
+      elasticsearch:
+        enabled: true
+    asserts:
+      - isKind:
+          of: OzgCloudElasticsearch
+  - it: should have metadata name
+    set:
+      elasticsearch:
+        enabled: true
+    asserts:
+      - equal:
+          path: metadata.name
+          value: vorgang-manager-elasticsearch-cr
+  - it: should have metadata namespace
+    set:
+      app:
+        namespace: test
+      elasticsearch:
+        enabled: true
+    asserts:
+      - equal:
+          path: metadata.namespace
+          value: by-helm-test
+  - it: should create cr if enabled
+    set:
+      elasticsearch:
+        enabled: true
+    asserts:
+      - hasDocuments:
+          count: 1
+        documentIndex: 1
+  - it: should NOT create cr if not enabled
+    asserts:
+      - hasDocuments:
+          count: 0
+        documentIndex: 0
\ No newline at end of file
diff --git a/src/test/helm/elasticsearch_deployment_test.yaml b/src/test/helm/elasticsearch_deployment_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9f7cbfd61a7bc9b92bd9d38886c0cb1df8a8d109
--- /dev/null
+++ b/src/test/helm/elasticsearch_deployment_test.yaml
@@ -0,0 +1,186 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: elasticsearch tests
+templates:
+  - templates/deployment.yaml
+set:
+  ozgcloud:
+    environment: dev
+tests:
+  - it: check if elastic credentials are disabled by default
+    template: deployment.yaml
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_address
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: address
+                optional: false
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_username
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: username
+                optional: false
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_password
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: password
+                optional: false
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_index
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: index
+                optional: false
+
+      - notContains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: es-root-ca
+            mountPath: "/bindings/ca-certificates/es-root-ca.pem"
+            subPath: ca.crt
+            readOnly: true
+
+      - notContains:
+          path: spec.template.spec.volumes
+          content:
+            name: es-root-ca
+            secret:
+              secretName: elasticsearch-root-ca
+
+
+
+
+
+  - it: smoke test if elasticsearch is disabled when set to false
+    template: deployment.yaml
+    set:
+      ozgcloud.environment: test
+      database.password: hase
+      elasticsearch.enabled: false
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_address
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: address
+                optional: false
+
+  - it: check enabled elastic credentials
+    template: deployment.yaml
+    set:
+      elasticsearch.enabled: true
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_address
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: address
+                optional: false
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_username
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: username
+                optional: false
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_password
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: password
+                optional: false
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_elasticsearch_index
+            valueFrom:
+              secretKeyRef:
+                name: elasticsearch-credentials
+                key: index
+                optional: false
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_ssl_bundle_pem_es-root-ca_truststore_certificate
+            value: /bindings/ca-certificates/es-root-ca.pem      
+                        
+
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: bindings
+            mountPath: "/bindings/ca-certificates/type"
+            subPath: type
+            readOnly: true
+                
+      - contains:
+          path: spec.template.spec.containers[0].volumeMounts
+          content:
+            name: es-root-ca
+            mountPath: "/bindings/ca-certificates/es-root-ca.pem"
+            subPath: ca.crt
+            readOnly: true      
+          
+                
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: bindings
+            configMap:
+              name: bindings-type   
+
+      - contains:
+          path: spec.template.spec.volumes
+          content:
+            name: es-root-ca
+            secret:
+              secretName: elasticsearch-certificate
+              optional: false
diff --git a/src/test/helm/image_pull_secret_test.yaml b/src/test/helm/image_pull_secret_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a3024aa65c794a3dee11af64bca46863b31d7625
--- /dev/null
+++ b/src/test/helm/image_pull_secret_test.yaml
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test image pull secret
+templates:
+  - templates/image-pull-secret.yaml
+release:
+  name: vorgang-manager
+  namespace: helm-test
+tests:
+  - it: should match basic data
+    set:
+      imageCredentials:
+        registry: docker.ozg-sh.de
+        username: test
+        password: test1234
+        email: webmaster@ozg-sh.de
+    asserts:
+      - hasDocuments:
+          count: 1
+      - containsDocument:
+          kind: Secret
+          apiVersion: v1
+      - equal:
+          path: metadata.name
+          value: vorgang-manager-image-pull-secret
+      - equal:
+          path: metadata.namespace
+          value: helm-test          
+      - isNotNullOrEmpty:
+          path: data[".dockerconfigjson"]
+
+  - it: should not create image pull secret
+    set:
+      imagePullSecret: "image-pull-secret"
+    asserts:
+      - hasDocuments:
+          count: 0
\ No newline at end of file
diff --git a/src/test/helm/network_policy_test.yaml b/src/test/helm/network_policy_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..35a3bb44e00d7a8bfcf615efefe23f473baa59a1
--- /dev/null
+++ b/src/test/helm/network_policy_test.yaml
@@ -0,0 +1,306 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: network policy test
+release:
+  namespace: by-helm-test
+templates:
+  - templates/network_policy.yaml
+tests:
+  - it: should match apiVersion
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - isAPIVersion:
+          of: networking.k8s.io/v1
+
+  - it: should match kind
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - isKind:
+          of: NetworkPolicy
+
+  - it: validate metadata
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - equal:
+          path: metadata
+          value:
+            name: network-policy-vorgang-manager
+            namespace: by-helm-test
+
+  - it: should set policy target matchLabel
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - equal:
+          path: spec.podSelector
+          value:
+            matchLabels:
+              component: vorgang-manager
+
+
+  - it: should add policyType Egress
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - contains:
+          path: spec.policyTypes
+          content: Egress
+
+  - it: should add policyType Ingress
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - contains:
+          path: spec.policyTypes
+          content: Ingress
+
+  - it: should add ingress rule for eingangsmanager and alfa
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - contains:
+          path: spec.ingress
+          content:
+              ports:
+              - port: 9090
+              from:
+              - podSelector: 
+                  matchLabels:
+                    component: alfa
+              - podSelector: 
+                  matchLabels:
+                    ozg-component: eingangsadapter
+
+
+  - it: should add egress rule to elasticsearch
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+              to:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: elastic-system
+                podSelector:
+                  matchLabels:
+                    elasticsearch.k8s.elastic.co/cluster-name : ozg-search-cluster
+              ports:
+                - port: 9200
+                  protocol: TCP
+
+  - it: should add egress rule to mongodb
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+              to:
+              - podSelector:
+                  matchLabels:
+                    component: ozgcloud-mongodb
+              ports:
+                - port: 27017
+                  protocol: TCP
+
+  - it: should add egress rule to user-manager
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+              to:
+              - podSelector: 
+                  matchLabels:
+                    component: user-manager
+              ports:
+                - port: 9000
+                  protocol: TCP
+
+  - it: should add egress rule to dns service
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+              to:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: test-dns-namespace
+              ports:
+                - port: 53
+                  protocol: UDP
+                - port: 53
+                  protocol: TCP
+                - port: 5353
+                  protocol: UDP
+                - port: 5353
+                  protocol: TCP
+
+  - it: should add egress rule to nachrichten-bayernid-proxy if bayernid is enabled
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+      ozgcloud:
+        bayernid:
+          enabled: true
+          proxy:
+            namespace: bayernidProxyNamespace
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+            to:
+            - podSelector: 
+                matchLabels:
+                  component: bayernid-proxy
+              namespaceSelector:
+                matchLabels:
+                  kubernetes.io/metadata.name: bayernidProxyNamespace
+            ports:
+            - port: 9090
+              protocol: TCP 
+
+  - it: should not add egress rule to bayernid-proxy if bayernid is disabled
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+      ozgcloud:
+        bayernid:
+          enabled: false
+    asserts:
+      - notContains:
+          path: spec.egress
+          content:
+            to:
+            - podSelector: 
+                matchLabels:
+                  component: bayernid-proxy
+              namespaceSelector:
+                matchLabels:
+                      kubernetes.io/metadata.name: bayernidProxyNamespace
+            ports:
+            - port: 9090
+              protocol: TCP 
+  
+  - it: should throw error if bayernid-proxy is enabled but bayernid namespace is not set
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+      ozgcloud:
+        bayernid:
+          enabled: true
+    asserts:
+      - failedTemplate:
+          errorMessage: ozgcloud.bayernid.proxy.namespace must be set if bayernid is enabled
+
+  - it: add ingress rule by values
+    set:
+      networkPolicy:
+        ssoPublicIp: 51.89.117.53/32
+        dnsServerNamespace: test-namespace-dns
+        additionalIngressConfig:
+        - from:
+          - podSelector: 
+              matchLabels:
+                component: client2
+    asserts:
+      - contains:
+          path: spec.ingress
+          content:
+            from:
+            - podSelector: 
+                matchLabels:
+                  component: client2
+
+  - it: add egress rules by values
+    set:
+      networkPolicy:
+        additionalEgressConfig:
+        - to:
+          - ipBlock:
+              cidr: 1.2.3.4/32
+        - to:
+          - podSelector:
+              matchLabels:
+                component: ozg-testservice
+          ports:
+            - port: 12345
+              protocol: TCP
+
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+    - contains:
+        path: spec.egress
+        content:
+          to:
+          - ipBlock:
+              cidr: 1.2.3.4/32
+    - contains:
+        path: spec.egress
+        content:
+          to:
+          - podSelector:
+              matchLabels:
+                component: ozg-testservice
+          ports:
+            - port: 12345
+              protocol: TCP
+
+  - it: test network policy disabled
+    set:
+      networkPolicy:
+        disabled: true
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - hasDocuments:
+          count: 0
+
+  - it: test network policy unset should be disabled
+    set:
+      networkPolicy:
+        disabled: false
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - hasDocuments:
+          count: 1
\ No newline at end of file
diff --git a/src/test/helm/ozgcloud_elasticsearch_operator_secrets_read_role_binding_test.yaml b/src/test/helm/ozgcloud_elasticsearch_operator_secrets_read_role_binding_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5b756142a2c819a86f9d7bdc586467b44c7742f6
--- /dev/null
+++ b/src/test/helm/ozgcloud_elasticsearch_operator_secrets_read_role_binding_test.yaml
@@ -0,0 +1,97 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test ozg_operator_secrets_read_role_binding
+release:
+  name: release-name
+  namespace: by-helm-test
+templates:
+  - templates/ozgcloud_elasticsearch_operator_secrets_read_role_binding.yaml
+tests:
+  - it: should contain header data
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - isAPIVersion:
+          of: rbac.authorization.k8s.io/v1
+      - isKind:
+          of: RoleBinding
+
+  - it: should have metadata
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - equal:
+          path: metadata.name
+          value: ozgcloud-elasticsearch-operator-secrets-read-role-binding
+      - equal:
+          path: metadata.namespace
+          value: by-helm-test
+
+  - it: should have subjects values
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - equal:
+          path: subjects
+          value:
+            - kind: ServiceAccount
+              name: ozgcloud-elasticsearch-operator-serviceaccount
+              namespace: test-operator-namespace
+
+  - it: should have roleRef values
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - equal:
+          path: roleRef.kind
+          value: Role
+      - equal:
+          path: roleRef.name
+          value: ozgcloud-elasticsearch-operator-secrets-read-role
+      - equal:
+          path: roleRef.apiGroup
+          value: rbac.authorization.k8s.io
+
+  - it: should not create RoleBinding if elasticsearch is disabled
+    asserts:
+      - hasDocuments:
+          count: 0
+
+  - it: should not create RoleBinding if ozgcloud operator is not enabled
+    set:
+      elasticsearch:
+        disableOzgCloudOperator: true
+        enabled: true
+    asserts:
+      - hasDocuments:
+          count: 0
\ No newline at end of file
diff --git a/src/test/helm/ozgcloud_elasticsearch_operator_secrets_read_role_test.yaml b/src/test/helm/ozgcloud_elasticsearch_operator_secrets_read_role_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d21b7ad3c48e51cb4c83b7a6fac036434aed091b
--- /dev/null
+++ b/src/test/helm/ozgcloud_elasticsearch_operator_secrets_read_role_test.yaml
@@ -0,0 +1,86 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test ozg_operator_secrets_read_role
+release:
+  name: release-name
+  namespace: by-helm-test
+templates:
+  - templates/ozgcloud_elasticsearch_operator_secrets_read_role.yaml
+tests:
+  - it: should contain header data
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - isAPIVersion:
+          of: rbac.authorization.k8s.io/v1
+      - isKind:
+          of: Role
+  - it: should have metadata
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - equal:
+          path: metadata.name
+          value: ozgcloud-elasticsearch-operator-secrets-read-role
+      - equal:
+          path: metadata.namespace
+          value: by-helm-test
+  - it: should have rules
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - equal:
+          path: rules
+          value:
+          - apiGroups:
+               - ""
+            resourceNames:
+              - elasticsearch-credentials
+              - elasticsearch-certificate
+            resources:
+               - secrets
+            verbs:
+               - get
+               - list
+
+  - it: should not create Role if elasticsearch is not enabled
+    asserts:
+      - hasDocuments:
+          count: 0
+
+  - it: should not create Role if ozgcloud operator is not enabled
+    set:
+      elasticsearch:
+        disableOzgCloudOperator: true
+        enabled: true
+    asserts:
+      - hasDocuments:
+          count: 0
\ No newline at end of file
diff --git a/src/test/helm/ozgcloud_elasticsearch_operator_secrets_write_role_binding_test.yaml b/src/test/helm/ozgcloud_elasticsearch_operator_secrets_write_role_binding_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8815c5839eebe6bcc24cc2724012dc434aed77fc
--- /dev/null
+++ b/src/test/helm/ozgcloud_elasticsearch_operator_secrets_write_role_binding_test.yaml
@@ -0,0 +1,104 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: ozgcloud_elasticsearch_operator_secrets_write_role_binding test
+release:
+  name: test-release-name
+  namespace: by-helm-test
+templates:
+  - templates/ozgcloud_elasticsearch_operator_secrets_write_role_binding.yaml
+tests:
+  - it: should contain header data
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - isAPIVersion:
+          of: rbac.authorization.k8s.io/v1
+      - isKind:
+          of: RoleBinding
+  - it: should have metadata
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - equal:
+          path: metadata.name
+          value: ozgcloud-elasticsearch-operator-secrets-write-role-binding-vorgang-manager
+      - equal:
+          path: metadata.namespace
+          value: by-helm-test
+  - it: should have subjects values
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - contains:
+          path: subjects
+          content:
+            kind: ServiceAccount
+            name: ozgcloud-elasticsearch-operator-serviceaccount
+            namespace: test-operator-namespace
+  - it: should have roleRef values
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - equal:
+          path: roleRef.kind
+          value: Role
+      - equal:
+          path: roleRef.name
+          value: ozgcloud-elasticsearch-operator-secrets-write-role-vorgang-manager
+      - equal:
+          path: roleRef.apiGroup
+          value: rbac.authorization.k8s.io
+  - it: should not create RoleBinding if no elasticsearch users available
+    asserts:
+      - hasDocuments:
+          count: 0
+  - it: should have subjects values
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - contains:
+          path: subjects
+          content:
+            kind: ServiceAccount
+            name: ozgcloud-elasticsearch-operator-serviceaccount
+            namespace: test-operator-namespace
+  - it: should not create RoleBinding if ozgcloud operator is not enabled
+    set:
+      elasticsearch:
+        disableOzgCloudOperator: true
+        enabled: true
+    asserts:
+      - hasDocuments:
+          count: 0
\ No newline at end of file
diff --git a/src/test/helm/ozgcloud_elasticsearch_operator_secrets_write_role_test.yaml b/src/test/helm/ozgcloud_elasticsearch_operator_secrets_write_role_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b0848c4ec3d42f1563b0c9da3fc1ffc4f4cb6107
--- /dev/null
+++ b/src/test/helm/ozgcloud_elasticsearch_operator_secrets_write_role_test.yaml
@@ -0,0 +1,81 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: ozgcloud_elasticsearch_operator_secrets_write_role test
+release:
+  name: test-release-name
+  namespace: by-helm-test
+templates:
+  - templates/ozgcloud_elasticsearch_operator_secrets_write_role.yaml
+tests:
+  - it: should contain header data
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - isAPIVersion:
+          of: rbac.authorization.k8s.io/v1
+      - isKind:
+          of: Role
+  - it: should have metadata
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - equal:
+          path: metadata.name
+          value: ozgcloud-elasticsearch-operator-secrets-write-role-vorgang-manager
+      - equal:
+          path: metadata.namespace
+          value: by-helm-test
+  - it: should have rules
+    set:
+      elasticsearch:
+        operatorNamespace: test-operator-namespace
+        enabled: true
+    asserts:
+      - contains:
+          path: rules
+          content:
+            apiGroups:
+               - ""
+            resources:
+               - secrets
+            verbs:
+               - create
+  - it: should not create Role if elasticsearch is not enabled
+    asserts:
+      - hasDocuments:
+          count: 0
+
+  - it: should not create Role if ozgcloud operator is not enabled
+    set:
+      elasticsearch:
+        disableOzgCloudOperator: true
+        enabled: true
+    asserts:
+      - hasDocuments:
+          count: 0
\ No newline at end of file
diff --git a/src/test/helm/rabbitmq_exchange_test.yaml b/src/test/helm/rabbitmq_exchange_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e8301174ef2833b416e0b004e549751bcb1311ee
--- /dev/null
+++ b/src/test/helm/rabbitmq_exchange_test.yaml
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test rabbitmq exchange
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/rabbitmq_exchange.yaml
+tests:
+  - it: test if name like namespace
+    set:
+      rabbitmq.enabled: true
+    asserts:
+      - isKind:
+          of: Exchange
+      - equal:
+          path: metadata.name
+          value: sh-helm-test
+  - it: test if spec name like namespace
+    set:
+      rabbitmq.enabled: true
+    asserts:
+      - isKind:
+          of: Exchange
+      - equal:
+          path: spec.name
+          value: sh-helm-test-exchange
+  - it: should not create rabbitmq exchange
+    set:
+      rabbitmq.enabled: false
+    asserts:
+      - hasDocuments:
+          count: 0
+  - it: should not create rabbitmq exchange by default
+    asserts:
+      - hasDocuments:
+          count: 0
diff --git a/src/test/helm/rabbitmq_permissions_test.yaml b/src/test/helm/rabbitmq_permissions_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..cd0223deddd65e07569bad9e9bae28bbc167c4f9
--- /dev/null
+++ b/src/test/helm/rabbitmq_permissions_test.yaml
@@ -0,0 +1,72 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test rabbitmq permissions
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/rabbitmq_permissions.yaml
+tests:
+  - it: test specs user like namespace
+    set:
+      rabbitmq.enabled: true
+    asserts:
+      - isKind:
+          of: Permission
+      - equal:
+          path: spec.user
+          value: sh-helm-test
+  - it: test specs write permissions
+    set:
+      rabbitmq.enabled: true
+      rabbitmq.cluster.name: rabbit-test
+      rabbitmq.cluster.namespace: rabbit-test-ns
+    asserts:
+      - isKind:
+          of: Permission
+      - equal:
+          path: spec.permissions.write
+          value: "sh-helm-test-.*"
+  - it: test specs read permissions
+    set:
+      rabbitmq.enabled: true
+    asserts:
+      - isKind:
+          of: Permission
+      - equal:
+          path: spec.permissions.read
+          value: "sh-helm-test-.*"
+  - it: should not create rabbitmq permission
+    set:
+      rabbitmq.enabled: false
+    asserts:
+      - hasDocuments:
+          count: 0
+  - it: should not create rabbitmq permission by default
+    set:
+      ozgcloud.environment: test
+    asserts:
+      - hasDocuments:
+          count: 0
\ No newline at end of file
diff --git a/src/test/helm/rabbitmq_queue_test.yaml b/src/test/helm/rabbitmq_queue_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..33bc41e08dc993cc7936979cc2d8846fde83a48d
--- /dev/null
+++ b/src/test/helm/rabbitmq_queue_test.yaml
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test rabbitmq queue
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/rabbitmq_queue.yaml
+tests:
+  - it: test if name like namespace
+    set:
+      rabbitmq.enabled: true
+    asserts:
+      - isKind:
+          of: Queue
+      - equal:
+          path: metadata.name
+          value: sh-helm-test
+  - it: should not create rabbitmq queue
+    set:
+      rabbitmq.enabled: false
+    asserts:
+      - hasDocuments:
+          count: 0
+  - it: should not create rabbitmq queue by default
+    asserts:
+      - hasDocuments:
+          count: 0
\ No newline at end of file
diff --git a/src/test/helm/rabbitmq_user_test.yaml b/src/test/helm/rabbitmq_user_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3e9f145d09caadeee50ae98f295dee5ae326ed01
--- /dev/null
+++ b/src/test/helm/rabbitmq_user_test.yaml
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test rabbitmq user
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/rabbitmq_user.yaml
+tests:
+  - it: test if name like namespace
+    set:
+      rabbitmq.enabled: true
+    asserts:
+      - isKind:
+          of: User
+      - equal:
+          path: metadata.name
+          value: sh-helm-test
+  - it: should not create rabbitmq user
+    set:
+      rabbitmq.enabled: false
+    asserts:
+      - hasDocuments:
+          count: 0
+  - it: should not create rabbitmq user by default
+    set:
+      ozgcloud.environment: test
+    asserts:
+      - hasDocuments:
+          count: 0
\ No newline at end of file
diff --git a/src/test/helm/service_account_test.yaml b/src/test/helm/service_account_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d3b2cc05a57fc8a130aa3f32a4fde67d17712c19
--- /dev/null
+++ b/src/test/helm/service_account_test.yaml
@@ -0,0 +1,62 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test service account
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/service_account.yaml
+tests:
+  - it: should create service account with default name
+    set:
+      serviceAccount:
+        create: true
+    asserts:
+      - isKind:
+          of: ServiceAccount
+      - equal:
+          path: metadata.name
+          value: vorgang-manager-service-account
+      - equal:
+          path: metadata.namespace
+          value: sh-helm-test
+  - it: should create service account with name
+    set:
+      serviceAccount:
+        create: true
+        name: helm-service-account
+    asserts:
+      - isKind:
+          of: ServiceAccount
+      - equal:
+          path: metadata.name
+          value: helm-service-account
+      - equal:
+          path: metadata.namespace
+          value: sh-helm-test
+  - it: should not create service account
+    asserts:
+      - hasDocuments:
+        count: 0
\ No newline at end of file
diff --git a/src/test/helm/service_monitor_test.yaml b/src/test/helm/service_monitor_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e09fc87590b135b4deea68ec1b7016d137efc8a7
--- /dev/null
+++ b/src/test/helm/service_monitor_test.yaml
@@ -0,0 +1,65 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/service_monitor.yaml
+tests:
+  - it: should have the label component with value vorgang-manager-service-monitor attached
+    asserts:
+      - isKind:
+          of: ServiceMonitor
+      - equal:
+          path: metadata.labels["component"]
+          value: vorgang-manager-service-monitor
+  - it: should be able to enable the endpoint
+    asserts:
+      - isKind:
+          of: ServiceMonitor
+      - contains:
+          path: spec.endpoints
+          content:
+            port: metrics
+            path: /actuator/prometheus
+  - it: namespace selector should contain the namespace
+    asserts:
+      - contains:
+          path: spec.namespaceSelector.matchNames
+          content: sh-helm-test
+  - it: selector should contain the component label with the value vorgang-manager-service
+    asserts:
+      - equal:
+          path: spec.selector.matchLabels["component"]
+          value: vorgang-manager-service
+  - it: selector should contain helm recommended labels name and namespace
+    asserts:
+      - equal:
+          path: spec.selector.matchLabels["app.kubernetes.io/name"]
+          value: vorgang-manager
+      - equal:
+          path: spec.selector.matchLabels["app.kubernetes.io/namespace"]
+          value: sh-helm-test
diff --git a/src/test/helm/service_test.yaml b/src/test/helm/service_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c4ec4e81209f96828f5d269739594b172dea0d18
--- /dev/null
+++ b/src/test/helm/service_test.yaml
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment
+release:
+  name: vorgang-manager
+  namespace: sh-helm-test
+templates:
+  - templates/service.yaml
+tests:
+  - it: should have the label component with value vorgang-manager-service attached
+    asserts:
+      - isKind:
+          of: Service
+      - equal:
+          path: metadata.labels.component
+          value: vorgang-manager-service
+  - it: should be of type ClusterIP
+    asserts:
+      - equal:
+          path: spec.type
+          value: ClusterIP
+  - it: ports should contain the grpc port
+    asserts:
+      - contains:
+          path: spec.ports
+          content:
+            name: grpc-9090
+            port: 9090
+            protocol: TCP
+          count: 1
+          any: true
+  - it: ports should contain the metrics port
+    asserts:
+      - contains:
+          path: spec.ports
+          content:
+            name: metrics
+            port: 8081
+            protocol: TCP
+          count: 1
+          any: true
+  - it: selector should contain the component label with the value vorgang-manager
+    asserts:
+      - equal:
+          path: spec.selector.component
+          value: vorgang-manager
+  - it: selector should contain helm recommended labels name and namespace
+    asserts:
+      - equal:
+          path: spec.selector["app.kubernetes.io/name"]
+          value: vorgang-manager
+      - equal:
+          path: spec.selector["app.kubernetes.io/namespace"]
+          value: sh-helm-test
+  
\ No newline at end of file
diff --git a/vorgang-manager-base/pom.xml b/vorgang-manager-base/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5f21670a37188cfac5f8761e86b7c8ff69e95f9f
--- /dev/null
+++ b/vorgang-manager-base/pom.xml
@@ -0,0 +1,86 @@
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-parent</artifactId>
+		<version>3.0.1</version>
+		<relativePath />
+	</parent>
+
+	<groupId>de.ozgcloud.vorgang</groupId>
+	<artifactId>vorgang-manager-base</artifactId>
+	<version>2.4.0</version>
+
+	<name>OZG-Cloud Vorgang Manager Base</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.security</groupId>
+			<artifactId>spring-security-core</artifactId>
+		</dependency>
+		
+		<dependency>
+			<groupId>net.devh</groupId>
+			<artifactId>grpc-server-spring-boot-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-validation</artifactId>
+		</dependency>
+		
+		<!-- TEST -->
+		<dependency>
+			<groupId>org.springframework.security</groupId>
+			<artifactId>spring-security-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<executions>
+					<execution>
+						<goals>
+							<goal>test-jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>
\ No newline at end of file
diff --git a/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/LogRunner.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/LogRunner.java
new file mode 100644
index 0000000000000000000000000000000000000000..230a2b01f9e44a120ff6192cba4c8b172cc11270
--- /dev/null
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/LogRunner.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang;
+
+import java.nio.charset.Charset;
+
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.stereotype.Component;
+
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@Component
+class LogRunner implements ApplicationListener<ContextRefreshedEvent> {
+
+	@Override
+	public void onApplicationEvent(ContextRefreshedEvent event) {
+		LOG.info("Standard Charset: " + Charset.defaultCharset());
+
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/VorgangManagerServerApplication.java
similarity index 59%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java
rename to vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/VorgangManagerServerApplication.java
index aaf2af20881206a460d8cfa662b09962404cdaf1..9909628b142bed49281786e808b4b528c82250f8 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/VorgangManagerServerApplication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto;
+package de.ozgcloud.vorgang;
 
 import java.util.TimeZone;
 
@@ -30,32 +30,45 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.EnableAspectJAutoProxy;
-import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
-import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.event.ApplicationEventMulticaster;
+import org.springframework.context.event.SimpleApplicationEventMulticaster;
+import org.springframework.core.task.AsyncTaskExecutor;
 import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
+import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor;
 
-import io.mongock.runner.springboot.EnableMongock;
-
-@SpringBootApplication(scanBasePackages = "de.itvsh.*")
-@EnableAsync
+@SpringBootApplication(scanBasePackages = { "de.ozgcloud" })
+@EnableAsync(proxyTargetClass = true)
 @EnableScheduling
 @EnableAspectJAutoProxy(proxyTargetClass = true)
-@EnableMongock
-@ConfigurationPropertiesScan("de.itvsh.ozg.pluto.common.*")
-@EnableMongoRepositories(basePackages = { "de.itvsh.ozg.pluto.vorgang", "de.itvsh.ozg.pluto.attached_item", "de.itvsh.ozg.pluto.command" })
-@EnableElasticsearchRepositories(basePackages = "de.itvsh.ozg.pluto.common.search")
-public class PlutoServerApplication {
+@ConfigurationPropertiesScan("de.ozgcloud.vorgang.*")
+public class VorgangManagerServerApplication {
 
 	public static void main(String[] args) {
 		TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
-		SpringApplication.run(PlutoServerApplication.class, args);
+		SpringApplication.run(VorgangManagerServerApplication.class, args);
 	}
 
 	@Bean
 	AuthenticationTrustResolver trustResolver() {
 		return new AuthenticationTrustResolverImpl();
 	}
+
+	@Bean
+	@Primary
+	DelegatingSecurityContextAsyncTaskExecutor delegatingTaskExecutor(AsyncTaskExecutor applicationTaskExecutor) {
+		return new DelegatingSecurityContextAsyncTaskExecutor(applicationTaskExecutor);
+	}
+
+
+	@Bean(name = "applicationEventMulticaster")
+	ApplicationEventMulticaster simpleApplicationEventMulticaster(AsyncTaskExecutor delegatingTaskExecutor) {
+		var eventMulticaster = new SimpleApplicationEventMulticaster();
+
+		eventMulticaster.setTaskExecutor(delegatingTaskExecutor);
+		return eventMulticaster;
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CallContext.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContext.java
similarity index 86%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CallContext.java
rename to vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContext.java
index 629dc7b5290a5fee224855ea80866a0bc4d334ad..a3a6c4595c35eef968067ea8ea4c309c1c6171e5 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CallContext.java
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
-
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
+package de.ozgcloud.vorgang.callcontext;
 
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Getter;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextAuthenticationToken.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextAuthenticationToken.java
similarity index 94%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextAuthenticationToken.java
rename to vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextAuthenticationToken.java
index 434c9dfbcc86e799b7352c5bd93d972b1f7b0d3a..ffba372a0c97a4b65c4e413d6b521768dfaecbd4 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextAuthenticationToken.java
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextAuthenticationToken.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
 
 import java.util.Collection;
 import java.util.stream.Collectors;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptor.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextHandleInterceptor.java
similarity index 80%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptor.java
rename to vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextHandleInterceptor.java
index 2cc8ae9fd28994f8cc173635a3cfbac2693cac9f..0a606293ce8f18d4385f31ed32f004f5b9880b75 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptor.java
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextHandleInterceptor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,21 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
+
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
 
-import java.nio.charset.StandardCharsets;
-import java.util.Collection;
-import java.util.Optional;
 import java.util.UUID;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
 
 import org.apache.logging.log4j.CloseableThreadContext;
 import org.springframework.security.core.context.SecurityContextHolder;
 
 import io.grpc.ForwardingServerCallListener;
 import io.grpc.Metadata;
-import io.grpc.Metadata.Key;
 import io.grpc.ServerCall;
 import io.grpc.ServerCall.Listener;
 import io.grpc.ServerCallHandler;
@@ -136,26 +132,5 @@ class CallContextHandleInterceptor implements ServerInterceptor {
 		void clearSecurityContext() {
 			SecurityContextHolder.clearContext();
 		}
-
 	}
-
-	// TODO move to a grpcUtil class in common
-	static Optional<String> getFromHeaders(String key, Metadata headers) {
-		return Optional.ofNullable(headers.get(createKeyOf(key))).map(val -> new String(val, StandardCharsets.UTF_8));
-	}
-
-	// TODO move to a grpcUtil class in common
-	static Collection<String> getCollection(String key, Metadata headers) {
-		return Optional.ofNullable(headers.getAll(createKeyOf(key)))
-				.map(vals -> StreamSupport.stream(vals.spliterator(), false))
-				.orElseGet(Stream::empty)
-				.map(bytes -> new String(bytes, StandardCharsets.UTF_8))
-				.toList();
-	}
-
-	// TODO move to a grpcUtil class in common
-	static Key<byte[]> createKeyOf(String key) {
-		return Key.of(key, Metadata.BINARY_BYTE_MARSHALLER);
-	}
-
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUser.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextUser.java
similarity index 93%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUser.java
rename to vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextUser.java
index 0c973fc187625837a5c317f64a40c4f61b3cbbcd..5be7d613c8830d09a657f804f48e77ec417bd53d 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUser.java
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CallContextUser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
 
 import java.io.Serializable;
 import java.util.Collection;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserService.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CurrentUserService.java
similarity index 96%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserService.java
rename to vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CurrentUserService.java
index a2bf6a835fcebf2f8e3d9d7df8cba2e501e23737..8b5e269ef0b593c26c2433c13c8fe7a27e7acf0d 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserService.java
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/CurrentUserService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
 
 import java.util.Optional;
 import java.util.stream.Collectors;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/User.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/User.java
similarity index 83%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/User.java
rename to vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/User.java
index 6806e0ecec55a974b2bb918680e56c3481245edc..9d735615a5cae60c28758b41b8e46da80fa669ad 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/User.java
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/User.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.callcontext;
 
-import javax.validation.constraints.NotNull;
-
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUser;
+import jakarta.validation.constraints.NotNull;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Getter;
@@ -33,7 +31,7 @@ import lombok.ToString;
 
 /**
  *
- * @deprecated Use {@link CallContextUser} instead
+ * @deprecated Use {@link de.ozgcloud.vorgang.callcontext.CallContextUser} instead
  *
  */
 @Deprecated(since = "0.24.0", forRemoval = true)
diff --git a/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/VorgangManagerClientCallContextAttachingInterceptor.java b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/VorgangManagerClientCallContextAttachingInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..77b60f25c80e5557b9037093a7bbc11d401e975b
--- /dev/null
+++ b/vorgang-manager-base/src/main/java/de/ozgcloud/vorgang/callcontext/VorgangManagerClientCallContextAttachingInterceptor.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.callcontext;
+
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
+
+import java.util.UUID;
+
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.ClientInterceptor;
+import io.grpc.ForwardingClientCall.SimpleForwardingClientCall;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+
+public class VorgangManagerClientCallContextAttachingInterceptor implements ClientInterceptor {
+
+	static final String KEY_REQUEST_ID = "REQUEST_ID-bin";
+	static final String KEY_CLIENT_NAME = "CLIENT_NAME-bin";
+
+	public static final String VORGANG_MANAGER_CLIENT_NAME = "OzgCloud_VorgangManager";
+
+	// <A> = Request, <B> = Response
+	@Override
+	public <A, B> ClientCall<A, B> interceptCall(MethodDescriptor<A, B> method, CallOptions callOptions, Channel next) {
+		return new CallContextAttachingClientCall<>(next.newCall(method, callOptions));
+	}
+
+	final class CallContextAttachingClientCall<A, B> extends SimpleForwardingClientCall<A, B> {
+
+		protected CallContextAttachingClientCall(ClientCall<A, B> delegate) {
+			super(delegate);
+		}
+
+		@Override
+		public void start(Listener<B> responseListener, Metadata headers) {
+			headers.merge(buildCallContextMetadata());
+			super.start(responseListener, headers);
+		}
+
+		private Metadata buildCallContextMetadata() {
+			var metadata = new Metadata();
+
+			metadata.put(createKeyOf(KEY_REQUEST_ID), UUID.randomUUID().toString().getBytes());
+			metadata.put(createKeyOf(KEY_CLIENT_NAME), VORGANG_MANAGER_CLIENT_NAME.getBytes());
+
+			return metadata;
+		}
+	}
+}
diff --git a/vorgang-manager-base/src/main/resources/.empty b/vorgang-manager-base/src/main/resources/.empty
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptorTest.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextHandleInterceptorTest.java
similarity index 94%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptorTest.java
rename to vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextHandleInterceptorTest.java
index 0e83ee10e5b8d70dbd65faeacbdc85dc9e53358d..9b46d592b5e05bf7ff496349234f1d2e6ab993ce 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptorTest.java
+++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextHandleInterceptorTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
 
-import static de.itvsh.ozg.pluto.common.callcontext.CallContextHandleInterceptor.*;
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
+import static de.ozgcloud.vorgang.callcontext.CallContextHandleInterceptor.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -36,8 +37,7 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.springframework.security.core.context.SecurityContextHolder;
 
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextHandleInterceptor.LogContextSettingListener;
+import de.ozgcloud.vorgang.callcontext.CallContextHandleInterceptor.LogContextSettingListener;
 import io.grpc.Metadata;
 import io.grpc.ServerCall;
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextTestFactory.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextTestFactory.java
similarity index 66%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextTestFactory.java
rename to vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextTestFactory.java
index 37aa23de7d50ebe893fdb156e485404a84665eb9..ab2588db7d09f5636d16df75dd778f4a31cd8595 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextTestFactory.java
+++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,18 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
 
-import static de.itvsh.ozg.pluto.command.UserTestFactory.*;
-import static de.itvsh.ozg.pluto.common.callcontext.CallContextHandleInterceptor.*;
+import static de.ozgcloud.vorgang.callcontext.CallContextHandleInterceptor.*;
+import static de.ozgcloud.vorgang.callcontext.UserTestFactory.*;
 
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
-import de.itvsh.ozg.pluto.command.CallContext;
-import de.itvsh.ozg.pluto.command.User;
-import de.itvsh.ozg.pluto.command.UserTestFactory;
+import de.ozgcloud.common.grpc.GrpcUtil;
 import io.grpc.Metadata;
 
 public class CallContextTestFactory {
@@ -65,12 +63,12 @@ public class CallContextTestFactory {
 
 	public static Metadata createMetadata() {
 		var result = new Metadata();
-		result.put(CallContextHandleInterceptor.createKeyOf(KEY_USER_ID), ID.getBytes());
-		result.put(CallContextHandleInterceptor.createKeyOf(KEY_USER_NAME), NAME.getBytes());
-		result.put(CallContextHandleInterceptor.createKeyOf(KEY_CLIENT_NAME), CLIENT.getBytes());
-		result.put(CallContextHandleInterceptor.createKeyOf(KEY_ACCESS_LIMITED_ORGAID), ORGANISATORISCHE_EINHEITEN_ID.getBytes());
-		result.put(CallContextHandleInterceptor.createKeyOf(KEY_REQUEST_ID), REQUEST_ID.getBytes());
-		result.put(CallContextHandleInterceptor.createKeyOf(KEY_ACCESS_LIMITED), DO_ORGA_ID_ACCESS_CHECK.toString().getBytes());
+		result.put(GrpcUtil.HEADER_KEY_USER_ID, ID.getBytes());
+		result.put(GrpcUtil.createKeyOf(KEY_USER_NAME), NAME.getBytes());
+		result.put(GrpcUtil.createKeyOf(KEY_CLIENT_NAME), CLIENT.getBytes());
+		result.put(GrpcUtil.createKeyOf(KEY_ACCESS_LIMITED_ORGAID), ORGANISATORISCHE_EINHEITEN_ID.getBytes());
+		result.put(GrpcUtil.createKeyOf(KEY_REQUEST_ID), REQUEST_ID.getBytes());
+		result.put(GrpcUtil.createKeyOf(KEY_ACCESS_LIMITED), DO_ORGA_ID_ACCESS_CHECK.toString().getBytes());
 
 		return result;
 	}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUserTestFactory.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextUserTestFactory.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUserTestFactory.java
rename to vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextUserTestFactory.java
index 7ddefbed7d3c65f655b046f8a87cb3d95994b1a7..cb365ffb0861d54f2ed84bc0f6ef1c2041a54736 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUserTestFactory.java
+++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextUserTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
 
 import java.util.Optional;
 
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-
 public class CallContextUserTestFactory {
 
+	public static final String ID = UserTestFactory.ID;
+
 	public static CallContextUser create() {
 		return createBuilder().build();
 	}
@@ -36,7 +36,7 @@ public class CallContextUserTestFactory {
 	public static CallContextUser.CallContextUserBuilder createBuilder() {
 		return CallContextUser.builder()
 				.clientName(CallContextTestFactory.CLIENT)
-				.userId(Optional.of(UserTestFactory.ID))
+				.userId(Optional.of(ID))
 				.userName(Optional.of(UserTestFactory.NAME))
 				.organisatorischeEinheitenId(UserTestFactory.ORGANISATORISCHE_EINHEITEN_ID)
 				.organisationEinheitenIdCheckNecessary(CallContextTestFactory.DO_ORGA_ID_ACCESS_CHECK);
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceITCase.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CurrentUserServiceITCase.java
similarity index 95%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceITCase.java
rename to vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CurrentUserServiceITCase.java
index d11241eb5948b1306140cf00bfbf4968f3c7c59f..9bf0607a482caa30a5c6d89044dbde17a1567144 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceITCase.java
+++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CurrentUserServiceITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
+
+import static org.assertj.core.api.Assertions.*;
 
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -31,9 +33,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.test.context.support.WithAnonymousUser;
 import org.springframework.security.test.context.support.WithMockUser;
 
-import static org.assertj.core.api.Assertions.*;
-
-import de.itvsh.kop.common.test.ITCase;
+import de.ozgcloud.common.test.ITCase;
 
 @ITCase
 class CurrentUserServiceITCase {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceTest.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CurrentUserServiceTest.java
similarity index 95%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceTest.java
rename to vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CurrentUserServiceTest.java
index 07a4908e366a3f7e0d6aa3ff0b7cc8da33e91836..627f30bee0343070702d6adfdf14429a31416fe1 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceTest.java
+++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CurrentUserServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/TestCallContextAttachingInterceptor.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/TestCallContextAttachingInterceptor.java
similarity index 75%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/TestCallContextAttachingInterceptor.java
rename to vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/TestCallContextAttachingInterceptor.java
index 6eac9cfcb23eace0bad3b2fe7448c15f5c77bb28..6adc3ce305decc0b895997fa329b62e8d8dd32fc 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/TestCallContextAttachingInterceptor.java
+++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/TestCallContextAttachingInterceptor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.callcontext;
+package de.ozgcloud.vorgang.callcontext;
 
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelleTestFactory;
+import de.ozgcloud.common.grpc.GrpcUtil;
 import io.grpc.CallOptions;
 import io.grpc.Channel;
 import io.grpc.ClientCall;
@@ -37,7 +37,7 @@ import lombok.Setter;
 public class TestCallContextAttachingInterceptor implements ClientInterceptor {
 
 	private final String clientName = CallContextTestFactory.CLIENT;
-	private final String organisationEinheitId = ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID;
+	private final String organisationEinheitId = UserTestFactory.ORGANISATORISCHE_EINHEITEN_ID;
 	private final Boolean organisationEinheitIdCheckNecessary = Boolean.TRUE;
 
 	@Override
@@ -54,11 +54,9 @@ public class TestCallContextAttachingInterceptor implements ClientInterceptor {
 		@Override
 		public void start(Listener<RespT> responseListener, Metadata headers) {
 			var metadata = new Metadata();
-			metadata.put(CallContextHandleInterceptor.createKeyOf(CallContextHandleInterceptor.KEY_CLIENT_NAME),
-					clientName.getBytes());
-			metadata.put(CallContextHandleInterceptor.createKeyOf(CallContextHandleInterceptor.KEY_ACCESS_LIMITED_ORGAID),
-					organisationEinheitId.getBytes());
-			metadata.put(CallContextHandleInterceptor.createKeyOf(CallContextHandleInterceptor.KEY_ACCESS_LIMITED),
+			metadata.put(GrpcUtil.createKeyOf(CallContextHandleInterceptor.KEY_CLIENT_NAME), clientName.getBytes());
+			metadata.put(GrpcUtil.createKeyOf(CallContextHandleInterceptor.KEY_ACCESS_LIMITED_ORGAID), organisationEinheitId.getBytes());
+			metadata.put(GrpcUtil.createKeyOf(CallContextHandleInterceptor.KEY_ACCESS_LIMITED),
 					organisationEinheitIdCheckNecessary.toString().getBytes());
 
 			headers.merge(metadata);
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/UserTestFactory.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/UserTestFactory.java
similarity index 86%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/UserTestFactory.java
rename to vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/UserTestFactory.java
index 2862afe1b0771bcc94e37b66da08bf698d8beee1..4bc4c347e44ae2e89137df62dbdbde21004dbf67 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/UserTestFactory.java
+++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/UserTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.callcontext;
 
 import java.util.UUID;
 
@@ -29,7 +29,7 @@ public class UserTestFactory {
 
 	public static final String ID = UUID.randomUUID().toString();
 	public static final String NAME = "Udo Jürgens";
-	public static final String ORGANISATORISCHE_EINHEITEN_ID = UUID.randomUUID().toString();
+	public static final String ORGANISATORISCHE_EINHEITEN_ID = "08150815";
 
 	public static User create() {
 		return createBuilder().build();
diff --git a/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/VorgangManagerClientCallContextAttachingInterceptorTest.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/VorgangManagerClientCallContextAttachingInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9357815f2f3f0d229fbdc63be816bef62cf33af8
--- /dev/null
+++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/VorgangManagerClientCallContextAttachingInterceptorTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.callcontext;
+
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
+import static de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+
+class VorgangManagerClientCallContextAttachingInterceptorTest {
+
+	@InjectMocks
+	private VorgangManagerClientCallContextAttachingInterceptor interceptor;
+
+	@Nested
+	class TestInterceptCall<A, B> {
+
+		@Mock
+		private MethodDescriptor<A, B> method;
+		@Mock
+		private CallOptions callOptions;
+		@Mock
+		private Channel next;
+		@Mock
+		private ClientCall<Object, Object> nextCall;
+
+		@Mock
+		private ClientCall.Listener<B> listener;
+		@Mock
+		private Metadata headers;
+		@Captor
+		private ArgumentCaptor<Metadata> metadataCaptor;
+
+		@BeforeEach
+		void initMocks() {
+			when(next.newCall(any(), any())).thenReturn(nextCall);
+		}
+
+		@Test
+		void shouldAddClientName() {
+			var addedMetadata = interceptCall();
+
+			assertThat(addedMetadata.get(createKeyOf(KEY_CLIENT_NAME))).isEqualTo(VORGANG_MANAGER_CLIENT_NAME.getBytes());
+		}
+
+		@Test
+		void shouldAddRequestId() {
+			var addedMetadata = interceptCall();
+
+			assertThat(addedMetadata.get(createKeyOf(KEY_REQUEST_ID))).isNotNull();
+		}
+
+		private Metadata interceptCall() {
+			var call = interceptor.interceptCall(method, callOptions, next);
+
+			call.start(listener, headers);
+
+			verify(headers).merge(metadataCaptor.capture());
+			return metadataCaptor.getValue();
+		}
+	}
+
+}
diff --git a/vorgang-manager-base/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/vorgang-manager-base/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 0000000000000000000000000000000000000000..79b126e6cdb86bec1f4f08c205de8961bde1934a
--- /dev/null
+++ b/vorgang-manager-base/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1 @@
+org.mockito.junit.jupiter.MockitoExtension
\ No newline at end of file
diff --git a/vorgang-manager-base/src/test/resources/junit-platform.properties b/vorgang-manager-base/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1cebb76d5a58ac034b2627d12411d82d1e85821e
--- /dev/null
+++ b/vorgang-manager-base/src/test/resources/junit-platform.properties
@@ -0,0 +1 @@
+junit.jupiter.extensions.autodetection.enabled = true
\ No newline at end of file
diff --git a/vorgang-manager-base/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/vorgang-manager-base/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000000000000000000000000000000000..ca6ee9cea8ec189a088d50559325d4e84ff8ad09
--- /dev/null
+++ b/vorgang-manager-base/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline
\ No newline at end of file
diff --git a/vorgang-manager-command/lombok.config b/vorgang-manager-command/lombok.config
new file mode 100644
index 0000000000000000000000000000000000000000..81661f0fd9c5f6e2f40f39aa9ee13f7017fc2726
--- /dev/null
+++ b/vorgang-manager-command/lombok.config
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+lombok.log.fieldName=LOG
+lombok.log.slf4j.flagUsage = ERROR
+lombok.log.log4j.flagUsage = ERROR
+lombok.data.flagUsage = ERROR
+lombok.nonNull.exceptionType = IllegalArgumentException
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
diff --git a/vorgang-manager-command/pom.xml b/vorgang-manager-command/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..da45403f8bee197bf08e3df2c5cb233195e68ed6
--- /dev/null
+++ b/vorgang-manager-command/pom.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-dependencies</artifactId>
+		<version>3.0.1</version>
+		<relativePath/>
+	</parent>
+	
+	<groupId>de.ozgcloud.command</groupId>
+	<artifactId>command-manager</artifactId>
+	<version>2.4.0</version>
+	<name>OZG-Cloud Command Manager</name>
+
+	<properties>
+		<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
+	</properties>
+	
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>de.ozgcloud.common</groupId>
+			<artifactId>ozgcloud-common-lib</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<optional>true</optional>
+		</dependency>
+	</dependencies>
+	
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<version>${maven-jar-plugin.version}</version>
+				<executions>
+					<execution>
+						<goals>
+							<goal>test-jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>
diff --git a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/Command.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/Command.java
similarity index 90%
rename from pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/Command.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/Command.java
index a0fd95afd49db53b37f04a95155d5f7cc0b3aada..07acbeaa4bafc4baab232d11078a7e67acba146a 100644
--- a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/Command.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/Command.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.command;
 
 import java.time.ZonedDateTime;
 import java.util.Map;
@@ -33,7 +33,8 @@ public interface Command {
 	public String getId();
 	public String getVorgangId();
 	public String getRelationId();
-	public long getRelationVersion();
+
+	public Long getRelationVersion();
 
 	public String getOrder();
 
@@ -48,4 +49,6 @@ public interface Command {
 	public Map<String, String> getBody();
 
 	public String getErrorMessage();
+
+	String getCreatedResource();
 }
diff --git a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandCreatedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandCreatedEvent.java
similarity index 92%
rename from pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandCreatedEvent.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandCreatedEvent.java
index 7ab71eb31e4aee8e62732d02f4dcb5de847ed56a..ab7acc734dce70103f8790fc0b0b5adc84954063 100644
--- a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandCreatedEvent.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandCreatedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.command;
 
 import org.springframework.context.ApplicationEvent;
 
diff --git a/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandExecutedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandExecutedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..b862438acdc8ae9f2551f9381cff8d1b5dd7a491
--- /dev/null
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandExecutedEvent.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.command;
+
+import org.springframework.context.ApplicationEvent;
+
+import lombok.Getter;
+
+@Getter
+public class CommandExecutedEvent extends ApplicationEvent {
+
+	private static final long serialVersionUID = 1L;
+
+	private final Command command;
+
+	private String createdResource;
+
+	@Deprecated
+	public CommandExecutedEvent(String commandId) {
+		super(commandId);
+
+		command = null;
+	}
+
+	@Deprecated
+	public CommandExecutedEvent(String commandId, String createdResource) {
+		super(commandId);
+		command = null;
+		this.createdResource = createdResource;
+	}
+
+	public CommandExecutedEvent(Command command) {
+		super(command.getId());
+
+		this.command = command;
+	}
+
+	public CommandExecutedEvent(Command command, String createdResource) {
+		super(command.getId());
+		this.command = command;
+		this.createdResource = createdResource;
+	}
+
+	@Override
+	public String getSource() {
+		return (String) super.getSource();
+	}
+
+	public Command getCommand() {
+		return command;
+	}
+}
\ No newline at end of file
diff --git a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandFailedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandFailedEvent.java
similarity index 93%
rename from pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandFailedEvent.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandFailedEvent.java
index fd894201e19f418d49656b557d94b62073325f63..dfaa57414e362e8186205389096ffb3aeda0b92e 100644
--- a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandFailedEvent.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandFailedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.command;
 
 import org.springframework.context.ApplicationEvent;
 
diff --git a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachServerProcessException.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandRevokeFailedEvent.java
similarity index 74%
rename from mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachServerProcessException.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandRevokeFailedEvent.java
index f3acfe246721ff6f2a92041f789239599f748810..a86875c42526f0c27d6ce663ea19a594820285f3 100644
--- a/mail-service/src/main/java/de/itvsh/ozg/mail/postfach/OsiPostfachServerProcessException.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandRevokeFailedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.command;
 
-class OsiPostfachServerProcessException extends OsiPostfachException {// NOSONAR
+public class CommandRevokeFailedEvent extends CommandFailedEvent {
 
 	private static final long serialVersionUID = 1L;
 
-	public OsiPostfachServerProcessException() {
-		super("Osi-Postfach server returned false", OsiPostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE);
+	public CommandRevokeFailedEvent(String commandId, String errorMessage) {
+		super(commandId, errorMessage);
 	}
-}
\ No newline at end of file
+
+}
diff --git a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandExecutedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandRevokedEvent.java
similarity index 77%
rename from pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandExecutedEvent.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandRevokedEvent.java
index 9a4a5c2419e1b0b7e62f601b4414c8c5539eb35d..2613a6ae0b72b9ea88e75d33569021f589313cea 100644
--- a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandExecutedEvent.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandRevokedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,20 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.command;
 
 import org.springframework.context.ApplicationEvent;
 
-public class CommandExecutedEvent extends ApplicationEvent {
+public class CommandRevokedEvent extends ApplicationEvent {
 
 	private static final long serialVersionUID = 1L;
 
-	protected CommandExecutedEvent(String commandId) {
-		super(commandId);
+	public CommandRevokedEvent(Command source) {
+		super(source);
 	}
 
 	@Override
-	public String getSource() {
-		return (String) super.getSource();
+	public Command getSource() {
+		return (Command) super.getSource();
 	}
-}
\ No newline at end of file
+}
diff --git a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandStatus.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandStatus.java
similarity index 90%
rename from pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandStatus.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandStatus.java
index 0a91a365cb2f8dad4195a716d492aff1ced8050f..51fcb85f35fcbf1d0d23e9a78207d844f07c0959 100644
--- a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/CommandStatus.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/CommandStatus.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.command;
 
 public enum CommandStatus {
 	PENDING, FINISHED, ERROR, REVOKE_PENDING, REVOKED;
diff --git a/vorgang-manager-command/src/main/java/de/ozgcloud/command/RevokeCommandEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/RevokeCommandEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9da9e74bf06f01571733c98d15439cfad91437de
--- /dev/null
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/RevokeCommandEvent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.command;
+
+import org.springframework.context.ApplicationEvent;
+
+public class RevokeCommandEvent extends ApplicationEvent {
+
+	private static final long serialVersionUID = 1L;
+
+	public RevokeCommandEvent(Command source) {
+		super(source);
+	}
+
+	@Override
+	public Command getSource() {
+		return (Command) super.getSource();
+	}
+}
diff --git a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/VorgangCreatedEvent.java b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangCreatedEvent.java
similarity index 89%
rename from pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/VorgangCreatedEvent.java
rename to vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangCreatedEvent.java
index 44c3995bd22f4511e8c4f9b5436fd01de18de53a..8a7d34ddbca882d04639747201601cc2eebd0850 100644
--- a/pluto-interface/src/main/java/de/itvsh/ozg/pluto/command/VorgangCreatedEvent.java
+++ b/vorgang-manager-command/src/main/java/de/ozgcloud/command/VorgangCreatedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.command;
 
 import org.springframework.context.ApplicationEvent;
 
 public class VorgangCreatedEvent extends ApplicationEvent {
 
+	private static final long serialVersionUID = 1L;
+
 	public VorgangCreatedEvent(String vorgangId) {
 		super(vorgangId);
 	}
diff --git a/vorgang-manager-command/src/test/java/de/ozgcloud/command/CommandCreatedEventTestFactory.java b/vorgang-manager-command/src/test/java/de/ozgcloud/command/CommandCreatedEventTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..8331a11b255754aa1f1404c21db595d48495b00e
--- /dev/null
+++ b/vorgang-manager-command/src/test/java/de/ozgcloud/command/CommandCreatedEventTestFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.command;
+
+public class CommandCreatedEventTestFactory {
+
+	public static CommandCreatedEvent create() {
+		return new CommandCreatedEvent(CommandTestFactory.create());
+	}
+
+	public static CommandCreatedEvent withCommand(Command command) {
+		return new CommandCreatedEvent(command);
+	}
+
+}
diff --git a/vorgang-manager-command/src/test/java/de/ozgcloud/command/CommandTestFactory.java b/vorgang-manager-command/src/test/java/de/ozgcloud/command/CommandTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..e24b3f9e82f1ddf14f14ba5a5f9348fd8adaa081
--- /dev/null
+++ b/vorgang-manager-command/src/test/java/de/ozgcloud/command/CommandTestFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.command;
+
+import java.util.Map;
+import java.util.UUID;
+
+public class CommandTestFactory {
+
+	public static final String ID = UUID.randomUUID().toString();
+	public static final String VORGANG_ID = UUID.randomUUID().toString();
+	public static final String ORDER = "DO_TEST";
+
+	public static final String CREATED_BY = UUID.randomUUID().toString();
+
+	public static Command create() {
+		return createBuilder().build();
+	}
+
+	public static TestCommand.TestCommandBuilder createBuilder() {
+		return TestCommand.builder()
+				.id(ID)
+				.vorgangId(VORGANG_ID)
+				.body(Map.of())
+				.bodyObject(Map.of())
+				.createdBy(CREATED_BY);
+	}
+}
diff --git a/vorgang-manager-command/src/test/java/de/ozgcloud/command/TestCommand.java b/vorgang-manager-command/src/test/java/de/ozgcloud/command/TestCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd4704652c5a194a413b10a49f30c58771cfa1ac
--- /dev/null
+++ b/vorgang-manager-command/src/test/java/de/ozgcloud/command/TestCommand.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.command;
+
+import java.time.ZonedDateTime;
+import java.util.Map;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+public class TestCommand implements Command {
+
+	private String id;
+	private String vorgangId;
+	private String relationId;
+	private Long relationVersion;
+
+	private String order;
+
+	private ZonedDateTime createdAt;
+	private ZonedDateTime finishedAt;
+	private String createdBy;
+	private String createdByName;
+
+	private CommandStatus status;
+
+	private Map<String, Object> bodyObject;
+	private Map<String, String> body;
+
+	private String errorMessage;
+
+	private String createdResource;
+}
diff --git a/vorgang-manager-interface/pom.xml b/vorgang-manager-interface/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fec773f41bdbdb828378179c4da7d28d98144ff8
--- /dev/null
+++ b/vorgang-manager-interface/pom.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-dependencies</artifactId>
+		<version>3.0.1</version>
+		<relativePath/>
+	</parent>
+
+	<groupId>de.ozgcloud.vorgang</groupId>
+	<artifactId>vorgang-manager-interface</artifactId>
+	<version>2.4.0</version>
+
+	<name>OZG-Cloud Vorgang Manager gRPC Interface</name>
+	<description>Interface (gRPC) for Vorgang Manager Server</description>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+		<java.version>17</java.version>
+		<maven.compiler.source>${java.version}</maven.compiler.source>
+		<maven.compiler.target>${java.version}</maven.compiler.target>
+
+		<find-and-replace-maven-plugin.version>1.1.0</find-and-replace-maven-plugin.version>
+		<ozgcloud.license.version>1.6.0</ozgcloud.license.version>
+	</properties>
+
+	<dependencyManagement>
+		<dependencies>
+			<dependency>
+				<groupId>de.ozgcloud.common</groupId>
+				<artifactId>ozgcloud-common-dependencies</artifactId>
+				<version>${ozgcloud-common.version}</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+
+	<dependencies>
+		<!-- GRPC -->
+		<dependency>
+			<groupId>io.grpc</groupId>
+			<artifactId>grpc-stub</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>io.grpc</groupId>
+			<artifactId>grpc-protobuf</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>jakarta.annotation</groupId>
+			<artifactId>jakarta.annotation-api</artifactId>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<sourceDirectory>src/main/protobuf</sourceDirectory>
+
+		<extensions>
+			<extension>
+				<groupId>kr.motd.maven</groupId>
+				<artifactId>os-maven-plugin</artifactId>
+			</extension>
+		</extensions>
+
+		<plugins>
+			<plugin>
+				<groupId>com.github.os72</groupId>
+				<artifactId>protoc-jar-maven-plugin</artifactId>
+				<version>${protoc-jar-plugin.version}</version>
+				<executions>
+					<execution>
+						<phase>generate-sources</phase>
+						<goals>
+							<goal>run</goal>
+						</goals>
+						<configuration>
+							<outputTargets>
+								<outputTarget>
+									<type>java</type>
+								</outputTarget>
+								<outputTarget>
+									<type>grpc-java</type>
+									<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.58.0</pluginArtifact>
+								</outputTarget>
+							</outputTargets>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>io.github.floverfelt</groupId>
+				<artifactId>find-and-replace-maven-plugin</artifactId>
+				<version>${find-and-replace-maven-plugin.version}</version>
+				<executions>
+					<execution>
+						<id>exec</id>
+						<phase>process-sources</phase>
+						<goals>
+							<goal>find-and-replace</goal>
+						</goals>
+						<configuration>
+							<replacementType>file-contents</replacementType>
+							<baseDir>target/generated-sources/</baseDir>
+							<findRegex>javax</findRegex>
+							<replaceValue>jakarta</replaceValue>
+							<recursive>true</recursive>
+							<fileMask>.java</fileMask>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<!-- TODO move to common -->
+			<plugin>
+				<groupId>com.mycila</groupId>
+				<artifactId>license-maven-plugin</artifactId>
+				<configuration>
+					<mapping>
+						<proto>SLASHSTAR_STYLE</proto>
+						<config>SCRIPT_STYLE</config>
+					</mapping>
+					<licenseSets>
+						<licenseSet>
+							<header>license/eupl_v1_2_de/header.txt</header>
+							<excludes>
+								<exclude>**/*.yaml</exclude>
+								<exclude>**/*.yml</exclude>
+								<exclude>README.md</exclude>
+							</excludes>
+						</licenseSet>
+					</licenseSets>
+				</configuration>
+				<dependencies>
+					<dependency>
+						<groupId>de.ozgcloud.common</groupId>
+						<artifactId>ozgcloud-common-license</artifactId>
+						<version>${ozgcloud.license.version}</version>
+					</dependency>
+				</dependencies>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-source-plugin</artifactId>
+				<version>3.2.1</version>
+				<executions>
+					<execution>
+						<id>attach-sources</id>
+						<goals>
+							<goal>jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+
+	<distributionManagement>
+		<repository>
+			<id>ozg-nexus</id>
+			<name>ozg-releases</name>
+			<url>https://nexus.ozg-sh.de/repository/ozg-releases/</url>
+		</repository>
+		<snapshotRepository>
+			<id>ozg-snapshots-nexus</id>
+			<name>ozg-snapshots</name>
+			<url>https://nexus.ozg-sh.de/repository/ozg-snapshots/</url>
+		</snapshotRepository>
+	</distributionManagement>
+</project>
diff --git a/vorgang-manager-interface/src/main/protobuf/bescheid.model.proto b/vorgang-manager-interface/src/main/protobuf/bescheid.model.proto
new file mode 100644
index 0000000000000000000000000000000000000000..b038dfe7e063938616ef05915fa23fab5f9b0ea6
--- /dev/null
+++ b/vorgang-manager-interface/src/main/protobuf/bescheid.model.proto
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+ syntax = "proto3";
+
+ package de.ozgcloud.bescheid;
+
+ option java_multiple_files = true;
+ option java_package = "de.ozgcloud.bescheid";
+ option java_outer_classname = "BescheidModelProto";
+
+message GrpcGetBescheidDraftRequest {
+	string vorgangId = 1;
+}
+
+message GrpcGetBescheidDraftResponse {
+	GrpcBescheid bescheid = 1;
+}
+
+message GrpcBescheid {
+	string beschiedenAm = 1;
+	bool bewilligt = 2;
+	string bescheidDocument = 3;
+	repeated string attachments = 4;
+	string sendBy = 5;
+	string nachrichtText = 6;
+	string nachrichtSubject = 7;
+}
\ No newline at end of file
diff --git a/vorgang-manager-interface/src/main/protobuf/bescheid.proto b/vorgang-manager-interface/src/main/protobuf/bescheid.proto
new file mode 100644
index 0000000000000000000000000000000000000000..9e6bb91b36c2c0257190cc98fcede20a2b8c6393
--- /dev/null
+++ b/vorgang-manager-interface/src/main/protobuf/bescheid.proto
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+ syntax = "proto3";
+
+ package de.ozgcloud.bescheid;
+
+ import "bescheid.model.proto";
+
+ option java_multiple_files = true;
+ option java_package = "de.ozgcloud.bescheid";
+ option java_outer_classname = "BescheidProto";
+
+ service BescheidService {
+ 	rpc getBescheidDraft(GrpcGetBescheidDraftRequest) returns (GrpcGetBescheidDraftResponse) {
+ 	}
+ }
\ No newline at end of file
diff --git a/pluto-interface/src/main/protobuf/binaryfile.proto b/vorgang-manager-interface/src/main/protobuf/binaryfile.proto
similarity index 81%
rename from pluto-interface/src/main/protobuf/binaryfile.proto
rename to vorgang-manager-interface/src/main/protobuf/binaryfile.proto
index 651bb186aee438b277acf1d1f663e57ba6d217cb..c4233ee254240504b738da24270db5421802de3a 100644
--- a/pluto-interface/src/main/protobuf/binaryfile.proto
+++ b/vorgang-manager-interface/src/main/protobuf/binaryfile.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,13 +23,13 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.grpc.binaryFile;
+package de.ozgcloud.vorgang.grpc.binaryFile;
 
 import "callcontext.proto";
 import "filemodel.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.grpc.binaryFile";
+option java_package = "de.ozgcloud.vorgang.grpc.binaryFile";
 option java_outer_classname = "BinaryFileProto";
 
 service BinaryFileService {
@@ -41,7 +41,6 @@ service BinaryFileService {
 	}
 	
 	rpc FindBinaryFilesMetaData(GrpcBinaryFilesRequest) returns (GrpcFindFilesResponse) {
-		
 	}
 	
 	rpc GetAttachments(GrpcGetAttachmentsRequest) returns (GrpcGetAttachmentsResponse) {
@@ -52,16 +51,16 @@ service BinaryFileService {
 }
 
 message GrpcBinaryFilesRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	repeated string fileId = 2;
 }
 
 message GrpcFindFilesResponse {
-	repeated de.itvsh.ozg.pluto.grpc.file.GrpcOzgFile file = 1;
+	repeated de.ozgcloud.vorgang.grpc.file.GrpcOzgFile file = 1;
 }
 
 message GrpcBinaryFileDataRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string fileId = 2;
 }
 
@@ -73,7 +72,7 @@ message GrpcUploadBinaryFileRequest {
 }
 
 message GrpcUploadBinaryFileMetaData {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string vorgangId = 2;
 	string field = 3;
 	string fileName = 4;
@@ -86,7 +85,7 @@ message GrpcUploadBinaryFileResponse {
 }
 
 message GrpcGetBinaryFileDataRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string fileId = 2;
 }
 
@@ -95,7 +94,7 @@ message GrpcGetBinaryFileDataResponse {
 }
 
 message GrpcGetAttachmentsRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string eingangId = 2;
 }
 message GrpcGetAttachmentsResponse {
@@ -103,7 +102,7 @@ message GrpcGetAttachmentsResponse {
 }
 
 message GrpcGetRepresentationsRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string eingangId = 2;
 }
 message GrpcGetRepresentationsResponse {
diff --git a/pluto-interface/src/main/protobuf/callcontext.proto b/vorgang-manager-interface/src/main/protobuf/callcontext.proto
similarity index 87%
rename from pluto-interface/src/main/protobuf/callcontext.proto
rename to vorgang-manager-interface/src/main/protobuf/callcontext.proto
index 51813508507b955d20a6880391f98c705c864de5..234931d391a98f48c6912ce162c0a22c950733ee 100644
--- a/pluto-interface/src/main/protobuf/callcontext.proto
+++ b/vorgang-manager-interface/src/main/protobuf/callcontext.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,10 +23,10 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.grpc.command;
+package de.ozgcloud.vorgang.grpc.command;
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.grpc.command";
+option java_package = "de.ozgcloud.vorgang.grpc.command";
 option java_outer_classname = "SharedCommandProto";
 
 message GrpcCallContext {
diff --git a/pluto-interface/src/main/protobuf/clientattribute.model.proto b/vorgang-manager-interface/src/main/protobuf/clientattribute.model.proto
similarity index 88%
rename from pluto-interface/src/main/protobuf/clientattribute.model.proto
rename to vorgang-manager-interface/src/main/protobuf/clientattribute.model.proto
index 53cd27ae878fa671f7f948433b572e198533e19c..89f6087d967dfc78c9378c5265552ea1b76eaacd 100644
--- a/pluto-interface/src/main/protobuf/clientattribute.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/clientattribute.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,10 +23,10 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.grpc.clientAttribute;
+package de.ozgcloud.vorgang.grpc.clientAttribute;
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.grpc.clientAttribute";
+option java_package = "de.ozgcloud.vorgang.grpc.clientAttribute";
 
 message GrpcClientAttribute {
 	string clientName = 1;
diff --git a/pluto-interface/src/main/protobuf/clientattribute.proto b/vorgang-manager-interface/src/main/protobuf/clientattribute.proto
similarity index 90%
rename from pluto-interface/src/main/protobuf/clientattribute.proto
rename to vorgang-manager-interface/src/main/protobuf/clientattribute.proto
index c9189f6ea2f2d2d7cd87e31efc59c8049ec997fd..d717d83cfb652f3615d68d7457cadaadcae3d461 100644
--- a/pluto-interface/src/main/protobuf/clientattribute.proto
+++ b/vorgang-manager-interface/src/main/protobuf/clientattribute.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,12 +23,12 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.grpc.clientAttribute;
+package de.ozgcloud.vorgang.grpc.clientAttribute;
 
 import "clientattribute.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.grpc.clientAttribute";
+option java_package = "de.ozgcloud.vorgang.grpc.clientAttribute";
 
 service ClientAttributeService {
 	rpc Set (GrpcSetClientAttributeRequest) returns (GrpcAcknowledgeResponse) {
diff --git a/pluto-interface/src/main/protobuf/command.model.proto b/vorgang-manager-interface/src/main/protobuf/command.model.proto
similarity index 79%
rename from pluto-interface/src/main/protobuf/command.model.proto
rename to vorgang-manager-interface/src/main/protobuf/command.model.proto
index 570ae43b217e4ee665923c02b0e64c4f364e82ec..4bbd54bc374d2b63590ffaab01524760faa9c4ad 100644
--- a/pluto-interface/src/main/protobuf/command.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/command.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,13 +23,13 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.grpc.command;
+package de.ozgcloud.vorgang.grpc.command;
 
 import "callcontext.proto";
 import "common.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.grpc.command";
+option java_package = "de.ozgcloud.vorgang.grpc.command";
 option java_outer_classname = "CommandModelProto";
 
 
@@ -66,14 +66,14 @@ enum GrpcOrder {
 }
 
 message GrpcCreateCommandRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext callContext = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext callContext = 1;
 	string vorgangId = 2;
 	GrpcOrder order = 3;
 	string relationId = 4;
 	int64 relationVersion = 5;
 	GrpcRedirectRequest redirectRequest = 12;
 	repeated GrpcCommandBodyField body = 15;
-	de.itvsh.ozg.pluto.common.GrpcObject bodyObj = 17;
+	de.ozgcloud.vorgang.common.GrpcObject bodyObj = 17;
 	string orderString = 21;
 }
 
@@ -91,15 +91,20 @@ message GrpcCommandResponse {
 }
 
 message GrpcRevokeCommandRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string id = 2;
 }
 
 message GrpcGetCommandRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string id = 2;
 }
 
+message GrpcSetCommandExecutedRequest {
+	string commandId = 1;
+	string createdResource = 2;
+}
+
 message GrpcCommand {
 	string id = 1;
 	string vorgangId = 2;
@@ -112,13 +117,14 @@ message GrpcCommand {
 	string relationId = 14;
 	GrpcOrder order = 15 [deprecated=true];
 	GrpcCommandBody body = 16;
-	de.itvsh.ozg.pluto.common.GrpcObject bodyObj = 17;
+	de.ozgcloud.vorgang.common.GrpcObject bodyObj = 17;
 	GrpcRedirectRequest redirectRequest = 20;
 	string orderString = 21;
+	string createdResource = 22;
 }
 
 message GrpcExistsPendingCommandsRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string vorgangId = 2;
 }
 
@@ -127,19 +133,19 @@ message GrpcExistsPendingCommandsResponse {
 }
 
 message GrpcRedirectRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string email = 2;
 	string password = 3;
 }
 
 
 message GrpcGetPendingCommandsRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string vorgangId = 2;
 }
 
 message GrpcFindCommandsRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string vorgangId = 2;
 	repeated string status = 3;
 	GrpcOrder order = 4;
@@ -160,4 +166,8 @@ message GrpcCommandBody {
 message GrpcCommandBodyField {
 	string name = 1;
 	string value = 2;
+}
+
+message GrpcEmpty {
+
 }
\ No newline at end of file
diff --git a/pluto-interface/src/main/protobuf/command.proto b/vorgang-manager-interface/src/main/protobuf/command.proto
similarity index 86%
rename from pluto-interface/src/main/protobuf/command.proto
rename to vorgang-manager-interface/src/main/protobuf/command.proto
index 341e8072d22a123c8c4e9498147a477bfb8d36db..019ee5b6933c5515e20067d80464354f582cbb9f 100644
--- a/pluto-interface/src/main/protobuf/command.proto
+++ b/vorgang-manager-interface/src/main/protobuf/command.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,12 +23,12 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.grpc.command;
+package de.ozgcloud.vorgang.grpc.command;
 
 import "command.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.grpc.command";
+option java_package = "de.ozgcloud.vorgang.grpc.command";
 option java_outer_classname = "CommandProto";
 
 service CommandService {
@@ -50,4 +50,8 @@ service CommandService {
 	
 	rpc FindCommands(GrpcFindCommandsRequest) returns (GrpcCommandsResponse) {
 	}
+
+	rpc SetCommandExecuted(GrpcSetCommandExecutedRequest) returns (GrpcEmpty) {
+
+	}
 }
\ No newline at end of file
diff --git a/pluto-interface/src/main/protobuf/common.model.proto b/vorgang-manager-interface/src/main/protobuf/common.model.proto
similarity index 76%
rename from pluto-interface/src/main/protobuf/common.model.proto
rename to vorgang-manager-interface/src/main/protobuf/common.model.proto
index e1db8f9d4cab8c038370d00830ad2601cc628cf5..e4b876f62d25d00402482c629d9ed792cf00f1f7 100644
--- a/pluto-interface/src/main/protobuf/common.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/common.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,10 +23,10 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.common;
+package de.ozgcloud.vorgang.common;
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.common";
+option java_package = "de.ozgcloud.vorgang.common";
 option java_outer_classname = "CommonModelProto";
 
 message GrpcObject {
@@ -43,4 +43,17 @@ message GrpcSubObject {
 	string name = 1;
 	repeated GrpcProperty property = 2;
 	repeated GrpcSubObject subObject = 3;
+}
+
+enum GrpcQueryOperator {
+	GREATER_THEN = 0;	// >
+	GREATER_THEN_OR_EQUAL_TO = 1; // >=
+	LESS_THEN = 2; // <
+	LESS_THEN_OR_EQUAL_TO = 3; // <=
+	EQUAL = 4; // =
+	UNEQUAL = 5; // <>
+	IS_NULL = 6;
+	IS_EMPTY = 7;
+	EXISTS = 8;
+	NOT_EXIST = 9;
 }
\ No newline at end of file
diff --git a/pluto-interface/src/main/protobuf/email.model.proto b/vorgang-manager-interface/src/main/protobuf/email.model.proto
similarity index 88%
rename from pluto-interface/src/main/protobuf/email.model.proto
rename to vorgang-manager-interface/src/main/protobuf/email.model.proto
index 5e5789494ce7f11601b82bd21cd33cb778b5d301..53a0075bedfdf9a5f58017c34ebb3f5da2c2b55d 100644
--- a/pluto-interface/src/main/protobuf/email.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/email.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,10 +23,10 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.mail.email";
+option java_package = "de.ozgcloud.nachrichten.email";
 option java_outer_classname = "EmailModelProto";
 
 message GrpcRecipient {
diff --git a/pluto-interface/src/main/protobuf/email.proto b/vorgang-manager-interface/src/main/protobuf/email.proto
similarity index 87%
rename from pluto-interface/src/main/protobuf/email.proto
rename to vorgang-manager-interface/src/main/protobuf/email.proto
index 59bec8eef3273c8ca071db976de717e48b7b8bb5..64fd405f4937b7ccc06a645eb1b20e908a546593 100644
--- a/pluto-interface/src/main/protobuf/email.proto
+++ b/vorgang-manager-interface/src/main/protobuf/email.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,12 +23,12 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.mail.email;
+package de.ozgcloud.nachrichten.email;
 
 import "email.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.mail.email";
+option java_package = "de.ozgcloud.nachrichten.email";
 option java_outer_classname = "EmailProto";
 
 
diff --git a/pluto-interface/src/main/protobuf/file.proto b/vorgang-manager-interface/src/main/protobuf/file.proto
similarity index 88%
rename from pluto-interface/src/main/protobuf/file.proto
rename to vorgang-manager-interface/src/main/protobuf/file.proto
index 25f826d27f91ae84716bc4481b84ecee5fd44bc0..a3061b2ca3661910dd7e47c589b6ae0f4235a5c8 100644
--- a/pluto-interface/src/main/protobuf/file.proto
+++ b/vorgang-manager-interface/src/main/protobuf/file.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,12 +23,12 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.grpc.file;
+package de.ozgcloud.vorgang.grpc.file;
 
 import "filemodel.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.grpc.file";
+option java_package = "de.ozgcloud.vorgang.grpc.file";
 option java_outer_classname = "FileProto";
 option deprecated = true;
 
diff --git a/pluto-interface/src/main/protobuf/filemodel.proto b/vorgang-manager-interface/src/main/protobuf/filemodel.proto
similarity index 86%
rename from pluto-interface/src/main/protobuf/filemodel.proto
rename to vorgang-manager-interface/src/main/protobuf/filemodel.proto
index f8785dce4879b07693f63b2d814f51dca8f8248f..49cbc59a2f83cf15bf9b28625591d6f7fbd90f17 100644
--- a/pluto-interface/src/main/protobuf/filemodel.proto
+++ b/vorgang-manager-interface/src/main/protobuf/filemodel.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,7 +23,7 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.grpc.file;
+package de.ozgcloud.vorgang.grpc.file;
 
 import "callcontext.proto";
 
@@ -32,7 +32,7 @@ option java_outer_classname = "FileModelProto";
 option deprecated = true;
 
 message GrpcGetAttachmentsRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string eingangId = 2;
 }
 message GrpcGetAttachmentsResponse {
@@ -40,7 +40,7 @@ message GrpcGetAttachmentsResponse {
 }
 
 message GrpcGetRepresentationsRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string eingangId = 2;
 }
 message GrpcGetRepresentationsResponse {
diff --git a/pluto-interface/src/main/protobuf/forwarding.model.proto b/vorgang-manager-interface/src/main/protobuf/forwarding.model.proto
similarity index 89%
rename from pluto-interface/src/main/protobuf/forwarding.model.proto
rename to vorgang-manager-interface/src/main/protobuf/forwarding.model.proto
index 7683959848a4e19384056697727b6e5fbfd5ddc1..2e9817322415526b1e2db0a6bdec203bc48a8698 100644
--- a/pluto-interface/src/main/protobuf/forwarding.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/forwarding.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,10 +23,10 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.forwarding;
+package de.ozgcloud.vorgang.forwarding;
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.forwarding";
+option java_package = "de.ozgcloud.vorgang.forwarding";
 option java_outer_classname = "ForwardingModelProto";
 
 enum GrpcForwardingStatus {
diff --git a/pluto-interface/src/main/protobuf/forwarding.proto b/vorgang-manager-interface/src/main/protobuf/forwarding.proto
similarity index 85%
rename from pluto-interface/src/main/protobuf/forwarding.proto
rename to vorgang-manager-interface/src/main/protobuf/forwarding.proto
index 41ab1aa56d3a127d327d8db83c4208772f291f5a..840119d031033c9d48153dd46c9c613a43c82048 100644
--- a/pluto-interface/src/main/protobuf/forwarding.proto
+++ b/vorgang-manager-interface/src/main/protobuf/forwarding.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,13 +23,13 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.forwarding;
+package de.ozgcloud.vorgang.forwarding;
 
 import "callcontext.proto";
 import "forwarding.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.forwarding";
+option java_package = "de.ozgcloud.vorgang.forwarding";
 option java_outer_classname = "ForwardingProto";
 
 
@@ -39,7 +39,7 @@ service ForwardingService {
 }
 
 message GrpcFindForwardingsRequest { 
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string vorgangId = 2;
 }
 
diff --git a/pluto-interface/src/main/protobuf/postfach.model.proto b/vorgang-manager-interface/src/main/protobuf/postfach.model.proto
similarity index 59%
rename from pluto-interface/src/main/protobuf/postfach.model.proto
rename to vorgang-manager-interface/src/main/protobuf/postfach.model.proto
index 79023e75110bdc195a3ccbbca1ff2cd8ebd92888..20b7b677f02de55d0ba6528ef49f5fff01cb62b4 100644
--- a/pluto-interface/src/main/protobuf/postfach.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/postfach.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,33 +23,44 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import "callcontext.proto";
+import "vorgang.model.proto";
+import "common.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.mail.postfach";
+option java_package = "de.ozgcloud.nachrichten.postfach";
 option java_outer_classname = "PostfachMailModelProto";
 
 message GrpcSendPostfachMailRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string commandId = 2;
 	GrpcPostfachMail mail = 5;
 }
 
+message GrpcSaveNachrichtDraftRequest {
+	string vorgangId = 1;
+	GrpcPostfachNachricht nachricht = 2;
+}
+
+message GrpcSaveNachrichtDraftResponse {
+}
+
 message GrpcSendPostfachMailResponse {
 }
 
 message GrpcFindPostfachMailRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string nachrichtId = 2;
 }
+
 message GrpcFindPostfachMailResponse {
 	GrpcPostfachMail nachricht = 1;
 }
 
 message GrpcFindPostfachMailsRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string vorgangId = 2;
 }
 
@@ -63,10 +74,21 @@ enum GrpcDirection {
 	OUT = 2;
 }
 
+message GrpcPostfachNachricht {
+	string id = 1;
+	string createdAt = 2;
+	de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress postfachAddress = 3;
+	string subject = 4;
+	string mailBody = 5;
+	string replyOption = 6;
+	repeated string attachment = 7;
+}
+
 message GrpcPostfachMail {
 	string id = 1;
 	string vorgangId = 2;
-	string postfachId = 3;
+	string postfachId = 3 [deprecated = true];
+	GrpcPostfachAddress postfachAddress = 14;
 	string createdAt = 4;
 	string createdBy = 5;
 	string sentAt = 6;
@@ -77,10 +99,18 @@ message GrpcPostfachMail {
 	string mailBody = 11;
 	string replyOption = 12;
 	repeated string attachment = 13;
+	GrpcPostfachAddress address = 15;
+}
+
+message GrpcPostfachAddress {
+	string version = 1;
+	de.ozgcloud.vorgang.common.GrpcObject identifier = 2;
+	int32 type = 3;
+	string serviceKontoType = 4;
 }
 
 message GrpcResendPostfachMailRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 	string commandId = 2;
 	string postfachMailId = 3;
 }
@@ -89,9 +119,22 @@ message GrpcResendPostfachMailResponse {
 }
 
 message GrpcIsPostfachConfiguredRequest {
-	de.itvsh.ozg.pluto.grpc.command.GrpcCallContext context = 1;
+	de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
 }
 
 message GrpcIsPostfachConfiguredResponse {
 	bool isConfigured = 1;
+}
+
+message GrpcGetPostfachConfigRequest {
+}
+
+message GrpcGetPostfachConfigResponse {
+	bool configured = 1;
+	repeated GrpcPostfach postfach = 2;
+}
+
+message GrpcPostfach {
+	string type = 1;
+	bool replyAllowed = 2;
 }
\ No newline at end of file
diff --git a/pluto-interface/src/main/protobuf/postfach.proto b/vorgang-manager-interface/src/main/protobuf/postfach.proto
similarity index 78%
rename from pluto-interface/src/main/protobuf/postfach.proto
rename to vorgang-manager-interface/src/main/protobuf/postfach.proto
index d72455549931bbed3da7bed15dce6ea1ff91cd08..702bc34c5ed1a8cc6caf91e086299e088d81b0e9 100644
--- a/pluto-interface/src/main/protobuf/postfach.proto
+++ b/vorgang-manager-interface/src/main/protobuf/postfach.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,15 +23,18 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import "postfach.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.mail.postfach";
+option java_package = "de.ozgcloud.nachrichten.postfach";
 option java_outer_classname = "MailProto";
 
 service PostfachService {
+	rpc SaveNachrichtDraft(GrpcSaveNachrichtDraftRequest) returns (GrpcSaveNachrichtDraftResponse) {
+	}
+
 	rpc SendPostfachMail(GrpcSendPostfachMailRequest) returns (GrpcSendPostfachMailResponse) {
 	}
 	
@@ -44,6 +47,10 @@ service PostfachService {
 	rpc ResendPostfachMail(GrpcResendPostfachMailRequest) returns (GrpcResendPostfachMailResponse) {
 	}
 	
-	rpc IsPostfachConfigured(GrpcIsPostfachConfiguredRequest) returns (GrpcIsPostfachConfiguredResponse){
+	rpc IsPostfachConfigured(GrpcIsPostfachConfiguredRequest) returns (GrpcIsPostfachConfiguredResponse) {
+	}
+
+	rpc GetPostfachConfig(GrpcGetPostfachConfigRequest) returns (GrpcGetPostfachConfigResponse) {
+
 	}
 }
\ No newline at end of file
diff --git a/pluto-interface/src/main/protobuf/route-forwarding.model.proto b/vorgang-manager-interface/src/main/protobuf/route-forwarding.model.proto
similarity index 82%
rename from pluto-interface/src/main/protobuf/route-forwarding.model.proto
rename to vorgang-manager-interface/src/main/protobuf/route-forwarding.model.proto
index a50887c82a6315cfe363dba89ed096d06145ca8a..82b4d5c38b07057734ce4bf181b4026e9c93edca 100644
--- a/pluto-interface/src/main/protobuf/route-forwarding.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/route-forwarding.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,18 +23,18 @@
  */
 syntax = "proto3";
 
-package de.itvsh.kop.eingangsadapter.forwarder;
+package de.ozgcloud.eingang.forwarder;
 
-import "vorgangmodel.proto";
+import "vorgang.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.kop.eingangsadapter.forwarding";
+option java_package = "de.ozgcloud.eingang.forwarding";
 option java_outer_classname = "RouteForwardingModelProto";
 
 
 message GrpcRouteForwardingRequest {
 	GrpcRouteCriteria routeCriteria = 1;
-	de.itvsh.ozg.pluto.vorgang.GrpcEingang eingang = 5; 
+	de.ozgcloud.vorgang.vorgang.GrpcEingang eingang = 5;
 }
 
 message GrpcRouteForwardingResponse {
diff --git a/pluto-interface/src/main/protobuf/route-forwarding.proto b/vorgang-manager-interface/src/main/protobuf/route-forwarding.proto
similarity index 87%
rename from pluto-interface/src/main/protobuf/route-forwarding.proto
rename to vorgang-manager-interface/src/main/protobuf/route-forwarding.proto
index 10c665669de2014ddd71d19b49e05a6b8eed6f1e..607c1a1cef49e4cc819caf260bd4f007e81f3139 100644
--- a/pluto-interface/src/main/protobuf/route-forwarding.proto
+++ b/vorgang-manager-interface/src/main/protobuf/route-forwarding.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,12 +23,12 @@
  */
 syntax = "proto3";
 
-package de.itvsh.kop.eingangsadapter.forwarder;
+package de.ozgcloud.eingang.forwarder;
 
 import "route-forwarding.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.kop.eingangsadapter.forwarder";
+option java_package = "de.ozgcloud.eingang.forwarder";
 option java_outer_classname = "RouteForwardingProto";
 
 service RouteForwardingService {
diff --git a/vorgang-manager-interface/src/main/protobuf/statistic.model.proto b/vorgang-manager-interface/src/main/protobuf/statistic.model.proto
new file mode 100644
index 0000000000000000000000000000000000000000..88d4542ea1290136634736231aa8f59d3a43f88f
--- /dev/null
+++ b/vorgang-manager-interface/src/main/protobuf/statistic.model.proto
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+syntax = "proto3";
+
+package de.ozgcloud.vorgang.statistic;
+
+import "common.model.proto";
+
+option java_multiple_files = true;
+option java_package = "de.ozgcloud.vorgang.statistic";
+option java_outer_classname = "StatisticModelProto";
+
+message GrpcVorgangCountRequest {
+  repeated string countByPath = 1;
+}
+
+message GrpcByStatusResult {
+  int32 neu = 1;
+  int32 angenommen = 2;
+  int32 verworfen = 3;
+  int32 in_bearbeitung = 4;
+  int32 beschieden = 5;
+  int32 abgeschlossen = 6;
+  int32 weitergeleitet = 7;
+
+}
+
+message GrpcPathCountResult {
+  string name = 1;
+  int32 value = 2;
+}
+
+message GrpcVorgangCountResponse {
+  GrpcByStatusResult byStatus = 1;
+  repeated GrpcPathCountResult pathCountResult = 2;
+}
+
+message GrpcVorgangStatisticRequest {
+	repeated GrpcVorgangStatisticQuery query = 1;
+}
+
+message GrpcVorgangStatisticQuery {
+	string resultName = 1;
+	GroupMethod groupMethod = 2;
+	string path = 3;
+  de.ozgcloud.vorgang.common.GrpcQueryOperator operator = 4;
+	oneof operand {
+		int32 operandIntValue = 5;
+		bool operandBoolValue = 6;
+		string operandStringValue = 7;
+	}
+
+	enum GroupMethod {
+		COUNT = 0;
+		EXISTS = 1;
+	}
+
+}
+
+message GrpcVorgangStatisticResponse {
+	repeated GrpcVorgangStatisticResult result = 1;
+}
+
+message GrpcVorgangStatisticResult {
+  string name = 1;
+  oneof result {
+    int32 resultIntValue = 2;
+    bool resultBoolValue = 3;
+    string resultStringValue = 4;
+  }
+}
\ No newline at end of file
diff --git a/vorgang-manager-interface/src/main/protobuf/statistic.proto b/vorgang-manager-interface/src/main/protobuf/statistic.proto
new file mode 100644
index 0000000000000000000000000000000000000000..6e2929e61dae524a5c9366048b189e3bc2cbf730
--- /dev/null
+++ b/vorgang-manager-interface/src/main/protobuf/statistic.proto
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+syntax = "proto3";
+
+package de.ozgcloud.vorgang.statistic;
+
+import "statistic.model.proto";
+
+option java_multiple_files = true;
+option java_package = "de.ozgcloud.vorgang.statistic";
+option java_outer_classname = "StatisticProto";
+
+service StatisticService {
+    rpc CountVorgang(GrpcVorgangCountRequest) returns (GrpcVorgangCountResponse);
+
+    rpc GetVorgangStatistic(GrpcVorgangStatisticRequest) returns (GrpcVorgangStatisticResponse);
+}
\ No newline at end of file
diff --git a/pluto-interface/src/main/protobuf/system.model.proto b/vorgang-manager-interface/src/main/protobuf/system.model.proto
similarity index 88%
rename from pluto-interface/src/main/protobuf/system.model.proto
rename to vorgang-manager-interface/src/main/protobuf/system.model.proto
index 8d5d05f431688eb94d48a4a7e21ce865a92e9d8a..61a77510a119e789557652f48149b25f4a3bec47 100644
--- a/pluto-interface/src/main/protobuf/system.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/system.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,10 +23,10 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.system;
+package de.ozgcloud.vorgang.system;
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.system";
+option java_package = "de.ozgcloud.vorgang.system";
 option java_outer_classname = "SystemStatusModelProto";
 
 message GrpcGetSystemStatusRequest {}
diff --git a/pluto-interface/src/main/protobuf/system.proto b/vorgang-manager-interface/src/main/protobuf/system.proto
similarity index 88%
rename from pluto-interface/src/main/protobuf/system.proto
rename to vorgang-manager-interface/src/main/protobuf/system.proto
index c7e853aefa6f162825ecc3b7f67e945d6c99ee1c..661313033d7dbeacfe967b52baed29edaa8c326b 100644
--- a/pluto-interface/src/main/protobuf/system.proto
+++ b/vorgang-manager-interface/src/main/protobuf/system.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,12 +23,12 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.system;
+package de.ozgcloud.vorgang.system;
 
 import "system.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.system";
+option java_package = "de.ozgcloud.vorgang.system";
 option java_outer_classname = "SystemStatusProto";
 
 service SystemStatusService {
diff --git a/vorgang-manager-interface/src/main/protobuf/vorgang.model.proto b/vorgang-manager-interface/src/main/protobuf/vorgang.model.proto
new file mode 100644
index 0000000000000000000000000000000000000000..8740ca7d29253a1523175c89af4b8c23bdea3ee2
--- /dev/null
+++ b/vorgang-manager-interface/src/main/protobuf/vorgang.model.proto
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+syntax = "proto3";
+
+package de.ozgcloud.vorgang.vorgang;
+
+import "clientattribute.model.proto";
+import "common.model.proto";
+
+option java_multiple_files = true;
+option java_package = "de.ozgcloud.vorgang.vorgang";
+option java_outer_classname = "VorgangModelProto";
+
+message GrpcVorgangHeader {
+  string id = 1;
+  int64 version = 2;
+  string status = 3;
+  string name = 4;
+  string createdAt = 5;
+  string aktenzeichen = 6;
+  string assignedTo = 7;
+  string nummer = 8;
+  repeated de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttribute clientAttributes = 9;
+  string formEngineName = 15;
+}
+
+message GrpcVorgangWithEingang {
+  string id = 1;
+  int64 version = 2;
+  string status = 3;
+  string name = 4;
+  string createdAt = 5;
+  string aktenzeichen = 6;
+  string assignedTo = 7;
+  string nummer = 8;
+  repeated de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttribute clientAttributes = 9;
+
+  GrpcEingang eingang = 10;
+  string formEngineName = 15;
+  GrpcVorgangHead header = 16;
+}
+
+message GrpcVorgangHead {
+  GrpcServiceKonto serviceKonto = 1;
+}
+
+message GrpcEingang {
+  string id = 1;
+
+  GrpcEingangHeader header = 2;
+  GrpcAntragsteller antragsteller = 3;
+  GrpcZustaendigeStelle zustaendigeStelle = 4;
+
+  GrpcFormData formData = 10;
+
+  int32 numberOfAttachments = 11;
+  int32 numberOfRepresentations = 12;
+
+  repeated GrpcIncomingFileGroup attachments = 20;
+  repeated GrpcIncomingFile representations = 21;
+}
+
+message GrpcIncomingFileGroup {
+  string name = 1;
+  repeated GrpcIncomingFile files = 2;
+}
+
+message GrpcIncomingFile {
+  string id = 1;
+  string vendorId = 2;
+  string name = 3;
+  string contentType = 4;
+  int64 size = 5;
+  bytes content = 6;
+}
+
+message GrpcEingangHeader {
+  string requestId = 1;
+  string createdAt = 2;
+  string formId = 3;
+  string formName = 4;
+  string sender = 5;
+  string customer = 6 [deprecated = true];
+  string customerId = 7 [deprecated = true];
+  string client = 8 [deprecated = true];
+  string clientId = 9 [deprecated = true];
+  string formEngineName = 10;
+  GrpcServiceKonto serviceKonto = 11;
+  string vorgangNummer = 12;
+}
+
+message GrpcServiceKonto {
+  string type = 1;
+  repeated GrpcPostfachAddress postfachAddresses = 2;
+}
+
+message GrpcPostfachAddress {
+  string version = 1;
+  de.ozgcloud.vorgang.common.GrpcObject identifier = 2;
+  int32 type = 3;
+}
+
+message GrpcAntragsteller {
+  string anrede = 1;
+  string nachname = 2;
+  string vorname = 3;
+  string geburtsdatum = 4;
+  string geburtsort = 5;
+  string geburtsname = 6;
+  string email = 7;
+  string telefon = 8;
+  string strasse = 9;
+  string hausnummer = 10;
+  string plz = 11;
+  string ort = 12;
+  string postfachId = 13 [deprecated = true];
+
+  GrpcFormData otherData = 30;
+}
+
+message GrpcFormData {
+  repeated GrpcFormField field = 1;
+  repeated GrpcSubForm form = 2;
+}
+
+message GrpcFormField {
+  string name = 1;
+  string value = 2;
+  string label = 3;
+}
+
+message GrpcSubForm {
+  string title = 1;
+  repeated GrpcFormField field = 2;
+  repeated GrpcSubForm subForm = 3;
+  string label = 4;
+  GrpcControlData controlData = 5;
+}
+
+message GrpcControlData {
+  bool metadata = 1;
+}
+
+message GrpcZustaendigeStelle {
+  string organisationseinheitenId = 1;
+  string email = 2;
+  string bezeichnung = 3;
+  string gemeindeSchluessel = 4;
+  string amtlicherRegionalSchluessel = 5;
+  string hausanschriftStrasse = 6;
+  string hausanschriftPlz = 7;
+  string hausanschriftOrt = 8;
+  string telefon = 9;
+}
+
+message GrpcQuery {
+  GrpcLogicalOperator logicalOperator = 1;
+  repeated GrpcVorgangQueryExpression expressions = 2;
+  GrpcQuery nestedQuery = 3;
+}
+
+enum GrpcLogicalOperator {
+  AND = 0;
+  OR = 1;
+}
+
+message GrpcVorgangQueryExpression {
+  string path = 1;
+  de.ozgcloud.vorgang.common.GrpcQueryOperator operator = 2;
+  oneof operand {
+    int32 operandIntValue = 3;
+    bool operandBoolValue = 4;
+    string operandStringValue = 5;
+  }
+}
+
diff --git a/pluto-interface/src/main/protobuf/vorgang.proto b/vorgang-manager-interface/src/main/protobuf/vorgang.proto
similarity index 86%
rename from pluto-interface/src/main/protobuf/vorgang.proto
rename to vorgang-manager-interface/src/main/protobuf/vorgang.proto
index 5fecca8afaeb16bb6ca9115d2e28526c0ff0a0b7..e5770ca7d5c414492b35e9b122e7dd845e996e43 100644
--- a/pluto-interface/src/main/protobuf/vorgang.proto
+++ b/vorgang-manager-interface/src/main/protobuf/vorgang.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,19 +23,16 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import "vorgangmodel.proto";
+import "vorgang.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.vorgang";
+option java_package = "de.ozgcloud.vorgang.vorgang";
 option java_outer_classname = "VorgangProto";
 
 service VorgangService {
 
-	rpc CreateVorgang(GrpcCreateVorgangRequest) returns (GrpcCreateVorgangResponse) {
-	}
-	
 	rpc FindVorgang(GrpcFindVorgangRequest) returns (GrpcFindVorgangResponse) {
 	}
 	
@@ -61,13 +58,18 @@ message GrpcCreateVorgangResponse {
 message GrpcFindVorgangRequest {
 	int32 offset = 1;
 	int32 limit = 2;
-	string searchBy = 3;
+	oneof request {
+		string searchBy = 3;
+		GrpcQuery query = 6;
+	}
 	GrpcFilterBy filterBy = 4;
 	GrpcOrderBy orderBy = 5;
 	
 	enum GrpcOrderBy {
 		PRIORITY = 0;
 		EA_PRIORITY = 1;
+		CREATED_AT_DESC = 2;
+		NEXT_WIEDERVORLAGE_FRIST = 3;
 	}
 }
 
@@ -86,6 +88,8 @@ message GrpcFilterBy {
 	repeated string organisationseinheitId = 2;
 	repeated string status = 3;
 	string assignedTo = 4;
+	bool filterByAssignedTo = 5;
+	bool hasNextWiedervorlageFrist = 6 [deprecated = true];
 }
 
 message GrpcFindVorgangWithEingangResponse {
diff --git a/pluto-interface/src/main/protobuf/vorgangattacheditem.model.proto b/vorgang-manager-interface/src/main/protobuf/vorgangattacheditem.model.proto
similarity index 83%
rename from pluto-interface/src/main/protobuf/vorgangattacheditem.model.proto
rename to vorgang-manager-interface/src/main/protobuf/vorgangattacheditem.model.proto
index 359174f09b50dd7da26f5eceb3b11d009f4230d8..f87b4bd182911f15bc638f086246b35f9a4a37cd 100644
--- a/pluto-interface/src/main/protobuf/vorgangattacheditem.model.proto
+++ b/vorgang-manager-interface/src/main/protobuf/vorgangattacheditem.model.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,12 +23,12 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.vorgangAttachedItem;
+package de.ozgcloud.vorgang.vorgangAttachedItem;
 
 import "common.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.vorgangAttachedItem";
+option java_package = "de.ozgcloud.vorgang.vorgangAttachedItem";
 option java_outer_classname = "VorgangAttachedItemModelProto";
 
 message GrpcVorgangAttachedItem {
@@ -37,5 +37,5 @@ message GrpcVorgangAttachedItem {
 	string client = 3;
 	string vorgangId = 4;
 	string itemName = 5;
-	de.itvsh.ozg.pluto.common.GrpcObject item = 6;
+	de.ozgcloud.vorgang.common.GrpcObject item = 6;
 }
\ No newline at end of file
diff --git a/pluto-interface/src/main/protobuf/vorgangattacheditem.proto b/vorgang-manager-interface/src/main/protobuf/vorgangattacheditem.proto
similarity index 90%
rename from pluto-interface/src/main/protobuf/vorgangattacheditem.proto
rename to vorgang-manager-interface/src/main/protobuf/vorgangattacheditem.proto
index 3385e18a78f782faafb4b1cf8df5add7efb83868..55354ab9669cc8f1b016401e4dc89cf88c1d76de 100644
--- a/pluto-interface/src/main/protobuf/vorgangattacheditem.proto
+++ b/vorgang-manager-interface/src/main/protobuf/vorgangattacheditem.proto
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -23,12 +23,12 @@
  */
 syntax = "proto3";
 
-package de.itvsh.ozg.pluto.vorgangAttachedItem;
+package de.ozgcloud.vorgang.vorgangAttachedItem;
 
 import "vorgangattacheditem.model.proto";
 
 option java_multiple_files = true;
-option java_package = "de.itvsh.ozg.pluto.vorgangAttachedItem";
+option java_package = "de.ozgcloud.vorgang.vorgangAttachedItem";
 option java_outer_classname = "VorgangAttachedItemProto";
 
 service VorgangAttachedItemService {
diff --git a/pluto-server/.mvn/wrapper/MavenWrapperDownloader.java b/vorgang-manager-server/.mvn/wrapper/MavenWrapperDownloader.java
similarity index 100%
rename from pluto-server/.mvn/wrapper/MavenWrapperDownloader.java
rename to vorgang-manager-server/.mvn/wrapper/MavenWrapperDownloader.java
diff --git a/pluto-server/.mvn/wrapper/maven-wrapper.jar b/vorgang-manager-server/.mvn/wrapper/maven-wrapper.jar
similarity index 100%
rename from pluto-server/.mvn/wrapper/maven-wrapper.jar
rename to vorgang-manager-server/.mvn/wrapper/maven-wrapper.jar
diff --git a/pluto-server/.mvn/wrapper/maven-wrapper.properties b/vorgang-manager-server/.mvn/wrapper/maven-wrapper.properties
similarity index 100%
rename from pluto-server/.mvn/wrapper/maven-wrapper.properties
rename to vorgang-manager-server/.mvn/wrapper/maven-wrapper.properties
diff --git a/vorgang-manager-server/lombok.config b/vorgang-manager-server/lombok.config
new file mode 100644
index 0000000000000000000000000000000000000000..81661f0fd9c5f6e2f40f39aa9ee13f7017fc2726
--- /dev/null
+++ b/vorgang-manager-server/lombok.config
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+lombok.log.fieldName=LOG
+lombok.log.slf4j.flagUsage = ERROR
+lombok.log.log4j.flagUsage = ERROR
+lombok.data.flagUsage = ERROR
+lombok.nonNull.exceptionType = IllegalArgumentException
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
diff --git a/pluto-server/mvnw b/vorgang-manager-server/mvnw
similarity index 100%
rename from pluto-server/mvnw
rename to vorgang-manager-server/mvnw
diff --git a/pluto-server/mvnw.cmd b/vorgang-manager-server/mvnw.cmd
similarity index 100%
rename from pluto-server/mvnw.cmd
rename to vorgang-manager-server/mvnw.cmd
diff --git a/pluto-server/pom.xml b/vorgang-manager-server/pom.xml
similarity index 56%
rename from pluto-server/pom.xml
rename to vorgang-manager-server/pom.xml
index 55ddeba824a5fb2f0e6eba9eca5c1907e586399d..c11f8387ed6ec6071d89251ddb9ee11b45c3b631 100644
--- a/pluto-server/pom.xml
+++ b/vorgang-manager-server/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -24,72 +24,131 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 
 	<parent>
-		<groupId>de.itvsh.kop.common</groupId>
-		<artifactId>kop-common-parent</artifactId>
-		<version>1.2.1</version>
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-parent</artifactId>
+		<version>3.0.1</version>
 		<relativePath />
 	</parent>
 
-	<groupId>de.itvsh.ozg.pluto</groupId>
-	<artifactId>pluto-server</artifactId>
-	<version>1.0.0</version>
+	<groupId>de.ozgcloud.vorgang</groupId>
+	<artifactId>vorgang-manager-server</artifactId>
+	<version>2.4.0</version>
 
-	<name>Pluto Server</name>
-	<description>Server Implementierung des VorgangManagers (Pluto)</description>
+	<name>OZG-Cloud Vorgang Manager Server</name>
+	<description>Server Implementierung des VorgangManagers</description>
 
 	<properties>
 		<java.version>17</java.version>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
-		<spring-boot.build-image.imageName>docker.ozg-sh.de/pluto:build-latest</spring-boot.build-image.imageName>
+		<spring-boot.build-image.imageName>docker.ozg-sh.de/vorgang-manager:build-latest</spring-boot.build-image.imageName>
 
-		<zip.version>2.11.1</zip.version>
-		<jsoup.version>1.15.3</jsoup.version>
+		<ozgcloud.license.version>1.6.0</ozgcloud.license.version>
+		<zufi-manager-interface.version>1.0.0-SNAPSHOT</zufi-manager-interface.version>
 
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<mongock.version>5.1.4</mongock.version>
+		<user-manager-interface.version>2.1.0</user-manager-interface.version>
+		<bescheid-manager.version>1.8.0</bescheid-manager.version>
+		<processor-manager.version>0.3.0</processor-manager.version>
+		<ozgcloud-starter.version>0.5.0</ozgcloud-starter.version>
 
+		<zip.version>2.11.1</zip.version>
+		<jsoup.version>1.15.3</jsoup.version>
+		<mongock.version>5.3.4</mongock.version>
 		<testcontainer.version>1.17.3</testcontainer.version>
+
 		<maven-deploy-plugin.version>3.0.0</maven-deploy-plugin.version>
+		<find-and-replace-maven-plugin.version>1.1.0</find-and-replace-maven-plugin.version>
+		<docker-java.version>3.3.3</docker-java.version>
+
 	</properties>
 
 	<dependencies>
 		<!-- own Project -->
 		<dependency>
-			<groupId>de.itvsh.ozg.mail</groupId>
-			<artifactId>mail-service</artifactId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-base</artifactId>
 			<version>${project.version}</version>
 		</dependency>
+
 		<dependency>
-			<groupId>de.itvsh.ozg.pluto</groupId>
-			<artifactId>pluto-interface</artifactId>
+			<groupId>de.ozgcloud.nachrichten</groupId>
+			<artifactId>nachrichten-manager</artifactId>
 			<version>${project.version}</version>
 		</dependency>
+
 		<dependency>
-			<groupId>de.itvsh.ozg.pluto</groupId>
-			<artifactId>pluto-utils</artifactId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-interface</artifactId>
 			<version>${project.version}</version>
 		</dependency>
 
 		<dependency>
-			<groupId>de.itvsh.kop.notification</groupId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-utils</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>de.ozgcloud.command</groupId>
+			<artifactId>command-manager</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>de.ozgcloud.notification</groupId>
 			<artifactId>notification-manager</artifactId>
 			<version>${project.version}</version>
 			<scope>runtime</scope>
 		</dependency>
 
+		<dependency>
+			<groupId>de.ozgcloud.bescheid</groupId>
+			<artifactId>bescheid-manager</artifactId>
+			<version>${bescheid-manager.version}</version>
+			<scope>runtime</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>de.ozgcloud.zufi</groupId>
+			<artifactId>zufi-manager-interface</artifactId>
+			<version>${zufi-manager-interface.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>de.ozgcloud.processor</groupId>
+			<artifactId>processor-manager</artifactId>
+			<version>${processor-manager.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>de.ozgcloud.user</groupId>
+			<artifactId>user-manager-interface</artifactId>
+			<version>${user-manager-interface.version}</version>
+			<!-- TODO Nur proto sources verwenden um quarkus Abhaenigkeiten zu
+			vermeiden. Ebenso im notification-manager -->
+			<exclusions>
+				<exclusion>
+					<groupId>io.grpc</groupId>
+					<artifactId>grpc-core</artifactId>
+				</exclusion>
+				<exclusion>
+					<groupId>org.jboss.slf4j</groupId>
+					<artifactId>slf4j-jboss-logmanager</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+
 		<!-- Spring -->
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-data-mongodb</artifactId>
 		</dependency>
-		<dependency>
-			<groupId>net.devh</groupId>
-			<artifactId>grpc-server-spring-boot-starter</artifactId>
-		</dependency>
 
 		<!--only required for NachrichtenManager -->
 		<dependency>
@@ -106,23 +165,10 @@
 			<artifactId>spring-webmvc</artifactId>
 		</dependency>
 
-		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-web</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-actuator</artifactId>
-		</dependency>
 
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-validation</artifactId>
-		</dependency>
-
-		<dependency>
-			<groupId>org.springframework.security</groupId>
-			<artifactId>spring-security-core</artifactId>
+			<artifactId>spring-boot-starter-actuator</artifactId>
 		</dependency>
 
 		<dependency>
@@ -201,20 +247,33 @@
 
 		<!-- Test -->
 		<dependency>
-			<groupId>de.itvsh.ozg.mail</groupId>
-			<artifactId>mail-service</artifactId>
+			<groupId>de.ozgcloud.nachrichten</groupId>
+			<artifactId>nachrichten-manager</artifactId>
+			<version>${project.version}</version>
+			<type>test-jar</type>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-base</artifactId>
 			<version>${project.version}</version>
 			<type>test-jar</type>
 			<scope>test</scope>
 		</dependency>
 		<dependency>
-			<groupId>de.itvsh.ozg.pluto</groupId>
-			<artifactId>pluto-utils</artifactId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-utils</artifactId>
 			<version>${project.version}</version>
 			<type>test-jar</type>
 			<scope>test</scope>
 		</dependency>
 
+		<dependency>
+			<groupId>de.ozgcloud.api-lib</groupId>
+			<artifactId>ozg-cloud-spring-boot-starter</artifactId>
+			<version>${ozgcloud-starter.version}</version>
+		</dependency>
+
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-test</artifactId>
@@ -226,11 +285,20 @@
 				</exclusion>
 			</exclusions>
 		</dependency>
+
 		<dependency>
 			<groupId>org.springframework.security</groupId>
 			<artifactId>spring-security-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.springframework.ws</groupId>
+			<artifactId>spring-ws-test</artifactId>
+			<scope>test</scope>
 		</dependency>
 
+
 		<dependency>
 			<groupId>org.junit.jupiter</groupId>
 			<artifactId>junit-jupiter-engine</artifactId>
@@ -245,25 +313,33 @@
 		<dependency>
 			<groupId>org.testcontainers</groupId>
 			<artifactId>mongodb</artifactId>
-			<version>${testcontainer.version}</version>
 			<scope>test</scope>
 		</dependency>
 		<dependency>
 			<groupId>org.testcontainers</groupId>
 			<artifactId>elasticsearch</artifactId>
-			<version>${testcontainer.version}</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>com.github.docker-java</groupId>
+			<artifactId>docker-java-api</artifactId>
+			<version>${docker-java.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.awaitility</groupId>
+			<artifactId>awaitility</artifactId>
 			<scope>test</scope>
 		</dependency>
 
 		<!-- mongock -->
 		<dependency>
 			<groupId>io.mongock</groupId>
-			<artifactId>mongock-springboot</artifactId>
+			<artifactId>mongock-springboot-v3</artifactId>
 			<version>${mongock.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>io.mongock</groupId>
-			<artifactId>mongodb-springdata-v3-driver</artifactId>
+			<artifactId>mongodb-springdata-v4-driver</artifactId>
 			<version>${mongock.version}</version>
 		</dependency>
 	</dependencies>
@@ -274,6 +350,21 @@
 			<plugin>
 				<groupId>org.springframework.boot</groupId>
 				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<mainClass>de.ozgcloud.vorgang.VorgangManagerServerApplication</mainClass>
+					<image>
+						<!-- cann be removed when common-lib > 2.3.2-->
+						<builder>paketobuildpacks/builder-jammy-base</builder>
+						<env>
+							<BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"> </BPE_DELIM_JAVA_TOOL_OPTIONS>
+							<BPE_APPEND_JAVA_TOOL_OPTIONS>-Dfile.encoding=UTF-8</BPE_APPEND_JAVA_TOOL_OPTIONS>
+						</env>
+					</image>
+					<profiles>
+						<profile>local</profile>
+						<profile>a12proc</profile>
+					</profiles>
+				</configuration>
 			</plugin>
 
 			<plugin>
@@ -299,6 +390,36 @@
 			<plugin>
 				<groupId>pl.project13.maven</groupId>
 				<artifactId>git-commit-id-plugin</artifactId>
+				<version>4.9.10</version>
+			</plugin>
+
+			<plugin>
+				<groupId>com.mycila</groupId>
+				<artifactId>license-maven-plugin</artifactId>
+				<configuration>
+					<mapping>
+						<config>SCRIPT_STYLE</config>
+						<ftlh>FTL</ftlh>
+					</mapping>
+					<licenseSets>
+						<licenseSet>
+							<header>license/eupl_v1_2_de/header.txt</header>
+							<excludes>
+								<exclude>**/README</exclude>
+								<exclude>src/test/resources/**</exclude>
+								<exclude>src/main/resources/*.yml</exclude>
+								<exclude>src/main/resources/*.txt</exclude>
+							</excludes>
+						</licenseSet>
+					</licenseSets>
+				</configuration>
+				<dependencies>
+					<dependency>
+						<groupId>de.ozgcloud.common</groupId>
+						<artifactId>ozgcloud-common-license</artifactId>
+						<version>${ozgcloud.license.version}</version>
+					</dependency>
+				</dependencies>
 			</plugin>
 		</plugins>
 	</build>
@@ -316,4 +437,4 @@
 		</snapshotRepository>
 	</distributionManagement>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/vorgang-manager-server/run_local.sh b/vorgang-manager-server/run_local.sh
new file mode 100755
index 0000000000000000000000000000000000000000..66e1805b608765ac99e93aa8927bea39d0a90b93
--- /dev/null
+++ b/vorgang-manager-server/run_local.sh
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+./mvnw spring-boot:run -Dspring-boot.run.profiles=local
diff --git a/pluto-server/sonar-project.properties b/vorgang-manager-server/sonar-project.properties
similarity index 93%
rename from pluto-server/sonar-project.properties
rename to vorgang-manager-server/sonar-project.properties
index 8660b9e44335323e02f6aaa513605e4a34635db9..b7f52501bc2eb44826c3c59681a818c722ad1835 100644
--- a/pluto-server/sonar-project.properties
+++ b/vorgang-manager-server/sonar-project.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
 # Ministerpräsidenten des Landes Schleswig-Holstein
 # Staatskanzlei
 # Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
diff --git a/vorgang-manager-server/src/db/cleanup_vorgang.mongodb b/vorgang-manager-server/src/db/cleanup_vorgang.mongodb
new file mode 100644
index 0000000000000000000000000000000000000000..273a474ba71021e16de29f43ba3be2bafcc12f59
--- /dev/null
+++ b/vorgang-manager-server/src/db/cleanup_vorgang.mongodb
@@ -0,0 +1,4 @@
+use('sh-schleswigflensburg-test')
+//use('sh-kiel-test');
+//db.vorgang.drop();
+db.vorgang.update({"_id": '4d903ada-2895-43cd-82de-85b87aad262e'}, {$set:{ 'name' : 'Lebensberechtigungsschein'}})
\ No newline at end of file
diff --git a/vorgang-manager-server/src/license/eupl/header.txt b/vorgang-manager-server/src/license/eupl/header.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6a42e7088495b7744ca3db2d05ff3ba76f43e839
--- /dev/null
+++ b/vorgang-manager-server/src/license/eupl/header.txt
@@ -0,0 +1,40 @@
+====
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+====
+
+Lizenziert unter der EUPL, Version 1.2 oder - sobald
+diese von der Europäischen Kommission genehmigt wurden -
+Folgeversionen der EUPL ("Lizenz");
+Sie dürfen dieses Werk ausschließlich gemäß
+dieser Lizenz nutzen.
+Eine Kopie der Lizenz finden Sie hier:
+
+https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+Sofern nicht durch anwendbare Rechtsvorschriften
+gefordert oder in schriftlicher Form vereinbart, wird
+die unter der Lizenz verbreitete Software "so wie sie
+ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ausdrücklich oder stillschweigend - verbreitet.
+Die sprachspezifischen Genehmigungen und Beschränkungen
+unter der Lizenz sind dem Lizenztext zu entnehmen.
diff --git a/vorgang-manager-server/src/license/eupl/license.txt b/vorgang-manager-server/src/license/eupl/license.txt
new file mode 100644
index 0000000000000000000000000000000000000000..af2666456c9d52978b0ac0817e2fb4eb679775d3
--- /dev/null
+++ b/vorgang-manager-server/src/license/eupl/license.txt
@@ -0,0 +1,125 @@
+====
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+====
+
+OPEN-SOURCE-LIZENZ FÜR DIE EUROPÄISCHE UNION v. 1.2 
+EUPL © Europäische Union 2007, 2016 
+Diese Open-Source-Lizenz für die Europäische Union („EUPL“) gilt für Werke (im Sinne der nachfolgenden Begriffsbestimmung), die unter EUPL-Bedingungen zur Verfügung gestellt werden. Das Werk darf nur in der durch diese Lizenz gestatteten Form genutzt werden (insoweit eine solche Nutzung dem Urheber vorbehalten ist). 
+Das Werk wird unter den Bedingungen dieser Lizenz zur Verfügung gestellt, wenn der Lizenzgeber (im Sinne der nachfolgenden Begriffsbestimmung) den folgenden Hinweis unmittelbar hinter dem Urheberrechtshinweis dieses Werks anbringt: 
+                      Lizenziert unter der EUPL 
+oder in einer anderen Form zum Ausdruck bringt, dass er es unter der EUPL lizenzieren möchte. 
+
+1.Begriffsbestimmungen 
+Für diese Lizenz gelten folgende Begriffsbestimmungen:  
+— „Lizenz“:diese Lizenz.  
+— „Originalwerk“:das Werk oder die Software, die vom Lizenzgeber unter dieser Lizenz verbreitet oder zugänglich gemacht wird, und zwar als Quellcode und gegebenenfalls auch als ausführbarer Code.  
+— „Bearbeitungen“:die Werke oder Software, die der Lizenznehmer auf der Grundlage des Originalwerks oder seiner Bearbeitungen schaffen kann. In dieser Lizenz wird nicht festgelegt, wie umfangreich die Änderung oder wie stark die Abhängigkeit vom Originalwerk für eine Einstufung als Bearbeitung sein muss; dies bestimmt sich nach dem Urheberrecht, das in dem unter Artikel 15 aufgeführten Land anwendbar ist.  
+— „Werk“:das Originalwerk oder seine Bearbeitungen.  
+— „Quellcode“:diejenige Form des Werkes, die zur Auffassung durch den Menschen bestimmt ist und die am besten geeignet ist, um vom Menschen verstanden und verändert zu werden.  
+— „Ausführbarer Code“:die — üblicherweise — kompilierte Form des Werks, die von einem Computer als Programm ausgeführt werden soll.  
+— „Lizenzgeber“:die natürliche oder juristische Person, die das Werk unter der Lizenz verbreitet oder zugänglich macht.  
+— „Bearbeiter“:jede natürliche oder juristische Person, die das Werk unter der Lizenz verändert oder auf andere Weise zur Schaffung einer Bearbeitung beiträgt.  
+— „Lizenznehmer“ („Sie“):jede natürliche oder juristische Person, die das Werk unter den Lizenzbedingungen nutzt.  
+— „Verbreitung“ oder „Zugänglichmachung“:alle Formen von Verkauf, Überlassung, Verleih, Vermietung, Verbreitung, Weitergabe, Übermittlung oder anderweitiger Online- oder Offline-Bereitstellung von Vervielfältigungen des Werks oder Zugänglichmachung seiner wesentlichen Funktionen für dritte natürliche oder juristische Personen.
+
+2.Umfang der Lizenzrechte 
+Der Lizenzgeber erteilt Ihnen hiermit für die Gültigkeitsdauer der am Originalwerk bestehenden Urheberrechte eine weltweite, unentgeltliche, nicht ausschließliche, unterlizenzierbare Lizenz, die Sie berechtigt: 
+—  das Werk uneingeschränkt zu nutzen, 
+—  das Werk zu vervielfältigen, 
+—  das Werk zu verändern und Bearbeitungen auf der Grundlage des Werks zu schaffen, 
+—  das Werk öffentlich zugänglich zu machen, was das Recht einschließt, das Werk oder Vervielfältigungsstücke davon öffentlich bereitzustellen oder wahrnehmbar zu machen oder das Werk, soweit möglich, öffentlich aufzuführen, 
+—  das Werk oder Vervielfältigungen davon zu verbreiten, 
+—  das Werk oder Vervielfältigungen davon zu vermieten oder zu verleihen, 
+—  das Werk oder Vervielfältigungen davon weiter zu lizenzieren. 
+Für die Wahrnehmung dieser Rechte können beliebige, derzeit bekannte oder künftige Medien, Träger und Formate verwendet werden, soweit das geltende Recht dem nicht entgegensteht. Für die Länder, in denen Urheberpersönlichkeitsrechte an dem Werk bestehen, verzichtet der Lizenzgeber im gesetzlich zulässigen Umfang auf seine Urheberpersönlichkeitsrechte, um die Lizenzierung der oben aufgeführten Verwertungsrechte wirksam durchführen zu können. Der Lizenzgeber erteilt dem Lizenznehmer ein nicht ausschließliches, unentgeltliches Nutzungsrecht an seinen Patenten, sofern dies zur Ausübung der durch die Lizenz erteilten Nutzungsrechte am Werk notwendig ist. 
+
+3.Zugänglichmachung des Quellcodes 
+Der Lizenzgeber kann das Werk entweder als Quellcode oder als ausführbaren Code zur Verfügung stellen. Stellt er es als ausführbaren Code zur Verfügung, so stellt er darüber hinaus eine maschinenlesbare Kopie des Quellcodes für jedes von ihm verbreitete Vervielfältigungsstück des Werks zur Verfügung, oder er verweist in einem Vermerk im Anschluss an den dem Werk beigefügten Urheberrechtshinweis auf einen Speicherort, an dem problemlos und unentgeltlich auf den Quellcode zugegriffen werden kann, solange der Lizenzgeber das Werk verbreitet oder zugänglich macht. 
+
+4.Einschränkungen des Urheberrechts
+Es ist nicht Zweck dieser Lizenz, Ausnahmen oder Schranken der ausschließlichen Rechte des Urhebers am Werk, die dem Lizenznehmer zugutekommen, einzuschränken. Auch die Erschöpfung dieser Rechte bleibt von dieser Lizenz unberührt. 
+
+5.Pflichten des Lizenznehmers 
+Die Einräumung der oben genannten Rechte ist an mehrere Beschränkungen und Pflichten für den Lizenznehmer gebunden: 
+
+Urheberrechtshinweis, Lizenztext, Nennung des Bearbeiters: Der Lizenznehmer muss alle Urheberrechts-, Patent- oder Markenrechtshinweise und alle Hinweise auf die Lizenz und den Haftungsausschluss unverändert lassen. Jedem von ihm verbreiteten oder zugänglich gemachten Vervielfältigungsstück des Werks muss der Lizenznehmer diese Hinweise sowie diese Lizenz beifügen. Der Lizenznehmer muss auf jedem abgeleiteten Werk deutlich darauf hinweisen, dass das Werk geändert wurde, und das Datum der Bearbeitung angeben.
+
+„Copyleft“-Klausel: Der Lizenznehmer darf Vervielfältigungen des Originalwerks oder Bearbeitungen nur unter den Bedingungen dieser EUPL oder einer neueren Version dieser Lizenz verbreiten oder zugänglich machen, außer wenn das Originalwerk ausdrücklich nur unter dieser Lizenzversion — z. B. mit der Angabe „Nur EUPL V. 1.2“ — verbreitet werden darf. Der Lizenznehmer (der zum Lizenzgeber wird) darf für das Werk oder die Bearbeitung keine zusätzlichen Bedingungen anbieten oder vorschreiben, die die Bedingungen dieser Lizenz verändern oder einschränken. 
+
+Kompatibilitäts-Klausel: Wenn der Lizenznehmer Bearbeitungen, die auf dem Werk und einem anderen Werk, das unter einer kompatiblen Lizenz lizenziert wurde, basieren, oder die Kopien dieser Bearbeitungen verbreitet oder zugänglich macht, kann dies unter den Bedingungen dieser kompatiblen Lizenz erfolgen. Unter „kompatibler Lizenz“ ist eine im Anhang dieser Lizenz angeführte Lizenz zu verstehen. Sollten die Verpflichtungen des Lizenznehmers aus der kompatiblen Lizenz mit denjenigen aus der vorliegenden Lizenz (EUPL) in Konflikt stehen, werden die Verpflichtungen aus der kompatiblen Lizenz Vorrang haben.
+
+Bereitstellung des Quellcodes: Wenn der Lizenznehmer Vervielfältigungsstücke des Werks verbreitet oder zugänglich macht, muss er eine maschinenlesbare Fassung des Quellcodes mitliefern oder einen Speicherort angeben, über den problemlos und unentgeltlich so lange auf diesen Quellcode zugegriffen werden kann, wie der Lizenznehmer das Werk verbreitet oder zugänglich macht. 
+
+Rechtsschutz: Diese Lizenz erlaubt nicht die Benutzung von Kennzeichen, Marken oder geschützten Namensrechten des Lizenzgebers, soweit dies nicht für die angemessene und übliche Beschreibung der Herkunft des Werks und der inhaltlichen Wiedergabe des Urheberrechtshinweises erforderlich ist.
+
+6.Urheber und Bearbeiter 
+Der ursprüngliche Lizenzgeber gewährleistet, dass er das Urheberrecht am Originalwerk innehat oder dieses an ihn lizenziert wurde und dass er befugt ist, diese Lizenz zu erteilen. 
+Jeder Bearbeiter gewährleistet, dass er das Urheberrecht an den von ihm vorgenommenen Änderungen des Werks besitzt und befugt ist, diese Lizenz zu erteilen. 
+Jedes Mal, wenn Sie die Lizenz annehmen, erteilen Ihnen der ursprüngliche Lizenzgeber und alle folgenden Bearbeiter eine Befugnis zur Nutzung ihrer Beiträge zum Werk unter den Bedingungen dieser Lizenz. 
+
+7.Gewährleistungsausschluss 
+Die Arbeit an diesem Werk wird laufend fortgeführt; es wird durch unzählige Bearbeiter ständig verbessert. Das Werk ist nicht vollendet und kann daher Fehler („bugs“) enthalten, die dieser Art der Entwicklung inhärent sind. 
+Aus den genannten Gründen wird das Werk unter dieser Lizenz „so, wie es ist“ ohne jegliche Gewährleistung zur Verfügung gestellt. Dies gilt unter anderem — aber nicht ausschließlich — für Marktreife, Verwendbarkeit für einen bestimmten Zweck, Mängelfreiheit, Richtigkeit sowie Nichtverletzung von anderen Immaterialgüterrechten als dem Urheberrecht (vgl. dazu Artikel 6 dieser Lizenz). 
+Dieser Gewährleistungsausschluss ist wesentlicher Bestandteil der Lizenz und Bedingung für die Einräumung von Rechten an dem Werk.
+
+8.Haftungsausschluss/Haftungsbeschränkung 
+Außer in Fällen von Vorsatz oder der Verursachung von Personenschäden haftet der Lizenzgeber nicht für direkte oder indirekte, materielle oder immaterielle Schäden irgendwelcher Art, die aus der Lizenz oder der Benutzung des Werks folgen; dies gilt unter anderem, aber nicht ausschließlich, für Firmenwertverluste, Produktionsausfall, Computerausfall oder Computerfehler, Datenverlust oder wirtschaftliche Schäden, und zwar auch dann, wenn der Lizenzgeber auf die Möglichkeit solcher Schäden hingewiesen wurde. Unabhängig davon haftet der Lizenzgeber im Rahmen der gesetzlichen Produkthaftung, soweit die entsprechenden Regelungen auf das Werk anwendbar sind. 
+
+9.Zusatzvereinbarungen 
+Wenn Sie das Werk verbreiten, können Sie Zusatzvereinbarungen schließen, in denen Verpflichtungen oder Dienstleistungen festgelegt werden, die mit dieser Lizenz vereinbar sind. Sie dürfen Verpflichtungen indessen nur in Ihrem eigenen Namen und auf Ihre eigene Verantwortung eingehen, nicht jedoch im Namen des ursprünglichen Lizenzgebers oder eines anderen Bearbeiters, und nur, wenn Sie sich gegenüber allen Bearbeitern verpflichten, sie zu entschädigen, zu verteidigen und von der Haftung freizustellen, falls aufgrund der von Ihnen eingegangenen Gewährleistungsverpflichtung oder Haftungsübernahme Forderungen gegen sie geltend gemacht werden oder eine Haftungsverpflichtung entsteht. 
+
+10.Annahme der Lizenz 
+Sie können den Bestimmungen dieser Lizenz zustimmen, indem Sie das Symbol „Lizenz annehmen“ unter dem Fenster mit dem Lizenztext anklicken oder indem Sie Ihre Zustimmung auf vergleichbare Weise in einer nach anwendbarem Recht zulässigen Form geben. Das Anklicken des Symbols gilt als Anzeichen Ihrer eindeutigen und unwiderruflichen Annahme der Lizenz und der darin enthaltenen Klauseln und Bedingungen. In gleicher Weise gilt als Zeichen der eindeutigen und unwiderruflichen Zustimmung die Ausübung eines Rechtes, das in Artikel 2 dieser Lizenz angeführt ist, wie das Erstellen einer Bearbeitung oder die Verbreitung oder Zugänglichmachung des Werks oder dessen Vervielfältigungen. 
+
+11.Informationspflichten
+Wenn Sie das Werk verbreiten oder zugänglich machen (beispielsweise, indem Sie es zum Herunterladen von einer Website anbieten), müssen Sie über den Vertriebskanal oder das benutzte Verbreitungsmedium der Öffentlichkeit zumindest jene Informationen bereitstellen, die nach dem anwendbaren Recht bezüglich der Lizenzgeber, der Lizenz und ihrer Zugänglichkeit, des Abschlusses des Lizenzvertrags sowie darüber, wie die Lizenz durch den Lizenznehmer gespeichert und vervielfältigt werden kann, erforderlich sind.
+
+12.Beendigung der Lizenz 
+Die Lizenz und die damit eingeräumten Rechte erlöschen automatisch, wenn der Lizenznehmer gegen die Lizenzbedingungen verstößt. Ein solches Erlöschen der Lizenz führt nicht zum Erlöschen der Lizenzen von Personen, denen das Werk vom Lizenznehmer unter dieser Lizenz zur Verfügung gestellt worden ist, solange diese Personen die Lizenzbedingungen erfüllen. 
+13.Sonstiges
+Unbeschadet des Artikels 9 stellt die Lizenz die vollständige Vereinbarung der Parteien über das Werk dar. Sind einzelne Bestimmungen der Lizenz nach geltendem Recht nichtig oder unwirksam, so berührt dies nicht die Wirksamkeit oder Durchsetzbarkeit der Lizenz an sich. Solche Bestimmungen werden vielmehr so ausgelegt oder modifiziert, dass sie wirksam und durchsetzbar sind. Die Europäische Kommission kann weitere Sprachfassungen oder neue Versionen dieser Lizenz oder aktualisierte Fassungen des Anhangs veröffentlichen, soweit dies notwendig und angemessen ist, ohne den Umfang der Lizenzrechte zu verringern. Neue Versionen werden mit einer eindeutigen Versionsnummer veröffentlicht. Alle von der Europäischen Kommission anerkannten Sprachfassungen dieser Lizenz sind gleichwertig. Die Parteien können sich auf die Sprachfassung ihrer Wahl berufen.
+
+14.Gerichtsstand
+Unbeschadet besonderer Vereinbarungen zwischen den Parteien gilt Folgendes: 
+—  Für alle Streitigkeiten über die Auslegung dieser Lizenz zwischen den Organen, Einrichtungen und sonstigen Stellen der Europäischen Union als Lizenzgeber und einem Lizenznehmer ist der Gerichtshof der Europäischen Union gemäß Artikel 272 des Vertrags über die Arbeitsweise der Europäischen Union zuständig; 
+—  Gerichtsstand für Streitigkeiten zwischen anderen Parteien über die Auslegung dieser Lizenz ist allein der Ort, an dem der Lizenzgeber seinen Wohnsitz oder den wirtschaftlichen Mittelpunkt seiner Tätigkeit hat. 
+
+15.Anwendbares Recht
+Unbeschadet besonderer Vereinbarungen zwischen den Parteien gilt Folgendes: 
+—  Diese Lizenz unterliegt dem Recht des Mitgliedstaats der Europäischen Union, in dem der Lizenzgeber seinen Sitz, Wohnsitz oder eingetragenen Sitz hat; 
+—  diese Lizenz unterliegt dem belgischen Recht, wenn der Lizenzgeber keinen Sitz, Wohnsitz oder eingetragenen Sitz in einem Mitgliedstaat der Europäischen Union hat.
+   
+Anlage 
+„Kompatible Lizenzen“ nach Artikel 5 der EUPL sind: 
+—  GNU General Public License (GPL) v. 2, v. 3 
+—  GNU Affero General Public License (AGPL) v. 3 
+—  Open Software License (OSL) v. 2.1, v. 3.0 
+—  Eclipse Public License (EPL) v. 1.0 
+—  CeCILL v. 2.0, v. 2.1 
+—  Mozilla Public Licence (MPL) v. 2 
+—  GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 
+—  Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) für andere Werke als Software 
+—  European Union Public Licence (EUPL) v. 1.1, v. 1.2 
+—  Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) oder Strong Reciprocity (LiLiQ-R+)
+Die Europäische Kommission kann diesen Anhang aktualisieren, um neuere Fassungen der obigen Lizenzen aufzunehmen, ohne hierfür eine neue Fassung der EUPL auszuarbeiten, solange diese Lizenzen die in Artikel 2 gewährten Rechte gewährleisten und den erfassten Quellcode vor ausschließlicher Aneignung schützen.
+Alle sonstigen Änderungen oder Ergänzungen dieses Anhangs bedürfen der Ausarbeitung einer neuen Version der EUPL.  
\ No newline at end of file
diff --git a/vorgang-manager-server/src/license/licenses.properties b/vorgang-manager-server/src/license/licenses.properties
new file mode 100644
index 0000000000000000000000000000000000000000..9d0f9a0ca06461d1fcd54385f6775eeb91d71652
--- /dev/null
+++ b/vorgang-manager-server/src/license/licenses.properties
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+eupl=eupl
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerServerConfiguration.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerServerConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..7415dd26ba1e3fe09e155ae51bc96faf68a3e46f
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangManagerServerConfiguration.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+
+import io.mongock.runner.springboot.EnableMongock;
+
+@Configuration
+@EnableMongock
+@EnableMongoRepositories(basePackages = { "de.ozgcloud.vorgang.vorgang", "de.ozgcloud.vorgang.attached_item", "de.ozgcloud.vorgang.command" })
+@EnableElasticsearchRepositories(basePackages = "de.ozgcloud.vorgang.common.search")
+public class VorgangManagerServerConfiguration {
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangProcessorConfiguration.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangProcessorConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..74b4d593005aab9c526598fc1f260635ae880e79
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/VorgangProcessorConfiguration.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider;
+import de.ozgcloud.apilib.user.GrpcOzgCloudUserProfileService;
+import de.ozgcloud.apilib.user.OzgCloudUserProfileService;
+import de.ozgcloud.apilib.user.UserProfileMapper;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
+import de.ozgcloud.apilib.vorgang.grpc.GrpcOzgCloudVorgangService;
+import de.ozgcloud.apilib.vorgang.grpc.OzgCloudVorgangMapper;
+import de.ozgcloud.apilib.vorgang.grpc.OzgCloudVorgangStubMapper;
+import de.ozgcloud.user.grpc.userprofile.UserProfileServiceGrpc.UserProfileServiceBlockingStub;
+import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Configuration
+class VorgangProcessorConfiguration {
+
+	@GrpcClient("vorgang-manager")
+	private VorgangServiceBlockingStub vorgangServiceStub;
+
+	@GrpcClient("user-manager")
+	private UserProfileServiceBlockingStub userProfileServiceGrpc;
+
+	@Bean
+	OzgCloudVorgangService ozgCloudVorgangService(OzgCloudVorgangMapper mapper, OzgCloudVorgangStubMapper stubMapper,
+			OzgCloudCallContextProvider contextProvider) {
+		return new GrpcOzgCloudVorgangService(vorgangServiceStub, mapper, stubMapper, contextProvider);
+	}
+
+	@Bean
+	OzgCloudUserProfileService ozgCloudUserProfileService(UserProfileMapper mapper, OzgCloudCallContextProvider contextProvider) {
+		return new GrpcOzgCloudUserProfileService(userProfileServiceGrpc, mapper, contextProvider);
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemMapper.java
similarity index 89%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemMapper.java
index f87e18745a075db18ebc0322fa29d9546b747297..6a214851b25583df0b07a9684fadd5e523ff256b 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import org.mapstruct.CollectionMappingStrategy;
 import org.mapstruct.Mapper;
@@ -30,8 +30,8 @@ import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 import org.mapstruct.ReportingPolicy;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem;
 
 @Mapper(uses = GrpcObjectMapper.class, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
 		unmappedTargetPolicy = ReportingPolicy.WARN, //
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemService.java
similarity index 80%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemService.java
index 97a0b6f39838109f261bfa8f059137d0d2a30bac..b7c194e4f7c03b87c8f73e88f3df38a15f381019 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,19 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import java.util.Optional;
 import java.util.stream.Stream;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemResponse;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.VorgangAttachedItemServiceGrpc.VorgangAttachedItemServiceImplBase;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemResponse;
+import de.ozgcloud.vorgang.vorgangAttachedItem.VorgangAttachedItemServiceGrpc.VorgangAttachedItemServiceImplBase;
 import io.grpc.stub.StreamObserver;
 import net.devh.boot.grpc.server.service.GrpcService;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItem.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItem.java
similarity index 88%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItem.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItem.java
index b7f791dac4b955005ce36c09f34ed1478444dccd..85baf2e679955e14eae31309344b6cf33dc5ad16 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItem.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import java.util.Map;
 
@@ -30,6 +30,7 @@ import org.springframework.data.annotation.TypeAlias;
 import org.springframework.data.annotation.Version;
 import org.springframework.data.mongodb.core.mapping.Document;
 
+import jakarta.validation.constraints.NotBlank;
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
@@ -52,15 +53,20 @@ public class VorgangAttachedItem {
 	static final String FIELDNAME_VORGANG_ID = "vorgangId";
 	static final String FIELDNAME_ITEM_NAME = "itemName";
 	static final String FIELDNAME_ITEM = "item";
+	public static final String FIELDNAME_IS_DELETED = "deleted";
 
 	@Id
 	private String id;
 	@Version
 	private long version;
 
+	@NotBlank
 	private String client;
+	@NotBlank
 	private String vorgangId;
+	@NotBlank
 	private String itemName;
+	private boolean deleted;
 
 	private Map<String, Object> item;
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCreatedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java
similarity index 78%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCreatedEvent.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java
index 3a0953d03f3bc42bb913c3ca1318c22bf14bb695..81137a5775a77ed2c44ffae3ee37a4cb99807883 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCreatedEvent.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCreatedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,16 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
-import de.itvsh.ozg.pluto.command.CommandExecutedEvent;
+import de.ozgcloud.command.CommandExecutedEvent;
 
 public class VorgangAttachedItemCreatedEvent extends CommandExecutedEvent {
 
 	private static final long serialVersionUID = 1L;
 
-	protected VorgangAttachedItemCreatedEvent(String commandId) {
-		super(commandId);
+	protected VorgangAttachedItemCreatedEvent(String commandId, String createdResource) {
+		super(commandId, createdResource);
 	}
 
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCustomRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepository.java
similarity index 83%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCustomRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepository.java
index b0b9228b4aff5ef539ca8aad2977eb3df8694066..541469d02d63cc89d586a703f9ef49451f8b96aa 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCustomRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import java.util.Map;
 
@@ -30,4 +30,8 @@ interface VorgangAttachedItemCustomRepository {
 	void patch(String itemId, long version, Map<String, Object> propertyMap);
 
 	void forcePatch(String itemId, Map<String, Object> propertyMap);
+
+	void delete(String itemId, long version);
+
+	void updateDeleted(boolean deleted, String itemId, long version);
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCustomRepositoryImpl.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepositoryImpl.java
similarity index 58%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCustomRepositoryImpl.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepositoryImpl.java
index 75024c3730d39432d7a5dffb73a49c7be95e216d..d6f352e97532dc8c74799fdda659b15f04a7ff03 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemCustomRepositoryImpl.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepositoryImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
+import static de.ozgcloud.vorgang.common.db.CriteriaUtil.*;
 import static org.springframework.data.mongodb.core.query.Criteria.*;
 import static org.springframework.data.mongodb.core.query.Query.*;
 
+import java.util.HashMap;
 import java.util.Map;
-import java.util.stream.Collectors;
 
-import org.apache.commons.lang3.tuple.Pair;
+import jakarta.annotation.PostConstruct;
+
 import org.bson.Document;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
@@ -38,18 +40,36 @@ import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.stereotype.Repository;
 
+import de.ozgcloud.vorgang.common.db.CollisionVerifier;
+
 @Repository
 public class VorgangAttachedItemCustomRepositoryImpl implements VorgangAttachedItemCustomRepository {
 
 	@Autowired
 	private MongoOperations mongoOperations;
 
+	private CollisionVerifier collisionVerifier;
+
+	@PostConstruct
+	void init() {
+		collisionVerifier = createCollisionVerifier();
+	}
+
+	CollisionVerifier createCollisionVerifier() {
+		return new CollisionVerifier(this::doVorgangAttachedItemExist);
+	}
+
+	boolean doVorgangAttachedItemExist(String itemId) {
+		return mongoOperations.exists(query(isId(itemId)), VorgangAttachedItem.COLLECTION_NAME);
+	}
+
 	@Override
 	public void patch(String itemId, long version, Map<String, Object> propertyMap) {
 		mongoOperations.updateFirst(
 				query(byIdAndVersion(itemId, version)),
 				createUpdateForItemAndVersion(propertyMap),
 				VorgangAttachedItem.class);
+
 	}
 
 	@Override
@@ -61,24 +81,46 @@ public class VorgangAttachedItemCustomRepositoryImpl implements VorgangAttachedI
 	}
 
 	private Query createQueryById(String itemId) {
-		return query(byId(itemId));
+		return query(new Criteria().andOperator(byId(itemId), byNotDeleted()));
 	}
 
 	private Criteria byIdAndVersion(String itemId, long version) {
-		return byId(itemId).and(VorgangAttachedItem.FIELDNAME_VERSION).is(version);
+		return new Criteria().andOperator(byId(itemId), byVersion(version), byNotDeleted());
 	}
 
 	private Criteria byId(String itemId) {
 		return where(VorgangAttachedItem.FIELDNAME_ID).is(itemId);
 	}
 
+	private Criteria byVersion(long version) {
+		return where(VorgangAttachedItem.FIELDNAME_VERSION).is(version);
+	}
+
+	private Criteria byNotDeleted() {
+		return where(VorgangAttachedItem.FIELDNAME_IS_DELETED).is(false);
+	}
+
 	private Update createUpdateForItemAndVersion(Map<String, Object> propertyMap) {
 		return Update.fromDocument(buildItemPatchDocument(propertyMap)).inc(VorgangAttachedItem.FIELDNAME_VERSION, 1);
 	}
 
 	private Document buildItemPatchDocument(Map<String, Object> propertiesMap) {
-		return new Document(propertiesMap.keySet().stream()
-				.map(fieldName -> Pair.of(String.format("%s.%s", VorgangAttachedItem.FIELDNAME_ITEM, fieldName), propertiesMap.get(fieldName)))
-				.collect(Collectors.toMap(Pair::getKey, Pair::getValue)));
+		Map<String, Object> resultMap = new HashMap<>(propertiesMap.size());
+		propertiesMap.forEach((k, v) -> resultMap.put("%s.%s".formatted(VorgangAttachedItem.FIELDNAME_ITEM, k), v));
+		return new Document(resultMap);
+	}
+
+	@Override
+	public void delete(String itemId, long version) {
+		var deleteResult = mongoOperations.remove(query(whereIdAndVersion(itemId, version)), VorgangAttachedItem.COLLECTION_NAME);
+		collisionVerifier.verify(deleteResult, itemId);
 	}
+
+	@Override
+	public void updateDeleted(boolean deleted, String itemId, long version) {
+		var updateResult = mongoOperations.updateFirst(query(whereIdAndVersion(itemId, version)),
+				Update.update(VorgangAttachedItem.FIELDNAME_IS_DELETED, deleted), VorgangAttachedItem.COLLECTION_NAME);
+		collisionVerifier.verify(updateResult, itemId);
+	}
+
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemDeletedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemDeletedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..145bcdc1e2114e9790cf6e096a955e08d0c29821
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemDeletedEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.attached_item;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
+
+public class VorgangAttachedItemDeletedEvent extends CommandExecutedEvent {
+
+	private static final long serialVersionUID = 1L;
+
+	protected VorgangAttachedItemDeletedEvent(Command command) {
+		super(command);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd98cab2decc8fa5cc1b7959dc5e44c0aa481576
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListener.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.attached_item;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import jakarta.validation.ValidationException;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandRevokeFailedEvent;
+import de.ozgcloud.command.CommandRevokedEvent;
+import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.vorgang.VorgangDeletedEvent;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Log4j2
+class VorgangAttachedItemEventListener {
+
+	private static final String IS_CREATE_ITEM_ORDER_CONDITION = "{T(de.ozgcloud.vorgang.attached_item.VorgangAttachedItemEventListener).IS_CREATE_ITEM_ORDER.test(event.getSource())}";
+	private static final String IS_UPDATE_ITEM_ORDER_CONDITION = "{T(de.ozgcloud.vorgang.attached_item.VorgangAttachedItemEventListener).IS_UPDATE_ITEM_ORDER.test(event.getSource())}";
+	private static final String IS_PATCH_ITEM_ORDER_CONDITION = "{T(de.ozgcloud.vorgang.attached_item.VorgangAttachedItemEventListener).IS_PATCH_ITEM_ORDER.test(event.getSource())}";
+	private static final String IS_DELETE_ITEM_ORDER_CONDITION = "{T(de.ozgcloud.vorgang.attached_item.VorgangAttachedItemEventListener).IS_DELETE_ITEM_ORDER.test(event.getSource())}";
+
+	public static final Predicate<Command> IS_CREATE_ITEM_ORDER = command -> Order.CREATE_ATTACHED_ITEM.isMeant(command.getOrder());
+	public static final Predicate<Command> IS_UPDATE_ITEM_ORDER = command -> Order.UPDATE_ATTACHED_ITEM.isMeant(command.getOrder());
+	public static final Predicate<Command> IS_PATCH_ITEM_ORDER = command -> Order.PATCH_ATTACHED_ITEM.isMeant(command.getOrder());
+	public static final Predicate<Command> IS_DELETE_ITEM_ORDER = command -> Order.DELETE_ATTACHED_ITEM.isMeant(command.getOrder());
+
+	@Autowired
+	private VorgangAttachedItemService service;
+	@Autowired
+	private VorgangAttachedItemMapper mapper;
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	@EventListener(condition = IS_CREATE_ITEM_ORDER_CONDITION)
+	public void createItem(CommandCreatedEvent event) {
+		var command = event.getSource();
+		validateCreateCommand(command);
+
+		var item = mapper.fill(command.getBodyObject());
+		service.create(command.getId(), item.toBuilder().id(null).version(0).build());
+	}
+
+	private void validateCreateCommand(Command command) {
+		if (!StringUtils.equals(command.getRelationId(), command.getVorgangId())) {
+			throw new ValidationException("Command invalid creation command: vorgangId and relationId must be equals");
+		}
+
+	}
+
+	@EventListener(condition = IS_UPDATE_ITEM_ORDER_CONDITION)
+	public void updateItem(CommandCreatedEvent event) {
+		var command = event.getSource();
+		var itemBuilder = mapper.fill(command.getBodyObject())
+				.toBuilder().id(command.getRelationId());
+
+		if (Objects.nonNull(command.getRelationVersion())) {
+			itemBuilder.version(command.getRelationVersion());
+			service.update(command.getId(), itemBuilder.build());
+		} else {
+			service.forceUpdate(command.getId(), itemBuilder.build());
+		}
+
+	}
+
+	@EventListener(condition = IS_PATCH_ITEM_ORDER_CONDITION)
+	public void patchItem(CommandCreatedEvent event) {
+		var command = event.getSource();
+		var item = mapper.fill(command.getBodyObject());
+
+		service.patch(command, item.getItem());
+	}
+
+	@EventListener(condition = IS_DELETE_ITEM_ORDER_CONDITION)
+	public void deleteItem(CommandCreatedEvent event) {
+		var command = event.getSource();
+		try {
+			service.markAsDeleteByIdAndVersion(command.getRelationId(), command.getRelationVersion());
+			publisher.publishEvent(new VorgangAttachedItemDeletedEvent(command));
+		} catch (RuntimeException e) {
+			handleException(e, command.getId());
+		}
+	}
+
+	void handleException(Exception e, String commandId) {
+		LOG.error("Command failed with Exception", e);
+		publisher.publishEvent(new CommandFailedEvent(commandId, "Command Failed: " + e.getMessage()));
+	}
+
+	@EventListener
+	public void onVorgangDeleted(VorgangDeletedEvent event) {
+		try {
+			service.deleteByVorgangId(event.getCommand().getVorgangId());
+		} catch (RuntimeException e) {
+			LOG.error("Error on deleting Attached Items.", e);
+		}
+	}
+
+	@EventListener(condition = IS_DELETE_ITEM_ORDER_CONDITION)
+	public void onRevokeDeleteItem(RevokeCommandEvent event) {
+		var command = event.getSource();
+		try {
+			service.unmarkAsDeleteByIdAndVersion(command.getRelationId(), command.getRelationVersion());
+			publisher.publishEvent(new CommandRevokedEvent(command));
+		} catch (RuntimeException e) {
+			LOG.error("Revoke of delete item command failed", e);
+			publisher.publishEvent(new CommandRevokeFailedEvent(command.getId(), e.getMessage()));
+		}
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemMapper.java
similarity index 82%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemMapper.java
index 7a83eccb638ed29519daf5137916a66573fc8d0b..d23d779a5520cb7f7519d96f02a8e339507d8b58 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import java.util.Map;
 import java.util.Optional;
 
+import org.apache.commons.collections.MapUtils;
 import org.mapstruct.Mapper;
 import org.mapstruct.ReportingPolicy;
 
@@ -45,11 +46,11 @@ public interface VorgangAttachedItemMapper {
 
 		return VorgangAttachedItem.builder()
 				.id(extractIdFromItem(propertyMap))
-				.client((String) propertyMap.get(PROPERTY_CLIENT))
-				.vorgangId((String) propertyMap.get(PROPERTY_VORGANG_ID))
-				.itemName((String) propertyMap.get(PROPERTY_ITEM_NAME))
+				.client(MapUtils.getString(propertyMap, PROPERTY_CLIENT))
+				.vorgangId(MapUtils.getString(propertyMap, PROPERTY_VORGANG_ID))
+				.itemName(MapUtils.getString(propertyMap, PROPERTY_ITEM_NAME))
 				.item((Map<String, Object>) propertyMap.get(PROPERTY_ITEM))
-				.version((Long) propertyMap.getOrDefault(PROPERTY_VERSION, 0L))
+				.version(MapUtils.getLong(propertyMap, PROPERTY_VERSION, 0L))
 				.build();
 	}
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemRepository.java
similarity index 64%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemRepository.java
index 3d4af854d7b4bfd25be972f33e591a8e0ca90210..f8040415d13614e2cb0c386e07affc2fd865eaf0 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,19 +21,24 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
+import java.util.Optional;
 import java.util.stream.Stream;
 
 import org.springframework.data.mongodb.repository.MongoRepository;
 
 interface VorgangAttachedItemRepository extends VorgangAttachedItemCustomRepository, MongoRepository<VorgangAttachedItem, String> {
 
-	Stream<VorgangAttachedItem> findByVorgangIdAndClientAndItemName(String vorgangId, String client, String itemName);
+	Optional<VorgangAttachedItem> findByIdAndDeleted(String id, boolean deleted);
 
-	Stream<VorgangAttachedItem> findByVorgangIdAndClient(String vorgangId, String client);
+	Stream<VorgangAttachedItem> findByVorgangIdAndClientAndItemNameAndDeleted(String vorgangId, String client, String itemName, boolean isDeleted);
 
-	Stream<VorgangAttachedItem> findByVorgangIdAndItemName(String vorgangId, String itemName);
+	Stream<VorgangAttachedItem> findByVorgangIdAndClientAndDeleted(String vorgangId, String client, boolean isDeleted);
 
-	Stream<VorgangAttachedItem> findByVorgangId(String vorgangId);
+	Stream<VorgangAttachedItem> findByVorgangIdAndItemNameAndDeleted(String vorgangId, String itemName, boolean isDeleted);
+
+	Stream<VorgangAttachedItem> findByVorgangIdAndDeleted(String vorgangId, boolean deleted);
+
+	void deleteByVorgangId(String vorgangId);
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java
similarity index 66%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java
index 4961b2b0eda6952202da5d58c7dcfa44a21314e5..7146a2e7ecb65a091addd65594834dd09baf66df 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -29,26 +29,32 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Stream;
 
+import jakarta.validation.Valid;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
 import lombok.NonNull;
 
 @Service
+@Validated
 public class VorgangAttachedItemService {
 
+	static final boolean NOT_DELETED = false;
+
 	@Autowired
 	private VorgangAttachedItemRepository repository;
 	@Autowired
 	private ApplicationEventPublisher publisher;
 
-	public VorgangAttachedItem create(String commandId, VorgangAttachedItem item) {
+	public VorgangAttachedItem create(@NonNull String commandId, @Valid VorgangAttachedItem item) {
 		var saved = repository.save(prepareForCreation(item));
 
-		publisher.publishEvent(new VorgangAttachedItemCreatedEvent(commandId));
+		publisher.publishEvent(new VorgangAttachedItemCreatedEvent(commandId, saved.getId()));
 
 		return saved;
 	}
@@ -73,19 +79,26 @@ public class VorgangAttachedItemService {
 		publisher.publishEvent(new VorgangAttachedItemUpdatedEvent(commandId));
 	}
 
+	public void forceUpdate(String commandId, VorgangAttachedItem item) {
+		repository.forcePatch(item.getId(), item.getItem());
+
+		publisher.publishEvent(new VorgangAttachedItemUpdatedEvent(commandId));
+	}
+
 	public Optional<VorgangAttachedItem> findById(String itemId) {
-		return repository.findById(itemId).map(this::addIdToItem);
+		return repository.findByIdAndDeleted(itemId, NOT_DELETED).map(this::addIdToItem);
 	}
 
 	public Stream<VorgangAttachedItem> find(String vorgangId, Optional<String> client, Optional<String> itemName) {
 		if (hasVorgangIdOnly(client, itemName)) {
-			return repository.findByVorgangId(vorgangId).map(this::addIdToItem);
+			return repository.findByVorgangIdAndDeleted(vorgangId, NOT_DELETED).map(this::addIdToItem);
 		} else if (isEmpty(itemName) && client.isPresent()) {
-			return repository.findByVorgangIdAndClient(vorgangId, client.get()).map(this::addIdToItem);
+			return repository.findByVorgangIdAndClientAndDeleted(vorgangId, client.get(), NOT_DELETED).map(this::addIdToItem);
 		} else if (isEmpty(client)) {
-			return repository.findByVorgangIdAndItemName(vorgangId, itemName.get()).map(this::addIdToItem);
+			return repository.findByVorgangIdAndItemNameAndDeleted(vorgangId, itemName.get(), NOT_DELETED).map(this::addIdToItem);
 		} else {
-			return repository.findByVorgangIdAndClientAndItemName(vorgangId, client.get(), itemName.get()).map(this::addIdToItem);
+			return repository.findByVorgangIdAndClientAndItemNameAndDeleted(vorgangId, client.get(), itemName.get(), NOT_DELETED)
+					.map(this::addIdToItem);
 		}
 	}
 
@@ -108,7 +121,7 @@ public class VorgangAttachedItemService {
 	}
 
 	public VorgangAttachedItem getById(String id) {
-		var attachedItem = repository.findById(id).orElseThrow(() -> new NotFoundException(VorgangAttachedItem.class, id));
+		var attachedItem = repository.findByIdAndDeleted(id, NOT_DELETED).orElseThrow(() -> new NotFoundException(VorgangAttachedItem.class, id));
 
 		return addIdToItem(attachedItem);
 	}
@@ -118,4 +131,17 @@ public class VorgangAttachedItemService {
 		itemMap.put(VorgangAttachedItem.FIELDNAME_ID, attachedItem.getId());
 		return attachedItem.toBuilder().item(Collections.unmodifiableMap(itemMap)).build();
 	}
+
+	public void markAsDeleteByIdAndVersion(String itemId, long version) {
+		repository.updateDeleted(true, itemId, version);
+	}
+
+	public void unmarkAsDeleteByIdAndVersion(String itemId, long version) {
+		repository.updateDeleted(false, itemId, version);
+	}
+
+	public void deleteByVorgangId(String vorgangId) {
+		repository.deleteByVorgangId(vorgangId);
+	}
+
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemUpdatedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemUpdatedEvent.java
similarity index 87%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemUpdatedEvent.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemUpdatedEvent.java
index 566a4ec2ed57ca747c0d97d8c8efb5299f2287f4..143aeef2ed923b340e2256c4dcdc60a993fb8dd7 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemUpdatedEvent.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemUpdatedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
-import de.itvsh.ozg.pluto.command.CommandExecutedEvent;
+import de.ozgcloud.command.CommandExecutedEvent;
 
 public class VorgangAttachedItemUpdatedEvent extends CommandExecutedEvent {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttribute.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttribute.java
similarity index 95%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttribute.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttribute.java
index 89e07a693d6ee2ac283d999f9999bae5ba66f289..395e5e1b15cab3805e55960028e4a5a27709f7ce 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttribute.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttribute.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,17 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.Optional;
 
-import javax.validation.constraints.NotNull;
-
 import org.springframework.data.annotation.AccessType;
 import org.springframework.data.annotation.PersistenceCreator;
 import org.springframework.data.annotation.Transient;
 import org.springframework.data.annotation.TypeAlias;
 
+import jakarta.validation.constraints.NotNull;
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeAlreadyExistsException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeAlreadyExistsException.java
similarity index 87%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeAlreadyExistsException.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeAlreadyExistsException.java
index 9dcf409fa330a17bcc08ef090a734897076134a2..b7cdc3f6b3c13b03d59706253e436fea7c5efbd0 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeAlreadyExistsException.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeAlreadyExistsException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.Map;
 
-import de.itvsh.ozg.pluto.common.errorhandling.FunctionalException;
+import de.ozgcloud.vorgang.common.errorhandling.FunctionalException;
 
 class ClientAttributeAlreadyExistsException extends FunctionalException {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeHasValueConstraint.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeHasValueConstraint.java
similarity index 87%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeHasValueConstraint.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeHasValueConstraint.java
index e454f02668c7e4171c8da9dedd6cc982339d51e6..c25307ca304c5887038d6fd7f0afa4abaf561a57 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeHasValueConstraint.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeHasValueConstraint.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import static java.lang.annotation.RetentionPolicy.*;
 
@@ -30,10 +30,10 @@ import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
-import javax.validation.Constraint;
-import javax.validation.ConstraintValidator;
-import javax.validation.ConstraintValidatorContext;
-import javax.validation.Payload;
+import jakarta.validation.Constraint;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import jakarta.validation.Payload;
 
 @Constraint(validatedBy = ClientAttributeHasValueValidator.class)
 @Target(ElementType.TYPE)
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeIdentificator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeIdentificator.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeIdentificator.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeIdentificator.java
index 6be4f8d0890642c7585cd954a4e45fa0e26faa8f..041e3259fc2a6933890e0d51a0f18865c452cb7e 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeIdentificator.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeIdentificator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
-
-import javax.validation.constraints.NotEmpty;
+package de.ozgcloud.vorgang.clientattribute;
 
+import jakarta.validation.constraints.NotEmpty;
 import lombok.Builder;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMap.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMap.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMap.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMap.java
index 1f245b967c520c45e5194b0e8a6f00209205f27b..5a79d440dd86866c4a3bd3920d3c6c6ac4a048ff 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMap.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.HashMap;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMapper.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMapper.java
index 565848c6cca69b64c12211d90b5553c8855b5d8b..094cbeb523b96ac760e08a9b2e01a370e17a37e4 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.List;
 import java.util.Objects;
@@ -34,10 +34,10 @@ import org.mapstruct.Mapping;
 import org.mapstruct.MappingConstants;
 import org.mapstruct.ValueMapping;
 
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttributeValue;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttributeValue.ValueCase;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcAccessPermission;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttribute;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttributeValue;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttributeValue.ValueCase;
 
 @Mapper
 public abstract class ClientAttributeMapper {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeNotExistingException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeNotExistingException.java
similarity index 87%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeNotExistingException.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeNotExistingException.java
index 7d08693c282db3917c6f3855b84405688b7a016a..192689828c513368d0d5c73c5cc3a2e812c8adc5 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeNotExistingException.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeNotExistingException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.Map;
 
-import de.itvsh.ozg.pluto.common.errorhandling.FunctionalException;
+import de.ozgcloud.vorgang.common.errorhandling.FunctionalException;
 
 class ClientAttributeNotExistingException extends FunctionalException {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeReadPermitted.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeReadPermitted.java
similarity index 85%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeReadPermitted.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeReadPermitted.java
index f917e03218572d88e69bb53eee1c2c67fd837a1b..388c216011cb6373abcccf011c1e68eb523b0d92 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeReadPermitted.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeReadPermitted.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.Objects;
 import java.util.function.Predicate;
@@ -29,8 +29,8 @@ import java.util.function.Predicate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttribute.AccessPermission;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute.AccessPermission;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
 
 @Component
 public class ClientAttributeReadPermitted implements Predicate<ClientAttribute> {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeRepository.java
similarity index 94%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeRepository.java
index 867a8d4a9cee3922ba63b580caba6c27fc8a034b..6b78663ea679d11f4bbec5367e3b69cf91fc1833 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import static org.springframework.data.mongodb.core.query.Criteria.*;
 import static org.springframework.data.mongodb.core.query.Query.*;
@@ -38,10 +38,10 @@ import org.springframework.stereotype.Repository;
 
 import com.mongodb.client.result.UpdateResult;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttribute.AccessPermission;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute.AccessPermission;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
 import lombok.NonNull;
 import lombok.extern.log4j.Log4j2;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeService.java
similarity index 93%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeService.java
index 2348180d1d8aa6c1b34389b9ae9600e0524c34f3..ea3f81dda53536c04ee92b2e30eafae2eee93fc5 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
-
-import javax.validation.Valid;
+package de.ozgcloud.vorgang.clientattribute;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
+import jakarta.validation.Valid;
 import lombok.NonNull;
 
 @Service
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributesMap.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributesMap.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributesMap.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributesMap.java
index 2adcd7be28604c6fade575065ba91bf4220ca857..7569dcb512d358814e9f2cdf282543902c8a7e55 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributesMap.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/ClientAttributesMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.HashMap;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeService.java
similarity index 80%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeService.java
index 68cb2643a6056c9c7e47f7ce478d2e0f90eb3634..a0f1f27e16229715e11c93fc74697f4ae3e8a6c4 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,20 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.Set;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceImplBase;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAcknowledgeResponse;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcDeleteClientAttributeRequest;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcSetClientAttributeRequest;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcUpdateClientAttributeRequest;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceImplBase;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcAcknowledgeResponse;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttribute;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcDeleteClientAttributeRequest;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcSetClientAttributeRequest;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcUpdateClientAttributeRequest;
 import io.grpc.stub.StreamObserver;
 import net.devh.boot.grpc.server.service.GrpcService;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandBodyMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandBodyMapper.java
similarity index 73%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandBodyMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandBodyMapper.java
index 88ec12d726e43b7e861ad71f6771b7524ba20143..69872354f57b19610be1327d12d3667f9aa6ade2 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandBodyMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandBodyMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,18 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
 import org.apache.commons.lang3.StringUtils;
 import org.mapstruct.Mapper;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandBody;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandBodyField;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandBody;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandBodyField;
 
 @Mapper
 public interface CommandBodyMapper {
@@ -46,16 +47,16 @@ public interface CommandBodyMapper {
 	default GrpcCommandBody mapToBody(Map<String, String> bodyMap) {
 		var builder = GrpcCommandBody.newBuilder();
 
-		bodyMap.entrySet().stream()
-				.map(entry -> GrpcCommandBodyField.newBuilder().setName(entry.getKey()).setValue(entry.getValue()).build())
-				.forEach(builder::addField);
+		bodyMap.entrySet().stream().map(this::buildBodyField).forEach(builder::addField);
 
 		return builder.build();
 	}
 
 	default List<GrpcCommandBodyField> mapToBodyFields(Map<String, String> bodyMap) {
-		return bodyMap.entrySet().stream()
-				.map(entry -> GrpcCommandBodyField.newBuilder().setName(entry.getKey()).setValue(entry.getValue()).build())
-				.collect(Collectors.toList());
+		return bodyMap.entrySet().stream().map(this::buildBodyField).toList();
+	}
+
+	private GrpcCommandBodyField buildBodyField(Entry<String, String> entry) {
+		return GrpcCommandBodyField.newBuilder().setName(entry.getKey()).setValue(entry.getValue()).build();
 	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandDeletionScheduler.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandDeletionScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec58ea7fd8faddf3f5c0f591493224cf573f0a4f
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandDeletionScheduler.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.command.Command;
+
+import lombok.extern.log4j.Log4j2;
+import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
+
+@Component
+@Profile("!itcase")
+@Log4j2
+public class CommandDeletionScheduler {
+
+	static final int CLEANUP_THRESHOLD_MINUTES = 30;
+
+	@Autowired
+	private CommandService commandService;
+
+	@Scheduled(fixedDelayString = "${ozgcloud.vorgang-manager.command.scheduler.fixedDelay:3600000}", //
+			initialDelayString = "${ozgcloud.vorgang-manager.command.scheduler.initialDelay:1800000}")
+	@SchedulerLock(name = "CommandDeletionScheduler")
+	void deleteCommands() {
+		try (var deleteVorgangCommands = commandService.findFinishedVorgangLoeschenCommandsOlderThen(getCleanupThreshold())) {
+			deleteVorgangCommands.map(Command::getVorgangId).distinct()
+					.forEach(commandService::deleteAllByVorgang);
+		} catch (RuntimeException e) {
+			LOG.error("Error deleting commands", e);
+		}
+	}
+
+	ZonedDateTime getCleanupThreshold() {
+		return ZonedDateTime.now(ZoneOffset.UTC).minusMinutes(CLEANUP_THRESHOLD_MINUTES);
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java
similarity index 70%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandEventListener.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java
index 27bf5db2bb9809b06699dc10a1da347359493a09..4d62cad074e7e8bc644ed62e885be84a1a317907 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Component;
 
+import de.ozgcloud.command.CommandExecutedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandRevokeFailedEvent;
+import de.ozgcloud.command.CommandRevokedEvent;
+
 @Component
 public class CommandEventListener {
 
@@ -35,6 +40,11 @@ public class CommandEventListener {
 
 	@EventListener
 	public void setStatusFinished(CommandExecutedEvent event) {
+		commandService.setCommandFinished(event.getSource(), event.getCreatedResource());
+	}
+
+	@EventListener
+	public void setStatusFinished(CommandRevokeFailedEvent event) {
 		commandService.setCommandFinished(event.getSource());
 	}
 
@@ -42,4 +52,9 @@ public class CommandEventListener {
 	public void setStatusError(CommandFailedEvent event) {
 		commandService.setCommandError(event.getSource(), event.getErrorMessage());
 	}
+
+	@EventListener
+	public void setCommandRevoked(CommandRevokedEvent event) {
+		commandService.setCommandRevoked(event.getSource().getId());
+	}
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
similarity index 63%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
index 8a4fea88d4a9c46fc145321dff7a0317922817d2..046aa01ccbf921a87e6d0ec79301404c65f3b8dd 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.springframework.data.mongodb.core.query.Criteria.*;
 import static org.springframework.data.mongodb.core.query.Query.*;
@@ -29,7 +29,9 @@ import static org.springframework.data.mongodb.core.query.Query.*;
 import java.time.ZonedDateTime;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
@@ -38,6 +40,9 @@ import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.stereotype.Repository;
 
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandStatus;
+
 @Repository
 class CommandRepository {
 
@@ -47,6 +52,11 @@ class CommandRepository {
 	private static final String MONGODB_RELATION_VERSION = "relationVersion";
 	private static final String MONGODB_ERROR_MSG = "errorMessage";
 	private static final String MONGODB_ORDER = "order";
+	private static final String MONGODB_PREVIOUS_STATE = "previousState";
+	private static final String MONGODB_CREATED_AT = "createdAt";
+	private static final String MONGODB_CREATED_BY = "createdBy";
+	private static final String MONGODB_ASSIGNED_TO = "body.assignedTo";
+	private static final String MONGODB_CREATED_RESOURCE = "createdResource";
 
 	@Autowired
 	private MongoOperations mongoOperations;
@@ -56,9 +66,17 @@ class CommandRepository {
 	}
 
 	void finishCommand(String commandId) {
+		finishCommand(commandId, new Update());
+	}
+
+	void finishCommand(String commandId, String createdResource) {
+		finishCommand(commandId, new Update().set(MONGODB_CREATED_RESOURCE, createdResource));
+	}
+
+	private void finishCommand(String commandId, Update update) {
 		mongoOperations.updateFirst(
 				queryById(commandId),
-				new Update().set(MONGODB_STATUS, CommandStatus.FINISHED).set(MONGODB_FINISHED_AT, ZonedDateTime.now()),
+				update.set(MONGODB_STATUS, CommandStatus.FINISHED).set(MONGODB_FINISHED_AT, ZonedDateTime.now()),
 				Command.class);
 	}
 
@@ -92,7 +110,6 @@ class CommandRepository {
 	}
 
 	Optional<Command> getById(String commandId) {
-
 		return Optional.ofNullable(mongoOperations.findById(commandId, Command.class));
 	}
 
@@ -124,4 +141,41 @@ class CommandRepository {
 
 		return result;
 	}
+
+	public Stream<Command> findCommands(Order order, CommandStatus status, ZonedDateTime createdBefore) {
+		return mongoOperations.stream(buildCommandsQuery(order, status, createdBefore), Command.class);
+	}
+
+	private Query buildCommandsQuery(Order order, CommandStatus status, ZonedDateTime createdBefore) {
+		var result = query(where(MONGODB_ORDER).is(order.name()).and(MONGODB_STATUS).is(status));
+		result.addCriteria(new Criteria(MONGODB_CREATED_AT).lte(createdBefore));
+		return result;
+	}
+
+	public void patch(String commandId, Map<String, Object> previousState) {
+		mongoOperations.updateFirst(
+				queryById(commandId),
+				buildItemPatchUpdate(previousState),
+				Command.class);
+	}
+
+	private Update buildItemPatchUpdate(Map<String, Object> valueMap) {
+		Update update = new Update();
+		for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
+			update.set("%s.%s".formatted(MONGODB_PREVIOUS_STATE, entry.getKey()), entry.getValue());
+		}
+		return update;
+	}
+
+	public void deleteAllByVorgang(String vorgangId) {
+		mongoOperations.remove(query(where(PersistedCommand.FIELD_VORGANG_ID).is(vorgangId)), PersistedCommand.COLLECTION_NAME);
+	}
+
+	public boolean existsCommandWithUserId(String userId) {
+		return mongoOperations.exists(query(buildCreatedByOrAssignedToCriteria(userId)), PersistedCommand.COLLECTION_NAME);
+	}
+
+	Criteria buildCreatedByOrAssignedToCriteria(String userId) {
+		return new Criteria().orOperator(where(MONGODB_CREATED_BY).is(userId), where(MONGODB_ASSIGNED_TO).is(userId));
+	}
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandResponse.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandResponse.java
similarity index 78%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandResponse.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandResponse.java
index 0cd6c6f6945c0e7ede22297b70dd34ee557de90d..2db13dbc59da0973133be049355d164b9e377252 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandResponse.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandResponse.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.util.List;
 
+import de.ozgcloud.command.Command;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Singular;
@@ -33,9 +34,9 @@ import lombok.Singular;
 @Getter
 public class CommandResponse {
 
-	public static final String MESSAGE_CODE_COMMAND_VORGANG_ID_NOT_FOUND = "de.itvsh.ozg.pluto.vorgang.command.error.invalid-vorgang-id";
-	public static final String MESSAGE_CODE_COMMAND_VORGANG_DOCUMENT_VERSION_IS_OUTDATED = "de.itvsh.ozg.pluto.vorgang.command.error.documentversion-outdated";
-	public static final String MESSAGE_CODE_COMMAND_VORGANG_INVALID_DOCUMENT_STATUS = "de.itvsh.ozg.pluto.vorgang.command.error.documentstatus-is-invalid";
+	public static final String MESSAGE_CODE_COMMAND_VORGANG_ID_NOT_FOUND = "de.ozgcloud.vorgang.vorgang.command.error.invalid-vorgang-id";
+	public static final String MESSAGE_CODE_COMMAND_VORGANG_DOCUMENT_VERSION_IS_OUTDATED = "de.ozgcloud.vorgang.vorgang.command.error.documentversion-outdated";
+	public static final String MESSAGE_CODE_COMMAND_VORGANG_INVALID_DOCUMENT_STATUS = "de.ozgcloud.vorgang.vorgang.command.error.documentstatus-is-invalid";
 
 	public enum ResponseCode {
 		OK, PENDING, ERROR, CONFLICT;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
similarity index 63%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
index e818185b227f4db06c4b89394c85299d8974242e..45a86ca09dc9abefa0a09adedf9059fe991c5bd3 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CommandService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,26 +21,38 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.time.ZonedDateTime;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.stream.Stream;
 
+import org.apache.commons.collections4.MapUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUser;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.callcontext.CallContext;
+import de.ozgcloud.vorgang.callcontext.CallContextUser;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.callcontext.User;
+import lombok.NonNull;
+import lombok.extern.log4j.Log4j2;
 
 @Service
 @Validated
+@Log4j2
 public class CommandService {
 
 	@Autowired
@@ -52,18 +64,13 @@ public class CommandService {
 	private CurrentUserService userService;
 
 	public Command createCommand(CreateCommandRequest request) {
-		return createCommand(request, Optional.empty());
-	}
-
-	public Command createCommand(CreateCommandRequest request, Optional<Status> currentVorgangStatus) {
-		var persisted = saveCommand(buildCommand(request, currentVorgangStatus));
+		var persisted = saveCommand(buildCommand(request));
 		publisher.publishEvent(new CommandCreatedEvent(persisted));
 		return persisted;
 	}
 
-	private Command buildCommand(CreateCommandRequest request, Optional<Status> currentVorgangStatus) {
+	private Command buildCommand(CreateCommandRequest request) {
 		var builder = PersistedCommand.builder()
-				// TODO id von Datenbank vergeben lassen
 				.id(UUID.randomUUID().toString())
 				.vorgangId(request.getVorgangId())
 				.order(request.getOrder())
@@ -75,8 +82,6 @@ public class CommandService {
 				.body(request.getBody())
 				.bodyObject(request.getBodyObject());
 
-		currentVorgangStatus.ifPresent(builder::previousStatus);
-
 		builder = addUserIfExists(builder, Optional.ofNullable(request.getCallContext()).map(CallContext::getUser), userService.findUser());
 		return builder.build();
 	}
@@ -104,10 +109,18 @@ public class CommandService {
 		return repository.getById(commandId);
 	}
 
+	public Stream<Command> findFinishedVorgangLoeschenCommandsOlderThen(@NonNull ZonedDateTime createdAfter) {
+		return repository.findCommands(Order.VORGANG_LOESCHEN, CommandStatus.FINISHED, createdAfter);
+	}
+
 	public void setCommandFinished(String commandId) {
 		repository.finishCommand(commandId);
 	}
 
+	public void setCommandFinished(String commandId, String createdResource) {
+		repository.finishCommand(commandId, createdResource);
+	}
+
 	public void setCommandError(String id, String errorMessage) {
 		repository.setErrorMessage(id, errorMessage);
 	}
@@ -116,8 +129,27 @@ public class CommandService {
 		updateCommandStatus(commandId, CommandStatus.REVOKED);
 	}
 
-	public void setCommandRevokePending(String commandId) {
+	public void setCommandRevokePending(final String commandId) {
 		updateCommandStatus(commandId, CommandStatus.REVOKE_PENDING);
+
+		publishRevokeCommandEvent(commandId);
+	}
+
+	void publishRevokeCommandEvent(final String commandId) {
+		var commandOptional = repository.getById(commandId);
+		commandOptional.ifPresentOrElse(command -> {
+			if (MapUtils.isEmpty(((PersistedCommand) command).getPreviousState())) {
+				handleError(commandId, "Command %s can not be revoked because it has no previous state.");
+			}
+			publisher.publishEvent(new RevokeCommandEvent(command));
+		}, () -> handleError(commandId, "No Command with id %s found."));
+	}
+
+	private void handleError(String commandId, String messageTemplate) {
+		var message = messageTemplate.formatted(commandId);
+		LOG.error(message);
+		publisher.publishEvent(new CommandFailedEvent(commandId, message));
+		throw new TechnicalException(message);
 	}
 
 	void updateCommandStatus(String commandId, CommandStatus status) {
@@ -136,4 +168,15 @@ public class CommandService {
 		return repository.findCommands(vorgangId, status, order).stream();
 	}
 
+	public void setPreviousState(String commandId, Map<String, Object> previousState) {
+		repository.patch(commandId, previousState);
+	}
+
+	public void deleteAllByVorgang(String vorgangId) {
+		repository.deleteAllByVorgang(vorgangId);
+	}
+
+	public boolean existsCommandWithUserId(String userId) {
+		return repository.existsCommandWithUserId(userId);
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CreateCommandRequest.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CreateCommandRequest.java
similarity index 81%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CreateCommandRequest.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CreateCommandRequest.java
index f9526cc77d498a6d90744cbe1bff6eaf2c2f7639..dacccf537d2543163054ea60ca636d539a39a5ce 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/CreateCommandRequest.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CreateCommandRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.util.Map;
 
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
 
-import de.itvsh.ozg.pluto.vorgang.redirect.RedirectRequest;
+import de.ozgcloud.vorgang.callcontext.CallContext;
+import de.ozgcloud.vorgang.vorgang.redirect.RedirectRequest;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.ToString;
@@ -44,14 +45,15 @@ public class CreateCommandRequest {
 
 	@NotNull
 	private String vorgangId;
+
 	@NotNull
 	private String relationId;
-	@NotNull
 	private Long relationVersion;
 
 	@NotNull
 	private String order;
 
+	// TODO migrate to bodyObject
 	private RedirectRequest redirectRequest;
 
 	// TODO migrate to bodyObject
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandMapper.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandMapper.java
index 3c79f047e770bf00dad9f9efc2cd04a4d8bf680d..38b96bb7c39ac4ca91b7c9b8b449705bc5709e05 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import org.apache.commons.lang3.StringUtils;
 import org.mapstruct.CollectionMappingStrategy;
@@ -30,9 +30,10 @@ import org.mapstruct.Mapping;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommand;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
 
 @Mapper(uses = { CommandBodyMapper.class, GrpcObjectMapper.class }, //
 		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandResponseMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandResponseMapper.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandResponseMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandResponseMapper.java
index ab62c76636f79220ddca0cdd7143f8e2d5c31648..e5e368211596a4e85bbc66dc2e35c8b4d49a7bb1 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandResponseMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandResponseMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import org.mapstruct.CollectionMappingStrategy;
 import org.mapstruct.Mapper;
@@ -29,8 +29,8 @@ import org.mapstruct.Mapping;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
 
 @Mapper(uses = CommandBodyMapper.class, //
 		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandService.java
similarity index 66%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandService.java
index cd8ac48c89c61dda9c6d4656f7f471c233ce1dda..d2294fa9e83d2767fa432440cb81e4a29e94007e 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCommandService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCommandService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,36 +21,44 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
+
+import static org.apache.commons.lang3.StringUtils.*;
 
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Stream;
 
 import org.springframework.beans.factory.annotation.Autowired;
-
-import de.itvsh.ozg.pluto.command.CommandResponse.ResponseCode;
-import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.command.CommandServiceGrpc.CommandServiceImplBase;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandsResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcExistsPendingCommandsRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcExistsPendingCommandsResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcFindCommandsRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
-import de.itvsh.ozg.pluto.grpc.command.GrpcRevokeCommandRequest;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.command.CommandResponse.ResponseCode;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.command.CommandServiceGrpc.CommandServiceImplBase;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommand;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandsResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcEmpty;
+import de.ozgcloud.vorgang.grpc.command.GrpcExistsPendingCommandsRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcExistsPendingCommandsResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcFindCommandsRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetPendingCommandsRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetPendingCommandsResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.grpc.command.GrpcRevokeCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcSetCommandExecutedRequest;
 import io.grpc.stub.StreamObserver;
+import lombok.extern.log4j.Log4j2;
 import net.devh.boot.grpc.server.service.GrpcService;
 
+@Log4j2
 @GrpcService
 public class GrpcCommandService extends CommandServiceImplBase {
 
@@ -58,14 +66,16 @@ public class GrpcCommandService extends CommandServiceImplBase {
 	private GrpcCreateCommandRequestMapper createCommandRequestMapper;
 	@Autowired
 	private CommandService commandService;
-	@Autowired
-	private VorgangService vorgangService;
+
 	@Autowired
 	private GrpcCommandResponseMapper commandResponseMapper;
 	@Autowired
 	private GrpcCommandMapper grpcCommandMapper;
+
 	@Autowired
 	private PolicyService policyService;
+	@Autowired
+	private ApplicationEventPublisher publisher;
 
 	@Override
 	public void createCommand(GrpcCreateCommandRequest request, StreamObserver<GrpcCommandResponse> responseObserver) {
@@ -73,36 +83,17 @@ public class GrpcCommandService extends CommandServiceImplBase {
 
 		var mappedRequest = createCommandRequestMapper.fromGrpc(request);
 
-		var command = commandService.createCommand(mappedRequest, getActualStatus(mappedRequest));
-
-		executeOrder(command);
+		var command = commandService.createCommand(mappedRequest);
 
 		responseObserver.onNext(mapToGrpcResponse(getCommand(command.getId())));
 		responseObserver.onCompleted();
 	}
 
-	private Optional<Status> getActualStatus(CreateCommandRequest request) {
-		if (isStatusChangeOrder(request.getOrder())) {
-			return Optional.of(getVorgang(request.getRelationId()).getStatus());
-		} else {
-			return Optional.empty();
-		}
-	}
-
+	// TODO check - is this function still in use?
 	boolean isStatusChangeOrder(String order) {
 		return order.startsWith("VORGANG");
 	}
 
-	private Vorgang getVorgang(String vorgangId) {
-		return vorgangService.getById(vorgangId);
-	}
-
-	// TODO implement event/listener system to execute (status) order
-	void executeOrder(Command command) {
-		StatusOrder.getOrderMethod(command.getOrder())
-				.ifPresent(orderMethod -> orderMethod.executeOrder(vorgangService, command));
-	}
-
 	@Override
 	public void getCommand(GrpcGetCommandRequest request, StreamObserver<GrpcCommand> responseObserver) {
 		policyService.checkPermissionByCommand(request.getId());
@@ -118,22 +109,17 @@ public class GrpcCommandService extends CommandServiceImplBase {
 		policyService.checkPermissionByCommand(request.getId());
 
 		String commandId = request.getId();
-		commandService.setCommandRevokePending(commandId);
-
-		proceedRevokeCommand(commandId);
-
-		Command updatedCommand = getCommand(commandId);
-
-		responseObserver.onNext(mapToGrpcResponse(updatedCommand));
-		responseObserver.onCompleted();
-	}
 
-	void proceedRevokeCommand(String commandId) {
-		PersistedCommand command = (PersistedCommand) getCommand(commandId);
+		try {
+			commandService.setCommandRevokePending(commandId);
 
-		vorgangService.revokeStatusChange(command);
+			Command updatedCommand = getCommand(commandId);
 
-		commandService.setCommandRevoked(commandId);
+			responseObserver.onNext(mapToGrpcResponse(updatedCommand));
+			responseObserver.onCompleted();
+		} catch (TechnicalException e) {
+			responseObserver.onError(e);
+		}
 	}
 
 	Command getCommand(String commandId) {
@@ -193,4 +179,15 @@ public class GrpcCommandService extends CommandServiceImplBase {
 	private GrpcCommandsResponse buildCommandsResponse(Stream<Command> commands) {
 		return GrpcCommandsResponse.newBuilder().addAllCommand(commands.map(grpcCommandMapper::toGrpc).toList()).build();
 	}
+
+	@Override
+	public void setCommandExecuted(GrpcSetCommandExecutedRequest request, StreamObserver<GrpcEmpty> responseObserver) {
+		commandService.findCommand(request.getCommandId())
+				.map(command -> new CommandExecutedEvent(command, trimToNull(request.getCreatedResource())))
+				.ifPresentOrElse(publisher::publishEvent,
+						() -> LOG.warn("Command with ID '%s' not found. Cannot mark as executed.".formatted(request.getCommandId())));
+
+		responseObserver.onNext(GrpcEmpty.newBuilder().build());
+		responseObserver.onCompleted();
+	}
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestMapper.java
similarity index 82%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestMapper.java
index 223984220cf6ca65eb0cf04f1ce86d640c575269..34a361a3edaa15b248d546e59a2754efb68d72cc 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.time.ZonedDateTime;
 
@@ -35,14 +35,16 @@ import org.mapstruct.NullValuePropertyMappingStrategy;
 import org.mapstruct.ValueMapping;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.files.FileIdMapper;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCallContext;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
-import de.itvsh.ozg.pluto.grpc.command.GrpcUser;
-import de.itvsh.ozg.pluto.vorgang.redirect.RedirectRequestMapper;
+import de.ozgcloud.vorgang.callcontext.CallContext;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.callcontext.User;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.files.FileIdMapper;
+import de.ozgcloud.vorgang.grpc.command.GrpcCallContext;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.grpc.command.GrpcUser;
+import de.ozgcloud.vorgang.vorgang.redirect.RedirectRequestMapper;
 
 @Mapper(uses = { RedirectRequestMapper.class, CommandBodyMapper.class, FileIdMapper.class, GrpcObjectMapper.class }, //
 		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/Order.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/Order.java
similarity index 87%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/Order.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/Order.java
index fc04cd334725b90fba1364ce6bd74e0c3a097c02..e6d5a01d9c0e7ff0fffdc4865867561a7653db20 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/Order.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/Order.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import org.apache.commons.lang3.StringUtils;
 
@@ -35,9 +35,13 @@ public enum Order {
 	VORGANG_ZURUECKSTELLEN,
 	VORGANG_ABSCHLIESSEN,
 	VORGANG_WIEDEREROEFFNEN,
+	VORGANG_ZUM_LOESCHEN_MARKIEREN,
+	VORGANG_LOESCHEN,
 
 	ASSIGN_USER,
 
+	SET_AKTENZEICHEN,
+
 	REDIRECT_VORGANG,
 	FORWARD_SUCCESSFULL,
 	FORWARD_FAILED,
@@ -55,7 +59,8 @@ public enum Order {
 
 	CREATE_ATTACHED_ITEM,
 	UPDATE_ATTACHED_ITEM,
-	PATCH_ATTACHED_ITEM;
+	PATCH_ATTACHED_ITEM,
+	DELETE_ATTACHED_ITEM;
 
 	public boolean isMeant(String orderString) {
 		return StringUtils.equals(name(), orderString);
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistPostfachNachrichtByCommandService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistPostfachNachrichtByCommandService.java
new file mode 100644
index 0000000000000000000000000000000000000000..5795423a5b4f1d1d4a2bcda9c367b2edbcf95c67
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistPostfachNachrichtByCommandService.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URLConnection;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.entity.ContentType;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.postfach.AttachmentFile;
+import de.ozgcloud.nachrichten.postfach.PersistPostfachNachrichtService;
+import de.ozgcloud.nachrichten.postfach.PostfachAddress;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.StringBasedIdentifier;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemMapper;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemService;
+import de.ozgcloud.vorgang.callcontext.CallContext;
+import de.ozgcloud.vorgang.callcontext.User;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.files.OzgFile;
+import de.ozgcloud.vorgang.files.UploadedFilesReference;
+
+import jakarta.activation.MimetypesFileTypeMap;
+
+import lombok.extern.log4j.Log4j2;
+
+/**
+ * @deprecated Temporally replacement for using GRPC Api by MailService
+ */
+@Deprecated
+@Service
+@Log4j2
+class PersistPostfachNachrichtByCommandService implements PersistPostfachNachrichtService {
+
+	static final String CLIENT = "OzgCloud_NachrichtenManager";
+	static final String ITEM_NAME = "PostfachMail";
+	static final String ATTACHMENT_NAME = "PostfachAttachment";
+
+	@Autowired
+	private CommandService service;
+	@Autowired
+	private VorgangAttachedItemService attachedItemService;
+	@Autowired
+	private FileService fileService;
+
+	@Override
+	public void persistNachricht(Optional<String> userId, PostfachNachricht nachricht) {
+		var builder = CreateCommandRequest.builder()
+				.callContext(buildCallContext(userId))
+				.vorgangId(nachricht.getVorgangId());
+
+		var request = StringUtils.isBlank(nachricht.getId()) ? buildPersistCommand(builder, nachricht) : buildUpdateCommand(builder, nachricht);
+
+		service.createCommand(request);
+	}
+
+	CreateCommandRequest buildPersistCommand(CreateCommandRequest.CreateCommandRequestBuilder builder, PostfachNachricht nachricht) {
+		return builder.order(Order.CREATE_ATTACHED_ITEM.name())
+				.relationId(nachricht.getVorgangId())
+				.bodyObject(buildItem(nachricht)).build();
+	}
+
+	CreateCommandRequest buildUpdateCommand(CreateCommandRequest.CreateCommandRequestBuilder builder, PostfachNachricht nachricht) {
+		return builder.order(Order.UPDATE_ATTACHED_ITEM.name())
+				.relationId(nachricht.getId())
+				.bodyObject(buildUpdateItem(nachricht)).build();
+	}
+
+	private CallContext buildCallContext(Optional<String> userId) {
+		var builder = CallContext.builder();
+		userId.map(id -> User.builder().id(id).build()).ifPresent(builder::user);
+
+		return builder.build();
+	}
+
+	private Map<String, Object> buildItem(PostfachNachricht nachricht) {
+		return Map.of(
+				VorgangAttachedItemMapper.PROPERTY_CLIENT, CLIENT,
+				VorgangAttachedItemMapper.PROPERTY_VORGANG_ID, nachricht.getVorgangId(),
+				VorgangAttachedItemMapper.PROPERTY_ITEM_NAME, ITEM_NAME,
+				VorgangAttachedItemMapper.PROPERTY_ITEM, buildNachrichtMap(nachricht));
+
+	}
+
+	private Map<String, Object> buildUpdateItem(PostfachNachricht nachricht) {
+		return Map.of(
+				VorgangAttachedItemMapper.PROPERTY_CLIENT, CLIENT,
+				VorgangAttachedItemMapper.PROPERTY_ITEM, buildNachrichtMap(nachricht));
+
+	}
+
+	Map<String, Object> buildNachrichtMap(PostfachNachricht nachricht) {
+		var result = new HashMap<>(Map.of(
+				PostfachNachricht.FIELD_VORGANG_ID, nachricht.getVorgangId(),
+				PostfachNachricht.FIELD_CREATED_AT, nachricht.getCreatedAt().format(DateTimeFormatter.ISO_DATE_TIME),
+				PostfachNachricht.FIELD_DIRECTION, nachricht.getDirection().name(),
+				PostfachNachricht.FIELD_REPLY_OPTION, nachricht.getReplyOption().name(),
+				PostfachNachricht.FIELD_SUBJECT, nachricht.getSubject(),
+				PostfachNachricht.FIELD_MAIL_BODY, nachricht.getMailBody(),
+				PostfachNachricht.FIELD_ATTACHMENTS, nachricht.getAttachments()));
+
+		putIfNonNull(result, PostfachNachricht.FIELD_POSTFACH_ID, nachricht.getPostfachId());
+		putIfNonNull(result, PostfachNachricht.FIELD_MESSAGE_ID, nachricht.getMessageId());
+		putIfNonNull(result, PostfachNachricht.FIELD_CREATED_BY, nachricht.getCreatedBy());
+		putIfNonNull(result, PostfachNachricht.FIELD_SENT_SUCCESSFUL, nachricht.getSentSuccessful());
+		putIfNonNull(result, PostfachNachricht.FIELD_MESSAGE_CODE, nachricht.getMessageCode());
+		putDateIfNonNull(result, PostfachNachricht.FIELD_SENT_AT, nachricht.getSentAt());
+
+		Optional.ofNullable(nachricht.getPostfachAddress()).map(this::buildPostfachAddressMap)
+				.ifPresent(postfachMaiMap -> result.put(PostfachNachricht.POSTFACH_ADDRESS_FIELD, postfachMaiMap));
+
+		return Collections.unmodifiableMap(result);
+	}
+
+	private Map<String, Object> putIfNonNull(Map<String, Object> mapIn, String key, Object value) {
+		if (Objects.nonNull(value)) {
+			mapIn.put(key, value);
+		}
+		return mapIn;
+	}
+
+	private Map<String, Object> putDateIfNonNull(Map<String, Object> mapIn, String key, Object value) {
+		if (Objects.nonNull(value)) {
+			mapIn.put(key, ((ZonedDateTime) value).format(DateTimeFormatter.ISO_DATE_TIME));
+		}
+		return mapIn;
+	}
+
+	private Map<String, Object> buildPostfachAddressMap(PostfachAddress postfachAddress) {
+		var resultMap = new HashMap<String, Object>();
+		resultMap.put(PostfachAddress.IDENTIFIER_FIELD, buildPostfachAddressIdentifierMap(postfachAddress));
+		resultMap.put(PostfachAddress.VERSION_FIELD, postfachAddress.getVersion());
+		resultMap.put(PostfachAddress.TYPE_FIELD, postfachAddress.getType());
+		Optional.ofNullable(postfachAddress.getServiceKontoType()).ifPresentOrElse(
+				serviceKontoType -> resultMap.put(PostfachAddress.SERVICEKONTO_TYPE_FIELD, serviceKontoType),
+				() -> LOG.warn("ServiceKontoType is null"));
+		return Collections.unmodifiableMap(resultMap);
+	}
+
+	private Map<String, Object> buildPostfachAddressIdentifierMap(PostfachAddress postfachAddress) {
+		var identifier = (StringBasedIdentifier) postfachAddress.getIdentifier();
+		return Map.of(PostfachNachricht.FIELD_POSTFACH_ID, identifier.getPostfachId());
+	}
+
+	@Override
+	public Optional<Map<String, Object>> findById(String postfachNachrichtId) {
+		return attachedItemService.findById(postfachNachrichtId).map(VorgangAttachedItem::getItem);
+	}
+
+	@Override
+	public Stream<Map<String, Object>> findByVorgangAsMap(String vorgangId) {
+		return attachedItemService.find(vorgangId, Optional.of(CLIENT), Optional.of(ITEM_NAME)).map(VorgangAttachedItem::getItem);
+	}
+
+	@Override
+	public void patch(String postfachNachrichtId, Map<String, Object> propertyMap) {
+		attachedItemService.forcePatch(postfachNachrichtId, propertyMap);
+	}
+
+	@Override
+	public Map<String, Object> getById(String postfachNachrichtId) {
+		return attachedItemService.getById(postfachNachrichtId).getItem();
+	}
+
+	@Override
+	public String persistAttachment(String vorgangId, AttachmentFile attachment) {
+		var contentType = getTypeByFile(attachment);
+		try (var content = attachment.getContent()) {
+			var decContent = Base64.getDecoder().decode(content.readAllBytes());
+
+			return fileService.uploadFileStream(
+					createUploadedFilesReference(vorgangId),
+					createOzgFile(attachment.getName(), contentType, decContent.length),
+					Optional.empty(),
+					new ByteArrayInputStream(decContent)).get(10, TimeUnit.MINUTES).toString();
+		} catch (ExecutionException | TimeoutException e) {
+			throw new TechnicalException(e.getMessage(), e);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+			throw new TechnicalException(e.getMessage(), e);
+		} catch (IOException e) {
+			throw new TechnicalException("Can not read attached file", e);
+		}
+	}
+
+	UploadedFilesReference createUploadedFilesReference(String vorgangId) {
+		return UploadedFilesReference.builder().vorgangId(vorgangId).client(CLIENT).name(ATTACHMENT_NAME).build();
+	}
+
+	OzgFile createOzgFile(String fileName, String contentType, long size) {
+		return OzgFile.builder().name(fileName).contentType(contentType).size(size).build();
+	}
+
+	String getTypeByFile(AttachmentFile attachmentFile) {
+		var fileNameMap = URLConnection.getFileNameMap();
+
+		return Optional.ofNullable(fileNameMap.getContentTypeFor(attachmentFile.getName())).orElseGet(() -> getTypeByContent(attachmentFile));
+	}
+
+	private String getTypeByContent(AttachmentFile attachmentFile) {
+		try (var contentStream = attachmentFile.getContent()) {
+			return Optional.ofNullable(URLConnection.guessContentTypeFromStream(contentStream))
+					.orElseGet(() -> getByMimeTypes(attachmentFile.getName()));
+		} catch (IOException e) {
+			LOG.warn("IO-Exception while guessing content type", e);
+		}
+		return ContentType.APPLICATION_OCTET_STREAM.toString();
+	}
+
+	// uses map file: src/main/resources/mime.types
+	private String getByMimeTypes(String fileName) {
+		MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
+
+		return fileTypeMap.getContentType(fileName);
+	}
+
+}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/PersistedCommand.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistedCommand.java
similarity index 84%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/command/PersistedCommand.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistedCommand.java
index 6c284a8ee8e63ee3ec25519f0346ef0e526ebe23..02a6396141f9dbab9cbfc610f682c7277cebecde 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/command/PersistedCommand.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/PersistedCommand.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.time.ZonedDateTime;
 import java.util.Map;
@@ -30,8 +30,9 @@ import org.springframework.data.annotation.Id;
 import org.springframework.data.annotation.TypeAlias;
 import org.springframework.data.mongodb.core.mapping.Document;
 
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.redirect.RedirectRequest;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.vorgang.vorgang.redirect.RedirectRequest;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Setter;
@@ -62,15 +63,19 @@ public class PersistedCommand implements Command {
 	private CommandStatus status;
 
 	private String relationId;
-	private long relationVersion;
+	private Long relationVersion;
 
 	private String order;
 
-	private Status previousStatus;
 	private String errorMessage;
 
 	private RedirectRequest redirectRequest;
 
 	private Map<String, String> body;
 	private Map<String, Object> bodyObject;
+
+	@Setter
+	private Map<String, Object> previousState;
+
+	private String createdResource;
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/CustomConverters.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/CustomConverters.java
similarity index 89%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/CustomConverters.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/CustomConverters.java
index 32935637c19c20482d07b97c7759bcfd0956c89c..ff27502b569ea176a6907d88fa3abc6dc4765ed4 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/CustomConverters.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/CustomConverters.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.converter;
+package de.ozgcloud.vorgang.common.converter;
 
 import java.util.Arrays;
 
@@ -33,7 +33,7 @@ import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
 public class CustomConverters {
 
 	@Bean
-	public MongoCustomConversions mongoCustomConversions() {
+	MongoCustomConversions mongoCustomConversions() {
 
 		return new MongoCustomConversions(
 				Arrays.asList(
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/FileIdConverter.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/FileIdConverter.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/FileIdConverter.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/FileIdConverter.java
index dec0f50c9024ac918b5f17756c354f8ce7c2f1bb..7df3cc470753e122ae2ecccd1019462dccc128e8 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/FileIdConverter.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/FileIdConverter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.converter;
+package de.ozgcloud.vorgang.common.converter;
 
 import java.util.Optional;
 
@@ -30,7 +30,7 @@ import org.springframework.data.convert.ReadingConverter;
 import org.springframework.data.convert.WritingConverter;
 import org.springframework.stereotype.Component;
 
-import de.itvsh.ozg.pluto.files.FileId;
+import de.ozgcloud.vorgang.files.FileId;
 
 @Component
 @ReadingConverter
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeReadConverter.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeReadConverter.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeReadConverter.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeReadConverter.java
index 1ffd071632acedac84fbb1f27f998d577188f2fe..e7ba0894a5594de71b9d757c66f4b15836de04e9 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeReadConverter.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeReadConverter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.converter;
+package de.ozgcloud.vorgang.common.converter;
 
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeWriteConverter.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeWriteConverter.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeWriteConverter.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeWriteConverter.java
index 99dad09b77150c0557eb8f408cb6f962313b1240..f77492da1e348a9f2869f3e4d4a5decf8ee56f8a 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeWriteConverter.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeWriteConverter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.converter;
+package de.ozgcloud.vorgang.common.converter;
 
 import java.time.ZonedDateTime;
 import java.util.Date;
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CollisionVerifier.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CollisionVerifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..2da472fa32d2d7620bdcb558df5f2ca89beda3e8
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CollisionVerifier.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.db;
+
+import java.util.ConcurrentModificationException;
+
+import com.mongodb.Function;
+import com.mongodb.client.result.DeleteResult;
+import com.mongodb.client.result.UpdateResult;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class CollisionVerifier {
+
+	private final Function<String, Boolean> doEntryWithIdExist;
+
+	public void verify(DeleteResult result, String entryId) {
+		if (isConcurrentModification(result) && doEntryWithIdExist(entryId)) {
+			throw new ConcurrentModificationException();
+		}
+	}
+
+	public void verify(UpdateResult result, String entryId) {
+		if (isConcurrentModification(result) && doEntryWithIdExist(entryId)) {
+			throw new ConcurrentModificationException();
+		}
+	}
+
+	boolean doEntryWithIdExist(String entryId) {
+		return doEntryWithIdExist.apply(entryId);
+	}
+
+	boolean isConcurrentModification(DeleteResult result) {
+		return result.wasAcknowledged() && result.getDeletedCount() <= 0;
+	}
+
+	boolean isConcurrentModification(UpdateResult result) {
+		return result.getModifiedCount() <= 0 && result.getMatchedCount() <= 0;
+	}
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/CriteriaUtil.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CriteriaUtil.java
similarity index 51%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/CriteriaUtil.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CriteriaUtil.java
index 5320f1c3f0299d06daa9010c8f1f513f0d14a42d..ee28acb14422f8fcd5dcfbb74e905db69323967b 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/CriteriaUtil.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/db/CriteriaUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,70 +21,83 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.common.db;
 
-import static de.itvsh.ozg.pluto.vorgang.Vorgang.*;
+import static de.ozgcloud.vorgang.vorgang.Vorgang.*;
 
 import java.time.LocalDate;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.data.mongodb.core.query.Criteria;
 
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 
-class CriteriaUtil { // NOSONAR
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class CriteriaUtil {
 
 	private static final String CASE_INSENSITIV = "i";
-	static final String CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST = "nextWiedervorlageFrist";
-	static final String CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY = String.format("%s.%s.%s", Vorgang.FIELD_CLIENT_ATTRIBUTES,
-			VorgangHeaderRepositoryImpl.DEFAULT_CLIENT,
-			CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST);
-	static final String CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY = CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY + ".value";
 
-	static Criteria isId(String id) {
-		return new Criteria(Vorgang.MONGODB_FIELDNAME_ID).is(id);
+	public static final String DEFAULT_CLIENT = "Alfa";
+	public static final String CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST = "nextWiedervorlageFrist";
+	public static final String CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY = String.format("%s.%s.%s", Vorgang.FIELD_CLIENT_ATTRIBUTES,
+			DEFAULT_CLIENT, CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST);
+	public static final String CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY = CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY + ".value";
+
+	public static Criteria isId(String id) {
+		return new Criteria(MONGODB_FIELDNAME_ID).is(id);
+	}
+
+	public static Criteria isNotDeleted() {
+		return new Criteria(MONGODB_FIELDNAME_STATUS).ne(Vorgang.Status.DELETED);
 	}
 
-	static Criteria inOrganisationseinheitenIds(List<String> ids) {
-		return new Criteria(Vorgang.FIELD_ORGANISATIONSEINHEIT).in(ids);
+	public static Criteria inOrganisationseinheitenIds(Collection<String> ids) {
+		return new Criteria(FIELD_ORGANISATIONSEINHEIT).in(ids);
 	}
 
-	static Criteria vorgangInCreation() {
+	public static Criteria vorgangNotInCreation() {
 		return new Criteria(MONGODB_FIELDNAME_IN_CREATION).is(false);
 	}
 
-	static Criteria vorgangIsAssignedTo(String assignedTo) {
+	public static Criteria vorgangIsAssignedTo(String assignedTo) {
 		return new Criteria(MONGODB_FIELDNAME_ASSIGNED_TO).is(assignedTo);
 	}
 
-	static Criteria vorgangInStatus(List<Status> status) {
+	public static Criteria vorgangIsUnassigned() {
+		return new Criteria(MONGODB_FIELDNAME_ASSIGNED_TO).exists(false);
+	}
+
+	public static Criteria vorgangInStatus(List<Status> status) {
 		return new Criteria(MONGODB_FIELDNAME_STATUS).in(status);
 	}
 
-	static Criteria vorgangRemainingStatus() {
+	public static Criteria vorgangRemainingStatus() {
 		return new Criteria(MONGODB_FIELDNAME_STATUS).not().in(Status.NEU, Status.ANGENOMMEN, Status.BESCHIEDEN, Status.IN_BEARBEITUNG,
 				Status.WEITERGELEITET);
 	}
 
-	static Criteria vorgangStatusBearbeitet() {
+	public static Criteria vorgangStatusBearbeitet() {
 		return new Criteria(MONGODB_FIELDNAME_STATUS).in(Status.BESCHIEDEN, Status.WEITERGELEITET);
 	}
 
-	static Criteria vorgangStatusZuBearbeitendeEA() {
+	public static Criteria vorgangStatusZuBearbeitendeEA() {
 		return new Criteria(MONGODB_FIELDNAME_STATUS).in(Status.NEU, Status.ANGENOMMEN);
 	}
 
-	static Criteria vorgangStatusZuBearbeitende() {
+	public static Criteria vorgangStatusZuBearbeitende() {
 		return new Criteria(MONGODB_FIELDNAME_STATUS).in(Status.NEU, Status.ANGENOMMEN, Status.IN_BEARBEITUNG);
 	}
 
-	static Criteria vorgangStatusInBearbeitung() {
+	public static Criteria vorgangStatusInBearbeitung() {
 		return new Criteria(MONGODB_FIELDNAME_STATUS).is(Status.IN_BEARBEITUNG);
 	}
 
-	static Criteria searchCriteria(String searchString) {
+	public static Criteria searchCriteria(String searchString) {
 		var searchParts = searchString.trim().split(StringUtils.SPACE);
 		return new Criteria().andOperator(Arrays.stream(searchParts).map(CriteriaUtil::buildSearchPartCriteria).toList());
 	}
@@ -99,11 +112,24 @@ class CriteriaUtil { // NOSONAR
 				new Criteria(FIELD_NUMMER).regex(searchPart, CASE_INSENSITIV));
 	}
 
-	static Criteria nextWiedervorlageFristInThePast() {
-		return new Criteria(CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY).lte(LocalDate.now().toString());
+	public static Criteria nextWiedervorlageFristInThePast() {
+		return new Criteria(CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).lte(LocalDate.now().toString());
+	}
+
+	public static Criteria nextWiedervorlageFristInTheFuture() {
+		return new Criteria(CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).gt(LocalDate.now().toString());
 	}
 
-	static Criteria withoutNextWiedervorlageFrist() {
+	public static Criteria withoutNextWiedervorlageFrist() {
 		return Criteria.where(CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).isNull();
 	}
+
+	public static Criteria nextWiedervorlageFristExists() {
+		return Criteria.where(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY).exists(true);
+	}
+
+	public static Criteria whereIdAndVersion(String vorgangId, long version) {
+		return isId(vorgangId).and(MONGODB_FIELDNAME_VERSION).is(version);
+	}
+
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/ExceptionHandler.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/ExceptionHandler.java
similarity index 95%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/ExceptionHandler.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/ExceptionHandler.java
index 0477ae980b3f68cdd5879cb3efae4661da5797b1..a58a91e0b04467f535f27830105f7b85aa8a90da 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/ExceptionHandler.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/ExceptionHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.errorhandling;
+package de.ozgcloud.vorgang.common.errorhandling;
 
 import java.util.UUID;
 
 import org.springframework.security.access.AccessDeniedException;
 
-import de.itvsh.kop.common.errorhandling.ExceptionUtil;
-import de.itvsh.kop.common.errorhandling.TechnicalException;
+import de.ozgcloud.common.errorhandling.ExceptionUtil;
+import de.ozgcloud.common.errorhandling.TechnicalException;
 import io.grpc.Metadata;
 import io.grpc.Metadata.Key;
 import io.grpc.Status;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/FunctionalException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/FunctionalException.java
similarity index 88%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/FunctionalException.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/FunctionalException.java
index b1516db35fab66db0339d7f11cf56ffa94c49988..348f49f60a77f101e2504d38531af6ff44da6af0 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/FunctionalException.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/FunctionalException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.errorhandling;
+package de.ozgcloud.vorgang.common.errorhandling;
 
 import java.util.Collections;
 import java.util.Map;
 import java.util.UUID;
 
-import de.itvsh.kop.common.errorhandling.ExceptionUtil;
-import de.itvsh.kop.common.errorhandling.FunctionalErrorCode;
-import de.itvsh.kop.common.errorhandling.IdentifiableException;
+import de.ozgcloud.common.errorhandling.ExceptionUtil;
+import de.ozgcloud.common.errorhandling.FunctionalErrorCode;
+import de.ozgcloud.common.errorhandling.IdentifiableException;
 import lombok.Getter;
 
 public class FunctionalException extends RuntimeException implements IdentifiableException {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/NotFoundException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/NotFoundException.java
similarity index 89%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/NotFoundException.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/NotFoundException.java
index 1f0af7afd1d3293a160d174c143326b827ccf766..ab8ac3cd89a6800a3250f2d87a38ac8c923c7000 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/NotFoundException.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/NotFoundException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.errorhandling;
+package de.ozgcloud.vorgang.common.errorhandling;
 
 import java.util.Map;
 
-import de.itvsh.kop.common.errorhandling.FunctionalErrorCode;
+import de.ozgcloud.common.errorhandling.FunctionalErrorCode;
 import lombok.Getter;
 
 @Getter
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/SearchServiceUnavailableException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/SearchServiceUnavailableException.java
similarity index 86%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/SearchServiceUnavailableException.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/SearchServiceUnavailableException.java
index b39c3f8f4e530a57783ea1cb3eac10553452a3d8..391f0fe5d78d13d43f29cab20ea3ce3d34719642 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/errorhandling/SearchServiceUnavailableException.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/errorhandling/SearchServiceUnavailableException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.errorhandling;
+package de.ozgcloud.vorgang.common.errorhandling;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
+import de.ozgcloud.common.errorhandling.TechnicalException;
 
 public class SearchServiceUnavailableException extends TechnicalException {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/RepositoryAspectPointcut.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/logging/RepositoryAspectPointcut.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/RepositoryAspectPointcut.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/logging/RepositoryAspectPointcut.java
index 56dee224276c3f189c025d309f144d2b24092d7f..7a04f6601ed7c3cd58dbd83bd166e733c73649ba 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/RepositoryAspectPointcut.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/logging/RepositoryAspectPointcut.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.logging;
+package de.ozgcloud.vorgang.common.logging;
 
 import org.aspectj.lang.annotation.Pointcut;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/RepositoryLoggingAspect.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/logging/RepositoryLoggingAspect.java
similarity index 88%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/RepositoryLoggingAspect.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/logging/RepositoryLoggingAspect.java
index 6b5a04763fcf35746ed118f124ae75bcaaa05e4b..ad369a2e7256448012fc49da06f0daba314c434e 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/RepositoryLoggingAspect.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/logging/RepositoryLoggingAspect.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.logging;
+package de.ozgcloud.vorgang.common.logging;
 
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.springframework.stereotype.Component;
 
-import de.itvsh.kop.common.logging.AspectLoggingUtils;
+import de.ozgcloud.common.logging.AspectLoggingUtils;
 
 @Aspect
 @Component
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M001_UpdateClientNameInClientAttributes.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M001_UpdateClientNameInClientAttributes.java
new file mode 100644
index 0000000000000000000000000000000000000000..3faa274dcfa8e0232140129e0151507412b5660f
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M001_UpdateClientNameInClientAttributes.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import io.mongock.api.annotations.ChangeUnit;
+import io.mongock.api.annotations.Execution;
+import io.mongock.api.annotations.RollbackExecution;
+
+@ChangeUnit(id = "2023-11-16 14:20:00 OZG-4189-OZG-4552", order = "M001", author = "mkuester", runAlways = true)
+public class M001_UpdateClientNameInClientAttributes { // NOSONAR
+
+	private static final String VORGANG_COLLECTION = "vorgang";
+
+	static final String OLD_CLIENT_NAME = "Goofy";
+	static final String NEW_CLIENT_NAME = "Alfa";
+
+	@Execution
+	public void doMigration(MongoTemplate template) {
+		template.updateMulti(
+				RenameUtil.createFindVorgangClientAttributesQuery(OLD_CLIENT_NAME),
+				RenameUtil.createVorgangClientAttributesClientUpdate(OLD_CLIENT_NAME, NEW_CLIENT_NAME),
+				VORGANG_COLLECTION);
+	}
+
+	@RollbackExecution
+	public void rollback() {
+		// kein rollback implementiert
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M002_UpdateClientNameInGridFs.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M002_UpdateClientNameInGridFs.java
new file mode 100644
index 0000000000000000000000000000000000000000..91b7a755d783cbd1db598c7af1e6751cf6746bf8
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M002_UpdateClientNameInGridFs.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import java.util.List;
+
+import org.springframework.data.mongodb.core.MongoOperations;
+
+import io.mongock.api.annotations.ChangeUnit;
+import io.mongock.api.annotations.Execution;
+import io.mongock.api.annotations.RollbackExecution;
+
+@ChangeUnit(id = "2023-11-20 15:20:00 OZG-4189-OZG-4601", order = "M002", author = "mkuester", runAlways = true)
+public class M002_UpdateClientNameInGridFs { // NOSONAR
+
+	static final String GRID_FS_FILE_COLLECTION = "fs.files";
+	static final String OLD_CLIENT_NAME = "goofy";
+	static final String NEW_CLIENT_NAME = "Alfa";
+
+	@Execution
+	public void doMigration(MongoOperations db) {
+		db.getCollection(GRID_FS_FILE_COLLECTION).updateMany(
+				RenameUtil.createMetadataClientMatchingDocument(OLD_CLIENT_NAME),
+				List.of(
+						RenameUtil.createSetFilenameOperation(OLD_CLIENT_NAME, NEW_CLIENT_NAME),
+						RenameUtil.createSetClientDocument(NEW_CLIENT_NAME)));
+	}
+
+	@RollbackExecution
+	public void rollback() {
+		// kein rollback implementiert
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M008_DropBinaryFilesCollection.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M003_UpdateClientNameInVorgangAttachedItem.java
similarity index 63%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M008_DropBinaryFilesCollection.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M003_UpdateClientNameInVorgangAttachedItem.java
index 7add226a1c6b939d89fc8e0391a4b9bd4581f884..56331373bd1a3286e864510cf2cfc24b7543df82 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M008_DropBinaryFilesCollection.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M003_UpdateClientNameInVorgangAttachedItem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.migration;
+package de.ozgcloud.vorgang.common.migration;
 
 import org.springframework.data.mongodb.core.MongoTemplate;
 
@@ -29,14 +29,20 @@ import io.mongock.api.annotations.ChangeUnit;
 import io.mongock.api.annotations.Execution;
 import io.mongock.api.annotations.RollbackExecution;
 
-@ChangeUnit(id = "2022-07-06 13:05:00 OZG-2689", order = "M008", author = "jreese", runAlways = true)
-public class M008_DropBinaryFilesCollection {// NOSONAR
+@ChangeUnit(id = "2023-11-20 15:20:00 OZG-4189-OZG-4551", order = "M003", author = "mkuester", runAlways = true)
+public class M003_UpdateClientNameInVorgangAttachedItem { // NOSONAR
 
-	static final String COLLECTION = "binaryFile";
+	static final String VORGANG_ATTACHED_ITEM = "vorgangAttachedItem";
+
+	static final String OLD_CLIENT_NAME = "Goofy";
+	static final String NEW_CLIENT_NAME = "Alfa";
 
 	@Execution
-	public void migrationMethod(MongoTemplate template) {
-		template.dropCollection(COLLECTION);
+	public void doMigration(MongoTemplate template) {
+		template.updateMulti(
+				RenameUtil.createFindVorgangAttachedItemQuery(OLD_CLIENT_NAME),
+				RenameUtil.createVorgangAttachedItemUpdate(NEW_CLIENT_NAME),
+				VORGANG_ATTACHED_ITEM);
 	}
 
 	@RollbackExecution
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M002_SetInCreationFalseForAllVorgangs.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItem.java
similarity index 59%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M002_SetInCreationFalseForAllVorgangs.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItem.java
index 20f58670976f16fcb61b395fde40607be9876e7b..6ce7f56b29f6f5e7e8ac6ec466803150689814b1 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/M002_SetInCreationFalseForAllVorgangs.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,32 +21,28 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.migration;
+package de.ozgcloud.vorgang.common.migration;
 
 import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.mongodb.core.query.Update;
 
 import io.mongock.api.annotations.ChangeUnit;
 import io.mongock.api.annotations.Execution;
 import io.mongock.api.annotations.RollbackExecution;
 
-@ChangeUnit(id = "2022-04-21 10:31:00 OZG-2093", order = "M002", author = "jreese", runAlways = false)
-public class M002_SetInCreationFalseForAllVorgangs { // NOSONAR
-	private static final String FIELD_NAME = "inCreation";
-	private static final String COLLECTION_NAME = "vorgang";
+@ChangeUnit(id = "2023-11-22 11:00:00 OZG-4191-OZG-4573", order = "M004", author = "mkuester", runAlways = true)
+public class M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItem { // NOSONAR
 
-	@Execution
-	public void migrationMethod(final MongoTemplate template) {
-		Update update = new Update();
-		update.set(FIELD_NAME, Boolean.FALSE);
+	static final String VORGANG_ATTACHED_ITEM = "vorgangAttachedItem";
 
-		Query query = new Query(Criteria
-				.where(FIELD_NAME)
-				.exists(false));
+	static final String OLD_CLIENT_NAME = "KopNachrichtenManager";
+	static final String NEW_CLIENT_NAME = "OzgCloud_NachrichtenManager";
 
-		template.updateMulti(query, update, COLLECTION_NAME);
+	@Execution
+	public void doMigration(MongoTemplate template) {
+		template.updateMulti(
+				RenameUtil.createFindVorgangAttachedItemQuery(OLD_CLIENT_NAME),
+				RenameUtil.createVorgangAttachedItemUpdate(NEW_CLIENT_NAME),
+				VORGANG_ATTACHED_ITEM);
 	}
 
 	@RollbackExecution
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M005_UpdateNachrichtenManagerClientNameInClientAttributes.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M005_UpdateNachrichtenManagerClientNameInClientAttributes.java
new file mode 100644
index 0000000000000000000000000000000000000000..f57dbf3d1b36934b1e390242289490976fc4913d
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M005_UpdateNachrichtenManagerClientNameInClientAttributes.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import io.mongock.api.annotations.ChangeUnit;
+import io.mongock.api.annotations.Execution;
+import io.mongock.api.annotations.RollbackExecution;
+
+@ChangeUnit(id = "2023-11-22 13:00:00 OZG-4191-OZG-4609", order = "M005", author = "mkuester", runAlways = true)
+public class M005_UpdateNachrichtenManagerClientNameInClientAttributes { // NOSONAR
+
+	private static final String VORGANG_COLLECTION = "vorgang";
+
+	static final String OLD_CLIENT_NAME = "KopNachrichtenManager ";
+	static final String NEW_CLIENT_NAME = "OzgCloud_NachrichtenManager";
+
+	@Execution
+	public void doMigration(MongoTemplate template) {
+		template.updateMulti(
+				RenameUtil.createFindVorgangClientAttributesQuery(OLD_CLIENT_NAME),
+				RenameUtil.createVorgangClientAttributesClientUpdate(OLD_CLIENT_NAME, NEW_CLIENT_NAME),
+				VORGANG_COLLECTION);
+	}
+
+	@RollbackExecution
+	public void rollback() {
+		// kein rollback implementiert
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M006_UpdateMailServiceClientNameInVorgangAttachedItem.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M006_UpdateMailServiceClientNameInVorgangAttachedItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..48a9d30efd1790c9a677cd6c28b812e9eb4d34d0
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M006_UpdateMailServiceClientNameInVorgangAttachedItem.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import io.mongock.api.annotations.ChangeUnit;
+import io.mongock.api.annotations.Execution;
+import io.mongock.api.annotations.RollbackExecution;
+
+@ChangeUnit(id = "2023-11-29 14:30:00 OZG-4191-OZG-4629", order = "M006", author = "mkuester", runAlways = true)
+public class M006_UpdateMailServiceClientNameInVorgangAttachedItem { // NOSONAR
+
+	static final String VORGANG_ATTACHED_ITEM = "vorgangAttachedItem";
+
+	static final String OLD_CLIENT_NAME = "MailService";
+	static final String NEW_CLIENT_NAME = "OzgCloud_NachrichtenManager";
+
+	@Execution
+	public void doMigration(MongoTemplate template) {
+		template.updateMulti(
+				RenameUtil.createFindVorgangAttachedItemQuery(OLD_CLIENT_NAME),
+				RenameUtil.createVorgangAttachedItemUpdate(NEW_CLIENT_NAME),
+				VORGANG_ATTACHED_ITEM);
+	}
+
+	@RollbackExecution
+	public void rollback() {
+		// kein rollback implementiert
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M007_UpdateMailServiceClientNameInClientAttributes.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M007_UpdateMailServiceClientNameInClientAttributes.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd4e603d53f8bcde768f28a51dbe474d543baada
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M007_UpdateMailServiceClientNameInClientAttributes.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import io.mongock.api.annotations.ChangeUnit;
+import io.mongock.api.annotations.Execution;
+import io.mongock.api.annotations.RollbackExecution;
+
+@ChangeUnit(id = "2023-11-29 14:45:00 OZG-4191-OZG-4629", order = "M007", author = "mkuester", runAlways = true)
+public class M007_UpdateMailServiceClientNameInClientAttributes { // NOSONAR
+
+	private static final String VORGANG_COLLECTION = "vorgang";
+
+	static final String OLD_CLIENT_NAME = "MailService ";
+	static final String NEW_CLIENT_NAME = "OzgCloud_NachrichtenManager";
+
+	@Execution
+	public void doMigration(MongoTemplate template) {
+		template.updateMulti(
+				RenameUtil.createFindVorgangClientAttributesQuery(OLD_CLIENT_NAME),
+				RenameUtil.createVorgangClientAttributesClientUpdate(OLD_CLIENT_NAME, NEW_CLIENT_NAME),
+				VORGANG_COLLECTION);
+	}
+
+	@RollbackExecution
+	public void rollback() {
+		// kein rollback implementiert
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M008_UpdateMailServiceClientNameInGridFs.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M008_UpdateMailServiceClientNameInGridFs.java
new file mode 100644
index 0000000000000000000000000000000000000000..86ecbf8812043ea90d76e6e3be8f1128b7d68149
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/M008_UpdateMailServiceClientNameInGridFs.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import java.util.List;
+
+import org.springframework.data.mongodb.core.MongoOperations;
+
+import io.mongock.api.annotations.ChangeUnit;
+import io.mongock.api.annotations.Execution;
+import io.mongock.api.annotations.RollbackExecution;
+
+@ChangeUnit(id = "2023-11-29 15:30:00 OZG-4191-OZG-4630", order = "M008", author = "mkuester", runAlways = true)
+public class M008_UpdateMailServiceClientNameInGridFs { // NOSONAR
+
+	static final String GRID_FS_FILE_COLLECTION = "fs.files";
+	static final String OLD_CLIENT_NAME = "MailService";
+	static final String NEW_CLIENT_NAME = "OzgCloud_NachrichtenManager";
+
+	@Execution
+	public void doMigration(MongoOperations db) {
+		db.getCollection(GRID_FS_FILE_COLLECTION).updateMany(
+				RenameUtil.createMetadataClientMatchingDocument(OLD_CLIENT_NAME),
+				List.of(
+						RenameUtil.createSetFilenameOperation(OLD_CLIENT_NAME, NEW_CLIENT_NAME),
+						RenameUtil.createSetClientDocument(NEW_CLIENT_NAME)));
+	}
+
+	@RollbackExecution
+	public void rollback() {
+		// kein rollback implementiert
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MigrationException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MigrationException.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MigrationException.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MigrationException.java
index 614718318223ed69b3a816f9755127d1d2600c26..7b17fa1cd8eaccdec864f475d500ebd502b6207d 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MigrationException.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MigrationException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.migration;
+package de.ozgcloud.vorgang.common.migration;
 
 class MigrationException extends RuntimeException {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockFailedEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockFailedEventListener.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockFailedEventListener.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockFailedEventListener.java
index c976a1bcd3eab705df8541f342963e6d116d05ca..14950331954fdd5b81c9148adb1936d31edbe750 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockFailedEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockFailedEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.migration;
+package de.ozgcloud.vorgang.common.migration;
 
 import org.springframework.context.ApplicationListener;
 import org.springframework.stereotype.Component;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockStartEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockStartEventListener.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockStartEventListener.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockStartEventListener.java
index 927babbce3ef32d1b89a30cdacdfe0ad42f07253..bcc9ef6e5280e03c89f9c3451b59bfdc138c2740 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockStartEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockStartEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.migration;
+package de.ozgcloud.vorgang.common.migration;
 
 import org.springframework.context.ApplicationListener;
 import org.springframework.stereotype.Component;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockSuccessEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockSuccessEventListener.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockSuccessEventListener.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockSuccessEventListener.java
index f6f38e05f226ecef2dfd4c598c8f3c46daf6392d..5586fb667c00fb73833efb23637794314924f9d3 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/migration/MongockSuccessEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/MongockSuccessEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.migration;
+package de.ozgcloud.vorgang.common.migration;
 
 import org.springframework.context.ApplicationListener;
 import org.springframework.stereotype.Component;
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/RenameUtil.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/RenameUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..df12808e40c57a97ff280d106198309999e9021b
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/migration/RenameUtil.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import java.util.Map;
+
+import org.bson.Document;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.Update;
+import org.springframework.data.mongodb.core.query.UpdateDefinition;
+
+class RenameUtil {
+
+	private final static String SET_OPERATOR = "$set";
+	private final static String REPLACE_ONE_OPERATOR = "$replaceOne";
+
+	static final String CLIENT_KEY = "client";
+
+	// VorgangAttachedItem
+	public static Query createFindVorgangAttachedItemQuery(String clientName) {
+		return Query.query(Criteria.where(CLIENT_KEY).is(clientName));
+	}
+
+	public static Update createVorgangAttachedItemUpdate(String newClientName) {
+		return new Update().set(CLIENT_KEY, newClientName);
+	}
+
+	// GridFsFiles
+	static final String FILENAME_KEY = "filename";
+	static final String METADATA_KEY = "metadata";
+
+	public static Document createMetadataClientMatchingDocument(String clientName) {
+		return new Document(Map.of(METADATA_KEY + "." + CLIENT_KEY, clientName));
+	}
+
+	public static Document createSetFilenameOperation(String oldClientName, String newClientName) {
+		return new Document(Map.of(SET_OPERATOR,
+				Map.of(FILENAME_KEY,
+						Map.of(REPLACE_ONE_OPERATOR,
+								Map.of("input", "$" + FILENAME_KEY,
+										"find", "/" + oldClientName + "/",
+										"replacement", "/" + newClientName + "/")))));
+	}
+
+	public static Document createSetClientDocument(String newClientName) {
+		return new Document(Map.of(SET_OPERATOR, Map.of(RenameUtil.METADATA_KEY + "." + CLIENT_KEY, newClientName)));
+	}
+
+	// Vorgang ClientAttributes
+	static final String CLIENT_ATTRIBUTES_KEY = "clientAttributes";
+
+	public static Query createFindVorgangClientAttributesQuery(String clientName) {
+		return new Query(Criteria.where(CLIENT_ATTRIBUTES_KEY + "." + clientName).exists(true));
+	}
+
+	public static UpdateDefinition createVorgangClientAttributesClientUpdate(String oldClientName, String newClientName) {
+		var update = new Update();
+		update.rename(CLIENT_ATTRIBUTES_KEY + "." + oldClientName, CLIENT_ATTRIBUTES_KEY + "." + newClientName);
+		return update;
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/EqualOperator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/EqualOperator.java
new file mode 100644
index 0000000000000000000000000000000000000000..51186e2e4e9e6b466e1a07ba4f58d35dd42f83c6
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/EqualOperator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import static java.util.Objects.*;
+import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond.*;
+import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.IfNull.*;
+
+import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import lombok.Builder;
+
+@Builder
+class EqualOperator implements Operator {
+
+	private String fieldPath;
+	private Object operand;
+
+	@Override
+	public Criteria getCriteria() {
+		return Criteria.where(fieldPath).is(operand);
+	}
+
+	@Override
+	public AggregationExpression getAggregationExpression() {
+		return isNull(operand)
+				? when(ifNull(fieldPath).then(true)).then(1).otherwise(0)
+				: Operator.super.getAggregationExpression();
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/ExistsOperator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/ExistsOperator.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc49ce98a32de96219a22fbca2c2d86d1a74bf2b
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/ExistsOperator.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import lombok.Builder;
+
+@Builder
+public class ExistsOperator implements Operator {
+
+	private String fieldPath;
+	private boolean negate;
+
+	@Override
+	public Criteria getCriteria() {
+		var criteriaBuilder = Criteria.where(fieldPath);
+		return negate ? criteriaBuilder.exists(false) : criteriaBuilder.exists(true);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/FieldPathProcessor.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/FieldPathProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..4acac72ce032115bb147a469ff5597ac56cb48eb
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/FieldPathProcessor.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+
+import de.ozgcloud.vorgang.statistic.InvalidFieldPathException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.extern.log4j.Log4j2;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+@Log4j2
+class FieldPathProcessor {
+
+	static final String PATH_ENTITY_VORGANG = "Vorgang";
+	static final String PATH_ENTITY_CLIENT_ATTRIBUTE = "ClientAttribute";
+
+	static final String CRITERIA_PATH_VORGANG = "";
+	static final String CRITERIA_PATH_CLIENT_ATTRIBUTE = Vorgang.FIELD_CLIENT_ATTRIBUTES;
+
+	private static final Map<String, String> ENTITY_TO_PATH = Map.of(
+			PATH_ENTITY_VORGANG, CRITERIA_PATH_VORGANG,
+			PATH_ENTITY_CLIENT_ATTRIBUTE, CRITERIA_PATH_CLIENT_ATTRIBUTE);
+
+	private static final Map<String, String> ENTITY_TO_PATHSUFFIX = Map.of(
+			PATH_ENTITY_CLIENT_ATTRIBUTE, "value");
+
+	private static final String CRITERIA_PATH_TEMPLATE = "%s.%s";
+
+	public static String processToCriteriaPath(String fieldPath) {
+		// TODO do path validation earlier
+		validate(fieldPath);
+
+		if (StringUtils.isBlank(getCriteriaEntity(fieldPath))) {
+			return getPath(fieldPath);
+		}
+
+		return CRITERIA_PATH_TEMPLATE.formatted(getCriteriaEntity(fieldPath), getPath(fieldPath));
+	}
+
+	private static void validate(String path) {
+		if (!path.contains(".")) {
+			throw new InvalidFieldPathException();
+		}
+	}
+
+	static String getCriteriaEntity(@NonNull String path) {
+		return Optional.ofNullable(ENTITY_TO_PATH.get(getEntity(path)))
+				.orElseThrow(() -> logAndBuildUnsupportedEntityException(getEntity(path)));
+	}
+
+	private static RuntimeException logAndBuildUnsupportedEntityException(String entity) {
+		LOG.error("Given Entity '{}' is unsupported.", entity);
+		return new UnsupportedEntityException();
+	}
+
+	public static String getPath(String path) {
+		var criteriaPath = StringUtils.substringAfter(path, ".");
+
+		return getPathSuffix(path).map(suffix -> CRITERIA_PATH_TEMPLATE.formatted(criteriaPath, suffix))
+				.orElse(criteriaPath);
+	}
+
+	static Optional<String> getPathSuffix(String path) {
+		return Optional.ofNullable(ENTITY_TO_PATHSUFFIX.get(getEntity(path)));
+	}
+
+	private static String getEntity(String path) {
+		return StringUtils.substringBefore(path, ".");
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/GreaterThenOperator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/GreaterThenOperator.java
new file mode 100644
index 0000000000000000000000000000000000000000..d425a710c5d0b6fa671447e56e8b53bcd13fe770
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/GreaterThenOperator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import lombok.Builder;
+
+@Builder
+class GreaterThenOperator implements Operator {
+
+	private String fieldPath;
+	private Object operand;
+
+	@Override
+	public Criteria getCriteria() {
+		return Criteria.where(fieldPath).gt(operand);
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/GreaterThenOrEqualOperator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/GreaterThenOrEqualOperator.java
new file mode 100644
index 0000000000000000000000000000000000000000..1abedd086f678ed9edfb79159968063ff129e221
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/GreaterThenOrEqualOperator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import lombok.Builder;
+
+@Builder
+class GreaterThenOrEqualOperator implements Operator {
+
+	private String fieldPath;
+	private Object operand;
+
+	@Override
+	public Criteria getCriteria() {
+		return Criteria.where(fieldPath).gte(operand);
+	}
+
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/LessThenOperator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/LessThenOperator.java
new file mode 100644
index 0000000000000000000000000000000000000000..146c70092a7ecac35db135e0e5a9b826740be21a
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/LessThenOperator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import lombok.Builder;
+
+@Builder
+class LessThenOperator implements Operator {
+
+	private String fieldPath;
+	private Object operand;
+
+	@Override
+	public Criteria getCriteria() {
+		return Criteria.where(fieldPath).lt(operand);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/LessThenOrEqualOperator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/LessThenOrEqualOperator.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef5dbb5b74b949571e1ea424e25928e46509b662
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/LessThenOrEqualOperator.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import lombok.Builder;
+
+@Builder
+class LessThenOrEqualOperator implements Operator {
+
+	private String fieldPath;
+	private Object operand;
+
+	@Override
+	public Criteria getCriteria() {
+		return Criteria.where(fieldPath).lte(operand);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperandFunctionParser.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperandFunctionParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e70688b9fe8e73ef5c4ca285a7b3e9c4f6385c3
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperandFunctionParser.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import java.time.LocalDate;
+
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.vorgang.statistic.VorgangStatisticBadRequestException;
+
+@Component
+public class OperandFunctionParser {
+
+	public String parse(String operand) {
+		if (operand.equalsIgnoreCase("today()")) {
+			return LocalDate.now().toString();
+		}
+		throw new VorgangStatisticBadRequestException("Operand function not supported: " + operand);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/Operator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/Operator.java
new file mode 100644
index 0000000000000000000000000000000000000000..0cd9c59177023620f5ecd00c83c44ade32fe9a55
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/Operator.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond.*;
+
+import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+public interface Operator {
+
+	Criteria getCriteria();
+
+	default AggregationExpression getAggregationExpression() {
+		return when(getCriteria()).then(1).otherwise(0);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperatorBuilder.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperatorBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..a14e3535d75691d98320ef5a357c371a994e66c8
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperatorBuilder.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import static java.util.Objects.*;
+import static org.apache.commons.lang3.StringUtils.*;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+import java.util.Collection;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.statistic.VorgangStatisticBadRequestException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class OperatorBuilder {
+
+	private GrpcQueryOperator grpcOperator;
+	private String fieldPath;
+	private Object operand;
+
+	public static OperatorBuilder from(GrpcQueryOperator grpcOperator) {
+		var builder = new OperatorBuilder();
+		builder.grpcOperator = grpcOperator;
+		return builder;
+	}
+
+	public OperatorBuilder fieldPath(String fieldPath) {
+		this.fieldPath = FieldPathProcessor.processToCriteriaPath(fieldPath);
+		return this;
+	}
+
+	public OperatorBuilder operand(Object operand) {
+		this.operand = operand;
+		return this;
+	}
+
+	public Operator build() {
+		if (isNull(grpcOperator)) {
+			throw new NullPointerException("Operator is missing");
+		}
+		operand = getParsedOperand();
+		return switch (grpcOperator) {
+			case EQUAL -> EqualOperator.builder().fieldPath(fieldPath).operand(operand).build();
+			case IS_EMPTY -> EqualOperator.builder().fieldPath(fieldPath).operand(StringUtils.EMPTY).build();
+			case IS_NULL -> EqualOperator.builder().fieldPath(fieldPath).build();
+			case UNEQUAL -> UnequalOperator.builder().fieldPath(fieldPath).operand(operand).build();
+			case GREATER_THEN -> GreaterThenOperator.builder().fieldPath(fieldPath).operand(operand).build();
+			case GREATER_THEN_OR_EQUAL_TO -> GreaterThenOrEqualOperator.builder().fieldPath(fieldPath).operand(operand).build();
+			case LESS_THEN -> LessThenOperator.builder().fieldPath(fieldPath).operand(operand).build();
+			case LESS_THEN_OR_EQUAL_TO -> LessThenOrEqualOperator.builder().fieldPath(fieldPath).operand(operand).build();
+			case EXISTS -> ExistsOperator.builder().fieldPath(fieldPath).build();
+			case NOT_EXIST -> ExistsOperator.builder().fieldPath(fieldPath).negate(true).build();
+			case UNRECOGNIZED -> throw new VorgangStatisticBadRequestException("Unrecognized operator");
+		};
+	}
+
+	@SneakyThrows
+	Object getParsedOperand() {
+		return Optional.ofNullable(getFieldClass()).map(this::parseValue).orElse(operand);
+	}
+
+	Class<?> getFieldClass() {
+		if (isBlank(fieldPath)) {
+			return null;
+		}
+		var fieldNames = fieldPath.split("\\.");
+		Class<?> clazz = Vorgang.class;
+		for (var fieldName : fieldNames) {
+			try {
+				clazz = getFieldClass(clazz.getDeclaredField(fieldName));
+			} catch (NoSuchFieldException | ClassNotFoundException e) {
+				LOG.warn("Cannot find field {} from {}", fieldName, fieldPath, e);
+				return null;
+			}
+		}
+		return clazz;
+	}
+
+	Class<?> getFieldClass(Field field) throws ClassNotFoundException {
+		if (Collection.class.isAssignableFrom(field.getType())) {
+			var actualTypeArgument = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
+			return Class.forName(actualTypeArgument.getTypeName());
+		} else {
+			return field.getType();
+		}
+	}
+
+	Object parseValue(Class<?> clazz) {
+		if (operand instanceof String valueString) {
+			if (ZonedDateTime.class.equals(clazz)) {
+				return ZonedDateTime.parse(valueString);
+			}
+			if (LocalDate.class.equals(clazz)) {
+				return LocalDate.parse(valueString);
+			}
+			if (LocalDateTime.class.equals(clazz)) {
+				return LocalDateTime.parse(valueString);
+			}
+		}
+		return operand;
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperatorFactory.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperatorFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea7dddfcc59c021571a88b76b25534359dd41091
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/OperatorFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+
+@Component
+public class OperatorFactory {
+
+	public OperatorBuilder newUnequalOperatorBuilder() {
+		return OperatorBuilder.from(GrpcQueryOperator.UNEQUAL);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/UnequalOperator.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/UnequalOperator.java
new file mode 100644
index 0000000000000000000000000000000000000000..e351d370b89f37de9879767304e578641a7b09ad
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/UnequalOperator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import static java.util.Objects.*;
+import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.Cond.*;
+import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.IfNull.*;
+
+import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import lombok.Builder;
+
+@Builder
+class UnequalOperator implements Operator {
+
+	private String fieldPath;
+	private Object operand;
+
+	@Override
+	public Criteria getCriteria() {
+		return Criteria.where(fieldPath).ne(operand);
+	}
+
+	@Override
+	public AggregationExpression getAggregationExpression() {
+		return isNull(operand)
+				? when(ifNull(fieldPath).then(false)).then(1).otherwise(0)
+				: Operator.super.getAggregationExpression();
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/UnsupportedEntityException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/UnsupportedEntityException.java
new file mode 100644
index 0000000000000000000000000000000000000000..29dec487dc27d374823fba8a3ab013daaf785bcc
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/operator/UnsupportedEntityException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import de.ozgcloud.vorgang.common.errorhandling.FunctionalException;
+
+public class UnsupportedEntityException extends FunctionalException {
+
+	public UnsupportedEntityException() {
+		super(() -> "entity.unsupported");
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/IndexedVorgang.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/IndexedVorgang.java
similarity index 78%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/IndexedVorgang.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/IndexedVorgang.java
index f220237034124ce0af23dc3544ee38b473b21947..9356de2e9e49b550a81f7cef507f15571c57fc1f 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/IndexedVorgang.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/IndexedVorgang.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import java.time.ZonedDateTime;
 
@@ -30,12 +30,14 @@ import org.springframework.data.elasticsearch.annotations.DateFormat;
 import org.springframework.data.elasticsearch.annotations.Document;
 import org.springframework.data.elasticsearch.annotations.Field;
 import org.springframework.data.elasticsearch.annotations.FieldType;
+import org.springframework.data.elasticsearch.annotations.Setting;
 
 import lombok.Builder;
 import lombok.Getter;
 import lombok.ToString;
 
-@Document(indexName = "#{@environment.getProperty('kop.elasticsearch.index')}")
+@Document(indexName = "#{@environment.getProperty('ozgcloud.elasticsearch.index')}")
+@Setting(settingPath = "elastic/settings.json")
 @ToString
 @Getter
 @Builder
@@ -55,14 +57,19 @@ class IndexedVorgang {
 	@Id
 	private String vorgangId;
 
+	@Field(type = FieldType.Keyword, normalizer = "lowercase_normalizer")
 	private String vorgangName;
+	@Field(type = FieldType.Keyword, normalizer = "lowercase_normalizer")
 	private String vorgangNummer;
 
 	@Field(type = FieldType.Date, format = DateFormat.date_time, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
 	private ZonedDateTime createdAt;
+	@Field(type = FieldType.Keyword, normalizer = "lowercase_normalizer")
 	private String antragstellerName;
+	@Field(type = FieldType.Keyword, normalizer = "lowercase_normalizer")
 	private String antragstellerVorname;
 
+	@Field(type = FieldType.Keyword, normalizer = "lowercase_normalizer")
 	private String aktenzeichen;
 	private String status;
 	private String organisationseinheitenId;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/IndexedVorgangMapper.java
similarity index 78%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/IndexedVorgangMapper.java
index 91fa731e2edbf3447ba35a801f56215fd5107096..114a372aaceab5ebc489483627d55b7dc51a1e95 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/IndexedVorgangMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import java.util.Optional;
 
@@ -30,12 +30,11 @@ import org.mapstruct.Mapping;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 
-import de.itvsh.ozg.pluto.vorgang.Antragsteller;
-import de.itvsh.ozg.pluto.vorgang.Eingang;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangHeader;
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelle;
+import de.ozgcloud.vorgang.vorgang.Antragsteller;
+import de.ozgcloud.vorgang.vorgang.Eingang;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangHeader;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelle;
 
 @Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
 interface IndexedVorgangMapper {
@@ -75,15 +74,11 @@ interface IndexedVorgangMapper {
 		return Optional.ofNullable(eingang.getZustaendigeStelle());
 	}
 
-	default VorgangHeader toVorgangHeader(IndexedVorgang vorgang) {
-		return VorgangHeader.builder()
-				.aktenzeichen(vorgang.getAktenzeichen())
-				.assignedTo(vorgang.getAssignedTo())
-				.id(vorgang.getVorgangId())
-				.createdAt(vorgang.getCreatedAt())
-				.nummer(vorgang.getVorgangNummer())
-				.name(vorgang.getVorgangName())
-				.status(Status.valueOf(vorgang.getStatus()))
-				.build();
-	}
+	@Mapping(target = "clientAttributes", ignore = true)
+	@Mapping(target = "formEngineName", ignore = true)
+	@Mapping(target = "id", source = "vorgangId")
+	@Mapping(target = "name", source = "vorgangName")
+	@Mapping(target = "nummer", source = "vorgangNummer")
+	@Mapping(target = "version", ignore = true)
+	VorgangHeader toVorgangHeader(IndexedVorgang vorgang);
 }
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchConfig.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..9821a7e8a9fabe21533a35a18946eb74d882ab9a
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchConfig.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.search;
+
+import jakarta.validation.Valid;
+import javax.net.ssl.SSLContext;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.ssl.SslBundles;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.elasticsearch.client.ClientConfiguration;
+import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration;
+import org.springframework.data.elasticsearch.support.HttpHeaders;
+
+import lombok.SneakyThrows;
+
+@Configuration
+@ConditionalOnProperty(prefix = "ozgcloud.elasticsearch", name = "address")
+public class SearchConfig extends ElasticsearchConfiguration {
+
+	@Autowired
+	@Valid
+	private SearchProperties properties;
+
+	@Autowired
+	private SslBundles sslBundles;
+
+	@SneakyThrows
+	@Override
+	public ClientConfiguration clientConfiguration() {
+		var configurationBuilder = ClientConfiguration.builder().connectedTo(properties.getAddress());
+		if (properties.isUseSsl()) {
+			configurationBuilder.usingSsl(createSslContext());
+		}
+		return configurationBuilder
+				.withDefaultHeaders(buildHeaders())
+				.withBasicAuth(properties.getUsername(), properties.getPassword())
+				.build();
+	}
+
+	SSLContext createSslContext() {
+		return sslBundles.getBundle("es-root-ca").createSslContext();
+	}
+
+	HttpHeaders buildHeaders() {
+		var headers = new HttpHeaders();
+		headers.add("Accept", "application/vnd.elasticsearch+json;compatible-with=7");
+		headers.add("Content-Type", "application/vnd.elasticsearch+json;compatible-with=7");
+		return headers;
+	}
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java
similarity index 58%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchEventListener.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java
index 8e0708b2d2e43df4efb08588e113e239848fe4b4..5bc0d38afd6d6a3b1c821953c7da30581b016fe5 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,25 +21,33 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import java.text.MessageFormat;
+import java.util.Collections;
+import java.util.HashMap;
 
+import org.apache.commons.collections.MapUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Component;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandService;
-import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
-import de.itvsh.ozg.pluto.vorgang.StatusChangedEvent;
-import de.itvsh.ozg.pluto.vorgang.VorgangAssignedEvent;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.status.StatusChangedEvent;
+import de.ozgcloud.vorgang.vorgang.SetAktenzeichenCompletedEvent;
+import de.ozgcloud.vorgang.vorgang.VorgangAssignedEvent;
+import de.ozgcloud.vorgang.vorgang.VorgangDeletedEvent;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import lombok.extern.log4j.Log4j2;
 
 @Component
-@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "uris")
+@ConditionalOnProperty(prefix = "ozgcloud.elasticsearch", name = "address")
+@Log4j2
 public class SearchEventListener {
+
 	@Autowired
 	private SearchService searchService;
 
@@ -75,4 +83,24 @@ public class SearchEventListener {
 		searchService.updateVorgang(vorgangService.getById(command.getVorgangId()));
 	}
 
+	@EventListener
+	public void onVorgangDeleted(VorgangDeletedEvent event) {
+		String vorgangId = event.getCommand().getVorgangId();
+		try {
+			searchService.deleteVorgang(vorgangId);
+		} catch (RuntimeException e) {
+			LOG.error("Error on deleting Vorgang (" + vorgangId + ") from search index.", e);
+		}
+	}
+
+	@EventListener
+	public void onSetAktenzeichenCompletedEvent(SetAktenzeichenCompletedEvent event) {
+		var command = event.getCommand();
+		var aktenzeichen = MapUtils.getString(command.getBodyObject(), VorgangService.BODY_OBJECT_AKTENZEICHEN);
+		try {
+			searchService.setAktenzeichen(command.getVorgangId(), aktenzeichen);
+		} catch (RuntimeException e) {
+			LOG.error("Error on setting new aktenzeichen ({}) for Vorgang ({}) in search index.", aktenzeichen, command.getVorgangId(), e);
+		}
+	}
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchIndexInitializer.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchIndexInitializer.java
similarity index 88%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchIndexInitializer.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchIndexInitializer.java
index ed1ee3f776f7c62ec64420efe8e2326de21421bd..cff29a65ac8e84bd2f1c86f4a3ec3950bce6b950 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchIndexInitializer.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchIndexInitializer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.annotation.Profile;
@@ -33,12 +33,12 @@ import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
 import lombok.extern.log4j.Log4j2;
 
 @Component
-@ConditionalOnBean(SearchService.class)
+@ConditionalOnProperty(prefix = "ozgcloud.elasticsearch", name = "address")
 @Profile("initSearchIndex")
 @Async
 @Log4j2
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchProperties.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchProperties.java
similarity index 79%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchProperties.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchProperties.java
index b6ba7993ca7eeadf3360eaa66bdcb47c2e6c4330..b1c18ef77670293c59fba8a751bb0c8d0057b0c9 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchProperties.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchProperties.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,25 +21,30 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
-
-import javax.validation.constraints.NotEmpty;
+package de.ozgcloud.vorgang.common.search;
 
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.io.Resource;
 
+import jakarta.validation.constraints.NotEmpty;
 import lombok.Getter;
 import lombok.Setter;
 
 @Getter
 @Setter
 @Configuration
-@ConfigurationProperties(prefix = "kop.elasticsearch")
+@ConfigurationProperties(prefix = "ozgcloud.elasticsearch")
 class SearchProperties {
+
 	private boolean initEnabled = false;
 	@NotEmpty
 	private String index;
 
 	private Resource ca;
+	private boolean useSsl = true;
+
+	private String address;
+	private String username;
+	private String password;
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchRequest.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchRequest.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchRequest.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchRequest.java
index 7bf83634285201d50deb1ec9ba22065597494a9e..bd98fefb10c3ec22bbcdd2ec855f1afb4ff78541 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchRequest.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import java.util.List;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchService.java
similarity index 53%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchService.java
index 9bdbc2705902e1df72b3cddcb2a2ed041bdebd29..646826cfdda8b0ac42d4b8e2ca56d7eb1f24b8e7 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
+
+import java.util.Collections;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -29,53 +31,50 @@ import org.springframework.dao.DataAccessResourceFailureException;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.ozg.pluto.common.errorhandling.SearchServiceUnavailableException;
-import de.itvsh.ozg.pluto.vorgang.FindVorgangRequest;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangHeader;
+import de.ozgcloud.vorgang.common.errorhandling.SearchServiceUnavailableException;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangHeader;
 
 @Service
-@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "uris")
+@ConditionalOnProperty(prefix = "ozgcloud.elasticsearch", name = "address")
 public class SearchService {
 
 	@Autowired
-	private SearchVorgangRepostitory repostitory;
+	private SearchVorgangRepository repository;
 
 	@Autowired
-	private SearchVorgangCustomRepostitory searchRepostitory;
+	private SearchVorgangCustomRepository searchRepository;
 
 	@Autowired
 	private IndexedVorgangMapper mapper;
 
 	public void addVorgang(Vorgang vorgang) {
-		repostitory.save(mapper.fromVorgang(vorgang));
+		repository.save(mapper.fromVorgang(vorgang));
 	}
 
 	public void updateVorgang(Vorgang vorgang) {
-		repostitory.save(mapper.fromVorgang(vorgang));
+		repository.save(mapper.fromVorgang(vorgang));
 	}
 
 	public boolean existsById(String vorgangId) {
-		return repostitory.existsById(vorgangId);
+		return repository.existsById(vorgangId);
 	}
 
-	public Page<VorgangHeader> find(FindVorgangRequest searchRequest) {
+	public Page<VorgangHeader> find(FindVorgangRequest findVorgangRequest) {
 		try {
-			return searchRepostitory.searchBy(buildSearchRequest(searchRequest));
+			return searchRepository.searchBy(findVorgangRequest);
 		} catch (DataAccessResourceFailureException e) {
 			throw new SearchServiceUnavailableException(e);
 		}
 	}
 
-	private SearchRequest buildSearchRequest(FindVorgangRequest request) {
-		return SearchRequest.builder()
-				.limit(request.getLimit())
-				.offSet(request.getOffset())
-				.query(request.getSearchBy())
-				.status(request.getFilterBy().getStatus().stream().map(Status::name).toList())
-				.filterByOrganisationseinheitIds(request.getFilterBy().isFilterByOrganisationseinheitenId())
-				.assignedTo(request.getFilterBy().getAssignedTo())
-				.organisationseinheitIds(request.getFilterBy().getOrganisationseinheitIds()).build();
+	public void deleteVorgang(String vorgangId) {
+		repository.deleteById(vorgangId);
+	}
+
+	public void setAktenzeichen(String vorgangId, String aktenzeichen) {
+		searchRepository.update(vorgangId, Collections.singletonMap(IndexedVorgang.FIELD_AKTENZEICHEN, aktenzeichen));
 	}
+
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepostitory.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepository.java
similarity index 68%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepostitory.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepository.java
index 97916f47445cb2e5feef580b4cdc310e5bca4afb..8ca9e2f84cfe21538e4287eae275b38ea1f6bd32 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangCustomRepostitory.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
+
+import java.util.Map;
 
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.data.domain.Page;
 
-import de.itvsh.ozg.pluto.vorgang.VorgangHeader;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangHeader;
+
+@ConditionalOnProperty(prefix = "ozgcloud.elasticsearch", name = "address")
+interface SearchVorgangCustomRepository {
+	Page<VorgangHeader> searchBy(FindVorgangRequest request);
 
-@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "uris")
-interface SearchVorgangCustomRepostitory {
-	Page<VorgangHeader> searchBy(SearchRequest request);
+	void update(String vorangId, Map<String, Object> patch);
 }
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryImpl.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..da3916c0e3fad0274a6c42de145886bbc0b02c84
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryImpl.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.search;
+
+import static de.ozgcloud.vorgang.common.search.IndexedVorgang.*;
+import static java.util.Objects.*;
+import static org.apache.commons.collections4.MapUtils.*;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
+import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
+import org.springframework.data.elasticsearch.core.RefreshPolicy;
+import org.springframework.data.elasticsearch.core.ScriptType;
+import org.springframework.data.elasticsearch.core.SearchHit;
+import org.springframework.data.elasticsearch.core.SearchHits;
+import org.springframework.data.elasticsearch.core.document.Document;
+import org.springframework.data.elasticsearch.core.query.UpdateQuery;
+import org.springframework.data.support.PageableExecutionUtils;
+import org.springframework.stereotype.Repository;
+
+import co.elastic.clients.elasticsearch._types.FieldValue;
+import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
+import co.elastic.clients.elasticsearch._types.query_dsl.Query;
+import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
+import de.ozgcloud.vorgang.vorgang.FilterCriteria;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangHeader;
+
+@Repository
+class SearchVorgangCustomRepositoryImpl implements SearchVorgangCustomRepository {
+
+	private static final Pattern SPECIAL_CHARACTERS_PATTERN = Pattern.compile("[+\\-=]|(&&)|(\\|\\|)|[!(){}\\[\\]^\"~*?:\\\\/]");
+
+	private static final String SCRIPT_REMOVE_FIELD_TEMPLATE = "ctx._source.remove('%s')";
+
+	private static final String JOIN_AND = " AND ";
+	private static final String KEYWORD = ".keyword";
+
+	private static final String STATUS = FIELD_STATUS + KEYWORD;
+	private static final String ASSIGNED_TO = FIELD_ASSIGNED_TO + KEYWORD;
+
+	private static final float DEFAULT_BOOST = 1f;
+	private static final float HALF_BOOST = 0.5f;
+	private static final float DOUBLE_BOOST = 2f;
+
+	private static final List<String> FIELD_LIST = List.of(
+			FIELD_NAME + "^" + HALF_BOOST,
+			FIELD_VORGANG_NUMMER + "^" + DOUBLE_BOOST,
+			FIELD_AKTENZEICHEN + "^" + DOUBLE_BOOST,
+			FIELD_ANTRAGSTELLER_NAME + "^" + DEFAULT_BOOST,
+			FIELD_ANTRAGSTELLTER_VORNAME + "^" + DEFAULT_BOOST);
+
+	@Autowired
+	private ElasticsearchOperations elasticsearchOperations;
+
+	@Autowired
+	private IndexedVorgangMapper mapper;
+
+	@Override
+	public Page<VorgangHeader> searchBy(FindVorgangRequest request) {
+		var pageable = buildPageable(request);
+		var searchQuery = buildQueryBuilder(request).withPageable(pageable).build();
+
+		var result = elasticsearchOperations.search(searchQuery, IndexedVorgang.class);
+
+		return PageableExecutionUtils.getPage(mapResult(result), pageable, result::getTotalHits);
+	}
+
+	PageRequest buildPageable(FindVorgangRequest request) {
+		return PageRequest.of(request.getOffset() / request.getLimit(), request.getLimit());
+	}
+
+	NativeQueryBuilder buildQueryBuilder(FindVorgangRequest request) {
+		var queryBuilder = new NativeQueryBuilder();
+
+		queryBuilder.withQuery(buildSearchByQueryBuilder(request));
+		queryBuilder.withFilter(buildFilterByQueryBuilder(request.getFilterBy()));
+
+		return queryBuilder;
+	}
+
+	Query buildSearchByQueryBuilder(FindVorgangRequest request) {
+		var searchBy = Arrays.stream(request.getSearchBy().strip().split(StringUtils.SPACE)).map(this::adjustSearchTerm)
+				.collect(Collectors.joining(JOIN_AND));
+		return QueryBuilders.queryString(b -> b.query(searchBy).fields(FIELD_LIST));
+	}
+
+	String adjustSearchTerm(String searchTerm) {
+		var resultBuilder = new StringBuilder("(*");
+		var lastEnd = 0;
+		var matcher = SPECIAL_CHARACTERS_PATTERN.matcher(searchTerm);
+		while (matcher.find()) {
+			var start = matcher.start();
+			var end = matcher.end();
+			resultBuilder.append(searchTerm, lastEnd, start).append("\\").append(searchTerm, start, end);
+			lastEnd = end;
+		}
+		if (lastEnd < searchTerm.length()) {
+			resultBuilder.append(searchTerm, lastEnd, searchTerm.length());
+		}
+		return replaceNotAllowedCharacters(resultBuilder.append("*)").toString());
+	}
+
+	String replaceNotAllowedCharacters(String searchTerm) {
+		return searchTerm.replaceAll("[><]", "?");
+	}
+
+	private Query buildFilterByQueryBuilder(FilterCriteria filterCriteria) {
+		var queryBuilder = QueryBuilders.bool();
+
+		if (filterCriteria.isFilterByOrganisationseinheitenId()) {
+			queryBuilder.must(buildTermQuery(FIELD_ORGANISATIONSEINHEITEN_ID, filterCriteria.getOrganisationseinheitIds().stream()));
+		}
+		if (filterCriteria.isFilterByAssignedTo()) {
+			addAssignedToFilter(queryBuilder, filterCriteria);
+		}
+		if (CollectionUtils.isNotEmpty(filterCriteria.getStatus())) {
+			queryBuilder.must(buildStatusQueryBuilder(filterCriteria));
+		}
+		return queryBuilder.build()._toQuery();
+	}
+
+	private void addAssignedToFilter(BoolQuery.Builder query, FilterCriteria filterCriteria) {
+		if (StringUtils.isNotEmpty(filterCriteria.getAssignedTo())) {
+			query.must(buildTermQuery(ASSIGNED_TO, filterCriteria.getAssignedTo()));
+		} else {
+			query.mustNot(QueryBuilders.exists(e -> e.field(ASSIGNED_TO)));
+		}
+	}
+
+	private Query buildStatusQueryBuilder(FilterCriteria filterCriteria) {
+		return buildTermQuery(STATUS, filterCriteria.getStatus().stream().map(Vorgang.Status::name));
+	}
+
+	private Query buildTermQuery(String field, String value) {
+		return QueryBuilders.term(ts -> ts.field(field).value(FieldValue.of(value)));
+	}
+
+	private Query buildTermQuery(String field, Stream<String> valueStream) {
+		return QueryBuilders.terms(ts -> ts.field(field).terms(t -> t.value(valueStream.map(FieldValue::of).toList())));
+	}
+
+	private List<VorgangHeader> mapResult(SearchHits<IndexedVorgang> searchHits) {
+		return searchHits.get().map(SearchHit::getContent).map(mapper::toVorgangHeader).toList();
+	}
+
+	public void update(String vorgangId, Map<String, Object> patch) {
+		var fieldsToRemove = getFieldsToRemove(patch);
+		if (CollectionUtils.isNotEmpty(fieldsToRemove)) {
+			executeUpdate(buildUpdateQueryWithScript(vorgangId, buildRemoveFieldScript(fieldsToRemove)));
+		}
+		var fieldsToUpdate = getFieldsToUpdate(patch);
+		if (isNotEmpty(fieldsToUpdate)) {
+			executeUpdate(buildUpdateQueryWithDocument(vorgangId, fieldsToUpdate));
+		}
+	}
+
+	Set<String> getFieldsToRemove(Map<String, Object> patch) {
+		return patch.entrySet().stream().filter(e -> isNull(e.getValue())).map(Map.Entry::getKey).collect(Collectors.toSet());
+	}
+
+	String buildRemoveFieldScript(Collection<String> fields) {
+		return fields.stream().map(SCRIPT_REMOVE_FIELD_TEMPLATE::formatted).collect(Collectors.joining(";"));
+	}
+
+	UpdateQuery buildUpdateQueryWithScript(String vorgangId, String script) {
+		return createUpdateBuilder(vorgangId).withScriptType(ScriptType.INLINE).withScript(script).build();
+	}
+
+	Map<String, Object> getFieldsToUpdate(Map<String, Object> patch) {
+		return patch.entrySet().stream().filter(e -> nonNull(e.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+	}
+
+	UpdateQuery buildUpdateQueryWithDocument(String vorgangId, Map<String, Object> fieldMap) {
+		return createUpdateBuilder(vorgangId).withDocument(Document.from(fieldMap)).build();
+	}
+
+	UpdateQuery.Builder createUpdateBuilder(String vorgangId) {
+		return UpdateQuery.builder(vorgangId).withRefreshPolicy(RefreshPolicy.IMMEDIATE);
+	}
+
+	void executeUpdate(UpdateQuery updateQuery) {
+		elasticsearchOperations.update(updateQuery, elasticsearchOperations.indexOps(IndexedVorgang.class).getIndexCoordinates());
+	}
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangRepostitory.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangRepository.java
similarity index 79%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangRepostitory.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangRepository.java
index 3578944cbe161cf84fb452c7a96d6c938d6cfb63..b7a4f141fca8b72bfc9e75e3bf8848f267004199 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/search/SearchVorgangRepostitory.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/search/SearchVorgangRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
 
-@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "uris")
-interface SearchVorgangRepostitory extends ElasticsearchRepository<IndexedVorgang, String> {
+@ConditionalOnProperty(prefix = "ozgcloud.elasticsearch", name = "address")
+interface SearchVorgangRepository extends ElasticsearchRepository<IndexedVorgang, String> {
 }
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/security/PolicyRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/security/PolicyRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6098ce9a853f443632d98a0f6bbc555232764a9
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/security/PolicyRepository.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.security;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+import org.bson.Document;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.aggregation.Aggregation;
+import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.stereotype.Repository;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
+import de.ozgcloud.vorgang.common.db.CriteriaUtil;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+
+@Repository
+class PolicyRepository {
+
+	private static final String VORANG_ID_AS_OBJECT_ID_FIELD = """
+			{"$addFields" : {"vorgangObjecId" : {"$toObjectId": "$vorgangId"}}}
+			""";
+	private static final String VORANG_ID_FROM_FILE_AS_OBJECT_ID_FIELD = """
+			{"$addFields" : {"vorgangObjecId" : {"$toObjectId": "$metadata.vorgangId"}}}
+			""";
+	private static final AggregationOperation ADD_VORGANG_OBJECT_ID_FIELD = context -> org.bson.Document.parse(VORANG_ID_AS_OBJECT_ID_FIELD);
+
+	private static final AggregationOperation ADD_VORGANG_FROM_FILE = context -> org.bson.Document.parse(VORANG_ID_FROM_FILE_AS_OBJECT_ID_FIELD);
+
+	public static final String FIELD_ORGANISATIONSEINHEIT_ID = "organisationseinheitenId";
+	public static final String FIELD_VORGANG = "vorgang";
+	public static final String FIELD_VORGANG_ORGANISATIONSEINHEIT = FIELD_VORGANG + "." + Vorgang.FIELD_ORGANISATIONSEINHEIT;
+
+	@Autowired
+	private MongoTemplate template;
+
+	public boolean existsByCommandId(String commandId, Collection<String> organisationEinheitenIds) {
+		var document = executeAggregation(buildAggregation(matchId(commandId), ADD_VORGANG_OBJECT_ID_FIELD), Command.class).orElseThrow(
+				() -> new NotFoundException(Command.class, commandId));
+		return evaluateOrganisationseinheitId(document, organisationEinheitenIds);
+	}
+
+	public boolean existsByFileId(String fileId, Collection<String> organisationEinheitenIds) {
+		var resultDocument = executeAggregation(buildAggregation(matchId(fileId), ADD_VORGANG_FROM_FILE), "fs.files");
+		return resultDocument.map(document -> evaluateOrganisationseinheitId(document, organisationEinheitenIds)).orElse(false);
+	}
+
+	private AggregationOperation matchId(String id) {
+		return Aggregation.match(new Criteria(Vorgang.MONGODB_FIELDNAME_ID).is(id));
+	}
+
+	public boolean existsByVorgangAttachedItem(String vorgangAttachedItemId, Collection<String> organisationEinheitenIds) {
+		var result = executeAggregation(buildAggregation(matchVorgangAttachedItemId(vorgangAttachedItemId), ADD_VORGANG_OBJECT_ID_FIELD),
+				VorgangAttachedItem.class).orElseThrow(() -> new NotFoundException(VorgangAttachedItem.class, vorgangAttachedItemId));
+		return evaluateOrganisationseinheitId(result, organisationEinheitenIds);
+	}
+
+	private AggregationOperation matchVorgangAttachedItemId(String id) {
+		return Aggregation.match(CriteriaUtil.isId(id).and(VorgangAttachedItem.FIELDNAME_IS_DELETED).is(false));
+	}
+
+	private Aggregation buildAggregation(AggregationOperation idAggregation, AggregationOperation operation) {
+		return Aggregation.newAggregation(Arrays.asList(
+				idAggregation,
+				operation,
+				lookupVorgang(),
+				Aggregation.project().and(FIELD_VORGANG_ORGANISATIONSEINHEIT).as(FIELD_ORGANISATIONSEINHEIT_ID)
+		));
+	}
+
+	private AggregationOperation lookupVorgang() {
+		return Aggregation.lookup(Vorgang.COLLECTION_NAME, "vorgangObjecId", "_id", FIELD_VORGANG);
+	}
+
+	private Optional<Document> executeAggregation(Aggregation aggregation, Class<?> inputType) {
+		var results = template.aggregate(aggregation, inputType, Document.class).getRawResults();
+		return getResult(results);
+	}
+
+	private Optional<Document> executeAggregation(Aggregation aggregation, String collectionName) {
+		var results = template.aggregate(aggregation, collectionName, Document.class).getRawResults();
+		return getResult(results);
+	}
+
+	Optional<Document> getResult(Document aggregationResult) {
+		return aggregationResult.getList("results", Document.class).stream().findFirst();
+	}
+
+	boolean evaluateOrganisationseinheitId(Document result, Collection<String> organisationEinheitenIds) {
+		var nestedList = result.getList(FIELD_ORGANISATIONSEINHEIT_ID, Object.class);
+		if (nestedList.isEmpty()) {
+			return false;
+		}
+		var organisationseinheitenId = nestedList.get(0);
+		if (organisationseinheitenId instanceof List<?> orgaIdList) {
+			return orgaIdList.stream().map(String::valueOf).anyMatch(organisationEinheitenIds::contains);
+		}
+		return organisationEinheitenIds.contains(String.valueOf(organisationseinheitenId));
+	}
+
+}
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/security/PolicyService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/security/PolicyService.java
similarity index 86%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/common/security/PolicyService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/security/PolicyService.java
index 8b92bea26dca7f61226b761be755d924727d320d..9e2f59da27bbfc444c5a52cb1a68f36911f460fe 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/security/PolicyService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/security/PolicyService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.security;
+package de.ozgcloud.vorgang.common.security;
 
 import java.util.List;
 import java.util.Set;
@@ -33,12 +33,12 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.AccessDeniedException;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUser;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
+import de.ozgcloud.vorgang.callcontext.CallContextUser;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
 
 @Service
 public class PolicyService {
@@ -81,7 +81,7 @@ public class PolicyService {
 	}
 
 	public void checkPermissionByVorgangAttachedItem(String vorgangAttachedItemId) {
-		evaluatePermissions(List.of(hasOrganisationEinheitenIdByVorgangAttachedItem(vorgangAttachedItemId)).stream(), VorgangAttachedItem.class,
+		evaluatePermissions(Stream.of(hasOrganisationEinheitenIdByVorgangAttachedItem(vorgangAttachedItemId)), VorgangAttachedItem.class,
 				vorgangAttachedItemId);
 	}
 
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigRemoteService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c47f05dc16e1b434b7f5eba931b7d4c2691f4e1
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigRemoteService.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.userconfig;
+
+import java.util.List;
+
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.user.grpc.organisationseinheit.OrganisationsEinheitServiceGrpc.OrganisationsEinheitServiceBlockingStub;
+import de.ozgcloud.user.organisationseinheit.GrpcGetSupportedOrganisationsEinheitenRequest;
+import de.ozgcloud.user.organisationseinheit.GrpcOrganisationsEinheit;
+import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Service
+public class UserConfigRemoteService {
+
+	@GrpcClient("user-manager")
+	private OrganisationsEinheitServiceBlockingStub serviceStub;
+
+	public List<String> getSupportedOrganisationsEinheiten() {
+		return getOrganisationsEinheiten().stream().map(GrpcOrganisationsEinheit::getOrganisationsEinheitId)
+				.toList();
+	}
+
+	List<GrpcOrganisationsEinheit> getOrganisationsEinheiten() {
+		return getServiceStub()
+				.getSupportedOrganisationsEinheiten(GrpcGetSupportedOrganisationsEinheitenRequest.newBuilder().build())
+				.getOrganisationseinheitenList();
+	}
+
+	private OrganisationsEinheitServiceBlockingStub getServiceStub() {
+		return serviceStub.withInterceptors(new VorgangManagerClientCallContextAttachingInterceptor());
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4462fe3311e43f1ed85c99eec1773ad7d31b639
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/common/userconfig/UserConfigService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.userconfig;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class UserConfigService {
+	@Autowired
+	private UserConfigRemoteService userConfigRemoteService;
+
+	public List<String> getSupportedOrganisationsEinheiten() {
+		return userConfigRemoteService.getSupportedOrganisationsEinheiten();
+	}
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/BinaryFileRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/BinaryFileRepository.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/BinaryFileRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/BinaryFileRepository.java
index 23151d1d698547d71d5960dd990271829b2f9361..c3425738771e7d2e24752432e58bdfc4ba4a21ab 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/BinaryFileRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/BinaryFileRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
+
+import static org.springframework.data.mongodb.core.query.Criteria.*;
+import static org.springframework.data.mongodb.core.query.Query.*;
 
 import java.io.InputStream;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
@@ -92,6 +96,7 @@ class BinaryFileRepository {
 		return StreamSupport.stream(fileIds.spliterator(), false)
 				.map(FileId::from)
 				.map(this::getFile)
+				.filter(Objects::nonNull)
 				.map(this::mapToOzgFile);
 	}
 
@@ -112,4 +117,8 @@ class BinaryFileRepository {
 				.contentType((String) gridFile.getMetadata().getOrDefault(CONTENT_TYPE, StringUtils.EMPTY))
 				.build();
 	}
+
+	public void deleteAllByVorgang(String vorgangId) {
+		gridFsTemplate.delete(query(where("metadata." + VORGANG_ID).is(vorgangId)));
+	}
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/EingangFilesRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/EingangFilesRepository.java
similarity index 96%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/EingangFilesRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/EingangFilesRepository.java
index 9d534b342a720f35a384f1583500f7ed230de189..9240cba9614944881f9e20c68ed680faaa386379 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/EingangFilesRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/EingangFilesRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -33,7 +33,7 @@ import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.stereotype.Repository;
 
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
 
 @Repository
 class EingangFilesRepository {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileId.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileId.java
similarity index 89%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileId.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileId.java
index 321ee3f55effb574a94f5ca064cb7aceb6479f27..f84ff2bb18c18bfde4a36ee6b4fe5e9be8356c23 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileId.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileId.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.util.UUID;
 
-import de.itvsh.kop.common.datatype.StringBasedValue;
+import de.ozgcloud.common.datatype.StringBasedValue;
 import lombok.EqualsAndHashCode;
 
 @EqualsAndHashCode(callSuper = true)
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileIdMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileIdMapper.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileIdMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileIdMapper.java
index b982e9766467584944d81e3097d11d8b9e63d46c..a55acfe2421f79e62fbcbcb13e9ff1139bb0f067 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileIdMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileIdMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import org.mapstruct.Mapper;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileService.java
similarity index 77%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileService.java
index 8b323c9088e7fee5776b585a66bddeb6fe87e7e7..043060ae237edae142e33c407a3ae101a6c4c335 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/FileService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/FileService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.io.InputStream;
 import java.util.Collection;
@@ -37,7 +37,7 @@ import org.springframework.stereotype.Service;
 
 import com.mongodb.client.gridfs.model.GridFSFile;
 
-import de.itvsh.ozg.mail.postfach.BinaryFileService;
+import de.ozgcloud.nachrichten.postfach.BinaryFileService;
 
 //TODO make service package protected, as soon PersistPostfachMailByCommandService and FileStreamService is gone
 @Service
@@ -60,8 +60,16 @@ public class FileService implements BinaryFileService {
 		return repository.findRepresentationsByEingangId(eingangId);
 	}
 
-	@Async
 	public CompletableFuture<FileId> uploadFileStream(UploadedFilesReference ref, OzgFile file, Optional<String> userId, InputStream content) {
+		return uploadFile(ref, file, userId, content);
+	}
+
+	@Async
+	public CompletableFuture<FileId> uploadFileStreamAsync(UploadedFilesReference ref, OzgFile file, Optional<String> userId, InputStream content) {
+		return uploadFile(ref, file, userId, content);
+	}
+
+	CompletableFuture<FileId> uploadFile(UploadedFilesReference ref, OzgFile file, Optional<String> userId, InputStream content) {
 		return CompletableFuture.completedFuture(binaryFileRepository.addContentStream(ref, file, userId, content));
 	}
 
@@ -70,12 +78,12 @@ public class FileService implements BinaryFileService {
 	}
 
 	@Override
-	public InputStream getUploadedFileStream(de.itvsh.ozg.mail.postfach.FileId fileId) {
+	public InputStream getUploadedFileStream(de.ozgcloud.nachrichten.postfach.FileId fileId) {
 		return binaryFileRepository.getFileContent(FileId.from(fileId.toString()));
 	}
 
 	@Override
-	public GridFSFile getFile(de.itvsh.ozg.mail.postfach.FileId fileId) {
+	public GridFSFile getFile(de.ozgcloud.nachrichten.postfach.FileId fileId) {
 		return binaryFileRepository.getFile(FileId.from(fileId.toString()));
 	}
 
@@ -86,4 +94,8 @@ public class FileService implements BinaryFileService {
 	private Iterable<String> mapFileIdToString(Collection<FileId> ids) {
 		return ids.stream().map(fileIdMapper::toString).toList();
 	}
+
+	public void deleteAllByVorgang(String vorgangId) {
+		binaryFileRepository.deleteAllByVorgang(vorgangId);
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcBinaryFileService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcBinaryFileService.java
similarity index 85%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcBinaryFileService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcBinaryFileService.java
index a66e8e966bda095f8664a6818c9dec0b78c3ddb0..386094e3e2cc092cc3366aa147038c7a692c9ae0 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcBinaryFileService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcBinaryFileService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.io.BufferedInputStream;
 import java.io.IOException;
@@ -35,15 +35,15 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 import com.google.protobuf.ByteString;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceImplBase;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcBinaryFilesRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcFindFilesResponse;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileResponse;
+import de.ozgcloud.nachrichten.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceImplBase;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcBinaryFilesRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcFindFilesResponse;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileResponse;
 import io.grpc.stub.CallStreamObserver;
 import io.grpc.stub.StreamObserver;
 import lombok.extern.log4j.Log4j2;
@@ -54,7 +54,7 @@ import net.devh.boot.grpc.server.service.GrpcService;
 public class GrpcBinaryFileService extends BinaryFileServiceImplBase {
 
 	// FIXME use client from security context
-	static final String CLIENT = "goofy"; // currently single client is hardcoded
+	static final String CLIENT = "Alfa"; // currently single client is hardcoded
 
 	@Autowired
 	private FileService service;
@@ -110,7 +110,7 @@ public class GrpcBinaryFileService extends BinaryFileServiceImplBase {
 
 	void sendChunks(CallStreamObserver<GrpcGetBinaryFileDataResponse> callObserver, InputStream fileStream, AtomicBoolean doSendFile) {
 		try {
-			// TODO remove additional flow control when goofy side has been fixed see
+			// TODO remove additional flow control when alfa side has been fixed see
 			// OZG-2631
 			if (doSendFile.get()) {
 				int size = sendNextChunk(callObserver, fileStream);
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcFileService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcFileService.java
similarity index 81%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcFileService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcFileService.java
index a0c0d488ca4ce2127cc8a5e60972801d56c1e156..09bd372e7bcc03b6b3363d1689dd455bdd31b6df 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcFileService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcFileService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,17 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.util.List;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.ozg.pluto.grpc.file.FileServiceGrpc.FileServiceImplBase;
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetAttachmentsRequest;
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetAttachmentsResponse;
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetRepresentationsRequest;
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetRepresentationsResponse;
+import de.ozgcloud.vorgang.grpc.file.FileServiceGrpc.FileServiceImplBase;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetAttachmentsRequest;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetAttachmentsResponse;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetRepresentationsRequest;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetRepresentationsResponse;
 import io.grpc.stub.StreamObserver;
 import net.devh.boot.grpc.server.service.GrpcService;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcOzgFileMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcOzgFileMapper.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcOzgFileMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcOzgFileMapper.java
index 8f5655c9653425a581f8d38c1b13da158ad36bc8..e7c93bf1726baf9f94bde95bbbff566b34740cd1 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/GrpcOzgFileMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/GrpcOzgFileMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.util.List;
 
@@ -29,7 +29,7 @@ import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.NullValueCheckStrategy;
 
-import de.itvsh.ozg.pluto.grpc.file.GrpcOzgFile;
+import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
 
 // TODO rename to GrpcBinaryFileMapper
 /**
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/OzgFile.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/OzgFile.java
similarity index 86%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/OzgFile.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/OzgFile.java
index edbd4a28c999d6d4596ce2664d770eff2050a8b0..feb172c6029c30cb8e09efdda6fcd384155756ac 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/OzgFile.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/OzgFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
@@ -30,15 +30,11 @@ import lombok.Getter;
 import lombok.ToString;
 
 // TODO: Rename to BinaryFile
-/**
- * @deprecated Will be renamed to BinaryFile
- *
- */
+
 @Builder(toBuilder = true)
 @ToString
 @Getter
 @AllArgsConstructor(access = AccessLevel.PUBLIC)
-@Deprecated(since = "0.25", forRemoval = true)
 public class OzgFile {
 
 	private FileId id;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/UploadStreamObserver.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/UploadStreamObserver.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/UploadStreamObserver.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/UploadStreamObserver.java
index b758bae27d2cd9a9a0c36b3042bf84ae7a81bc2c..253eafa6fac242afe95b129daf0a7119ee8c399d 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/UploadStreamObserver.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/UploadStreamObserver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.io.IOException;
 import java.io.PipedInputStream;
@@ -33,10 +33,10 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileResponse;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileResponse;
 import io.grpc.stub.StreamObserver;
 import lombok.AccessLevel;
 import lombok.Getter;
@@ -102,7 +102,7 @@ class UploadStreamObserver implements StreamObserver<GrpcUploadBinaryFileRequest
 	CompletableFuture<FileId> storeMetaData(GrpcUploadBinaryFileRequest fileUploadRequest) {
 		var userId = fileUploadRequest.getMetadata().getContext().getUser().getId();
 
-		return service.uploadFileStream(
+		return service.uploadFileStreamAsync(
 				buildUploadFilesReferences(fileUploadRequest),
 				buildOzgFile(fileUploadRequest),
 				Optional.of(userId), pipedInput);
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/UploadedFilesReference.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/UploadedFilesReference.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/files/UploadedFilesReference.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/UploadedFilesReference.java
index 9708c03e15d7bd93621f7461f0c3e75f71788e5d..b123c6f28cb501c3937d42c4b22c2fb5d84a9942 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/files/UploadedFilesReference.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/files/UploadedFilesReference.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import lombok.Builder;
 import lombok.Getter;
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..c604a83127557259d276051df46f72921f61585e
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryScheduler.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.registry;
+
+import java.util.concurrent.TimeUnit;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.vorgang.common.userconfig.UserConfigService;
+import lombok.extern.log4j.Log4j2;
+import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
+
+@Profile("!itcase")
+@Component
+@ConditionalOnProperty(prefix = "ozgcloud.vorgang-manager", name = { "address" })
+@Log4j2
+class RegistryScheduler {
+	@Autowired
+	private RegistryService registryService;
+
+	@Autowired
+	private UserConfigService userConfigService;
+
+	@Scheduled(fixedDelayString = "${ozgcloud.vorgang-manager.registry.scheduler.fixedDelay:5}", //
+			initialDelayString = "${ozgcloud.vorgang-manager.registry.scheduler.initialDelay:5}", //
+			timeUnit = TimeUnit.MINUTES)
+	@SchedulerLock(name = "RegistryScheduler")
+	void register() {
+		try {
+			registryService.registerVorgangManager(userConfigService.getSupportedOrganisationsEinheiten());
+		} catch (Exception e) {
+			LOG.error("Error registering VorgangManager", e);
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5e3618af3f9574e688ab832eb1a85ea503232e2
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/RegistryService.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.registry;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import lombok.extern.log4j.Log4j2;
+
+@Service
+@Log4j2
+class RegistryService {
+	@Value(value = "${ozgcloud.vorgang-manager.address:#{null}}")
+	private Optional<String> vorgangManagerAddress;
+
+	@Autowired
+	private ZufiRemoteService zufiRemoteService;
+
+	public void registerVorgangManager(List<String> supportedOrganisationsEinheiten) {
+		try {
+			register(supportedOrganisationsEinheiten);
+		} catch (Exception e) {
+			LOG.error("Error registering this VorgangsManager.", e);
+		}
+	}
+
+	private void register(List<String> supportedOrganisationsEinheiten) {
+		if (CollectionUtils.isNotEmpty(supportedOrganisationsEinheiten)) {
+			registerAddress(supportedOrganisationsEinheiten, vorgangManagerAddress);
+		} else {
+			LOG.warn("No OrganistationsEinheitenIds provided. Not registering this VorgangsManager");
+		}
+	}
+
+	void registerAddress(List<String> supportedOrganisationsEinheiten, Optional<String> vorgangManagerAddress) {
+		vorgangManagerAddress.ifPresentOrElse(address -> {
+			zufiRemoteService.registerVorgangManager(supportedOrganisationsEinheiten, address);
+		}, () -> LOG.error("Property ozgcloud.vorgang-manager.address not set. Not registering this VorgangsManager"));
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6355abdeaf4a34b8d5ad14792e703af8e2e2b69
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/registry/ZufiRemoteService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.registry;
+
+import java.util.List;
+
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor;
+import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationRequest;
+import de.ozgcloud.zufi.grpc.registration.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub;
+import lombok.NonNull;
+import lombok.extern.log4j.Log4j2;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Log4j2
+@Service
+class ZufiRemoteService {
+	@GrpcClient("zufi-manager")
+	private VorgangManagerRegistrationServiceBlockingStub serviceStub;
+
+	public void registerVorgangManager(@NonNull List<String> organistationsEinheitenIds, String vorgangManagerAddress) {
+		boolean success = getServiceStub()
+				.register(buildRequest(organistationsEinheitenIds, vorgangManagerAddress)).getSuccess();
+		LOG.info("Register success: " + success);
+	}
+
+	private VorgangManagerRegistrationServiceBlockingStub getServiceStub() {
+		return serviceStub.withInterceptors(new VorgangManagerClientCallContextAttachingInterceptor());
+	}
+
+	private GrpcVorgangManagerRegistrationRequest buildRequest(List<String> organistationsEinheitenIds, String address) {
+		return GrpcVorgangManagerRegistrationRequest.newBuilder().addAllOrganisationsEinheitenIds(organistationsEinheitenIds)
+				.setServiceAddress(address).build();
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/PostfachAddress.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/PostfachAddress.java
new file mode 100644
index 0000000000000000000000000000000000000000..651c6b626671151b4290c60878aebeda5803cee5
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/PostfachAddress.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.servicekonto;
+
+import java.util.Map;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+public class PostfachAddress {
+
+	public static final String IDENTIFIER_POSTFACH_ID_FIELD = "postfachId";
+
+	private String version;
+	private int type;
+	private Map<String, Object> identifier;
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/ServiceKonto.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/ServiceKonto.java
new file mode 100644
index 0000000000000000000000000000000000000000..eff05ad25f7e865e2761657f328357adfd9d55cd
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/ServiceKonto.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.servicekonto;
+
+import java.util.List;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.Singular;
+
+@Getter
+@Builder
+@Setter
+public class ServiceKonto {
+
+	public static final String OSI_IDENTIFIER = "OSI";
+
+	private String type;
+	@Singular
+	private List<PostfachAddress> postfachAddresses;
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..c3e12faa0457953aa11adaf56ea8d8a59f4d5a8e
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoMapper.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.servicekonto;
+
+import org.mapstruct.CollectionMappingStrategy;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.NullValueCheckStrategy;
+import org.mapstruct.NullValuePropertyMappingStrategy;
+import org.mapstruct.ReportingPolicy;
+
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN,
+		unmappedSourcePolicy = ReportingPolicy.WARN, 
+		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, 
+		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
+		collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
+		uses = GrpcObjectMapper.class)
+public interface ServiceKontoMapper {
+
+	@Mapping(target = "postfachAddresses", source = "postfachAddressesList")
+	ServiceKonto fromServiceKonto(GrpcServiceKonto serviceKonto);
+
+	@Mapping(target = "postfachAddressesList", source = "postfachAddresses")
+	GrpcServiceKonto toServiceKonto(ServiceKonto serviceKonto);
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountByPath.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountByPath.java
new file mode 100644
index 0000000000000000000000000000000000000000..427ca78d9ce79357121ddae7bbe3562c1cda6bb9
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountByPath.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+class CountByPath{
+
+	private String fieldPath;
+	private String alias;
+
+	public static CountByPath fromStatisticRequest(VorgangStatisticRequest statisticRequest) {
+		return CountByPath.builder().fieldPath(statisticRequest.getFieldPath()).alias(statisticRequest.getResultName()).build();
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountResult.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..8cc4f2ca3e44c15bf5778a1ab33510f4daa12221
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountResult.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+
+@Builder
+@Getter
+@EqualsAndHashCode
+public class CountResult {
+	static final String KEY_NAME = "name";
+	static final String KEY_VALUE = "value";
+
+	private String name;
+	private int value;
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountStatisticMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountStatisticMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..7cd60d971b89d188c97741eea95e52ce5b825d8b
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/CountStatisticMapper.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+
+@Component
+class CountStatisticMapper {
+
+	static final Pattern PATH_COUNT_REQUEST_PATTERN = Pattern.compile(".+:.+");
+	static final String PATH_COUNT_REQUEST_SEPARATOR = ":";
+
+	GrpcVorgangCountResponse mapTo(Statistic statistic) {
+		return GrpcVorgangCountResponse.newBuilder()
+				.setByStatus(mapToByStatus(statistic))
+				.addAllPathCountResult(mapToPathCountResults(statistic))
+				.build();
+	}
+
+	GrpcByStatusResult mapToByStatus(Statistic statistic) {
+		var counterByStatus = statistic.getCountByStatus();
+		return GrpcByStatusResult.newBuilder()
+				.setNeu(counterByStatus.get(Vorgang.Status.NEU))
+				.setAngenommen(counterByStatus.get(Vorgang.Status.ANGENOMMEN))
+				.setVerworfen(counterByStatus.get(Vorgang.Status.VERWORFEN))
+				.setInBearbeitung(counterByStatus.get(Vorgang.Status.IN_BEARBEITUNG))
+				.setBeschieden(counterByStatus.get(Vorgang.Status.BESCHIEDEN))
+				.setAbgeschlossen(counterByStatus.get(Vorgang.Status.ABGESCHLOSSEN))
+				.setWeitergeleitet(counterByStatus.get(Vorgang.Status.WEITERGELEITET))
+				.build();
+	}
+
+	private List<GrpcPathCountResult> mapToPathCountResults(Statistic statistic) {
+		return statistic.getCountResult().entrySet().stream().map(this::mapToPathCountResult).toList();
+	}
+
+	private GrpcPathCountResult mapToPathCountResult(Entry<String, Integer> countPathEntry) {
+		return GrpcPathCountResult.newBuilder().setName(countPathEntry.getKey()).setValue(countPathEntry.getValue()).build();
+	}
+
+	public VorgangCountRequest mapFromVorgangCountRequest(GrpcVorgangCountRequest request) {
+		return VorgangCountRequest.builder().countByPaths(mapFromCountByPathRequest(request.getCountByPathList())).build();
+	}
+
+	List<CountByPath> mapFromCountByPathRequest(List<String> countByPathRequests) {
+		return countByPathRequests.stream().filter(StringUtils::isNoneBlank).map(this::mapPathCountRequest).toList();
+	}
+
+	CountByPath mapPathCountRequest(String pathCountRequest) {
+		return CountByPath.builder().alias(extractAlias(pathCountRequest)).fieldPath(extractFieldPath(pathCountRequest)).build();
+	}
+
+	String extractFieldPath(String pathCountRequest) {
+		validatePathCountRequest(pathCountRequest);
+		return pathCountRequest.split(PATH_COUNT_REQUEST_SEPARATOR)[1];
+	}
+
+	String extractAlias(String pathCountRequest) {
+		validatePathCountRequest(pathCountRequest);
+		return pathCountRequest.split(PATH_COUNT_REQUEST_SEPARATOR)[0];
+	}
+
+	void validatePathCountRequest(String pathCountRequest) {
+		if (!PATH_COUNT_REQUEST_PATTERN.matcher(pathCountRequest).matches()) {
+			throw new VorgangStatisticBadRequestException(
+					"Invalid path count request. Expected format 'alias:path.to.field' but was: '%s'".formatted(pathCountRequest));
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/InvalidFieldPathException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/InvalidFieldPathException.java
new file mode 100644
index 0000000000000000000000000000000000000000..01728294d07b88570a80164eeebcbdc1179820f8
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/InvalidFieldPathException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import de.ozgcloud.vorgang.common.errorhandling.FunctionalException;
+
+public class InvalidFieldPathException extends FunctionalException {
+
+	public InvalidFieldPathException() {
+		super(() -> "statistic.invalid.path");
+
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/Statistic.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/Statistic.java
new file mode 100644
index 0000000000000000000000000000000000000000..f7958e039dd5c10b75350df6667f9d9824dc7315
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/Statistic.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Singular;
+
+@Builder
+@Getter
+class Statistic {
+
+	@Singular("addStatusCount")
+	private Map<Vorgang.Status, Integer> countByStatus;
+
+	@Builder.Default
+	private Map<String, Integer> countResult = new HashMap<>();
+
+	@Builder.Default
+	private Map<String, Boolean> existsResult = new HashMap<>();
+
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticFilter.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..361d860a5ef165b5bf2c34d7a780e506883cd3fb
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticFilter.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.apache.commons.collections4.CollectionUtils.*;
+
+import java.util.Collection;
+
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import de.ozgcloud.vorgang.common.db.CriteriaUtil;
+import lombok.Builder;
+import lombok.Singular;
+
+@Builder
+class StatisticFilter {
+
+	@Builder.Default
+	private Criteria filterCriteria = new Criteria();
+
+	@Singular
+	private Collection<String> organisationsEinheitIds;
+
+	public Criteria getCriteria() {
+		return CriteriaUtil.vorgangNotInCreation().andOperator(getOrganisationsEinheitIdCriteria(), filterCriteria);
+	}
+
+	public Criteria getOrganisationsEinheitIdCriteria() {
+		if (isEmpty(organisationsEinheitIds)) {
+			return new Criteria();
+		}
+		return CriteriaUtil.inOrganisationseinheitenIds(organisationsEinheitIds);
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticGroupMethod.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticGroupMethod.java
new file mode 100644
index 0000000000000000000000000000000000000000..231ad37fc9e44c6daebe4bd0f8bbb11ac94241c4
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticGroupMethod.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+public enum StatisticGroupMethod {
+
+	COUNT, EXISTS;
+
+	public static StatisticGroupMethod from(GrpcVorgangStatisticQuery.GroupMethod groupMethod) {
+		return switch (groupMethod) {
+			case COUNT -> COUNT;
+			case EXISTS -> EXISTS;
+			case UNRECOGNIZED -> throw new VorgangStatisticBadRequestException("Unrecognized group method: " + groupMethod);
+		};
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticGrpcService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticGrpcService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0dddccbb9427a169efa54b7171a07f74ca9a686
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticGrpcService.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import io.grpc.stub.StreamObserver;
+import net.devh.boot.grpc.server.service.GrpcService;
+
+@GrpcService
+public class StatisticGrpcService extends StatisticServiceGrpc.StatisticServiceImplBase {
+
+	@Autowired
+	private StatisticService statisticService;
+	@Autowired
+	private CountStatisticMapper countStatisticMapper;
+	@Autowired
+	private StatisticMapper statisticMapper;
+
+	@Override
+	public void countVorgang(GrpcVorgangCountRequest request, StreamObserver<GrpcVorgangCountResponse> responseObserver) {
+		var statistic = statisticService.countVorgang(countStatisticMapper.mapFromVorgangCountRequest(request));
+
+		responseObserver.onNext(countStatisticMapper.mapTo(statistic));
+		responseObserver.onCompleted();
+	}
+
+	@Override
+	public void getVorgangStatistic(GrpcVorgangStatisticRequest request, StreamObserver<GrpcVorgangStatisticResponse> responseObserver) {
+		var statistic = statisticService.collectStatistic(statisticMapper.mapFromVorgangStatisticRequest(request));
+
+		responseObserver.onNext(statisticMapper.mapToVorgangStatisticResponse(statistic));
+		responseObserver.onCompleted();
+	}
+
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..c53bdc4b4559494145d6d85fce7d689d137c6c3a
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticMapper.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.vorgang.common.operator.OperandFunctionParser;
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+
+@Component
+class StatisticMapper {
+
+	@Autowired
+	private OperandFunctionParser operandFunctionParser;
+
+	public List<VorgangStatisticRequest> mapFromVorgangStatisticRequest(GrpcVorgangStatisticRequest grpcRequest) {
+		return grpcRequest.getQueryList().stream().map(this::mapFromVorgangStatisticQuery).toList();
+	}
+
+	VorgangStatisticRequest mapFromVorgangStatisticQuery(GrpcVorgangStatisticQuery statisticQuery) {
+		return VorgangStatisticRequest.builder()
+				.resultName(statisticQuery.getResultName())
+				.fieldPath(getFieldPath(statisticQuery))
+				.statisticGroupMethod(StatisticGroupMethod.from(statisticQuery.getGroupMethod()))
+				.operator(buildOperator(statisticQuery))
+				.build();
+	}
+
+	String getFieldPath(GrpcVorgangStatisticQuery statisticQuery) {
+		return statisticQuery.getPath().startsWith(Vorgang.FIELD_CLIENT_ATTRIBUTES)
+				? statisticQuery.getPath() + ".value"
+				: statisticQuery.getPath();
+	}
+
+	Operator buildOperator(GrpcVorgangStatisticQuery statisticQuery) {
+		return OperatorBuilder.from(statisticQuery.getOperator())
+				.fieldPath(statisticQuery.getPath())
+				.operand(getValue(statisticQuery)).build();
+	}
+
+	Object getValue(GrpcVorgangStatisticQuery statisticQuery) {
+		return switch (statisticQuery.getOperandCase()) {
+		case OPERANDBOOLVALUE -> statisticQuery.getOperandBoolValue();
+		case OPERANDINTVALUE -> statisticQuery.getOperandIntValue();
+		case OPERANDSTRINGVALUE -> getStringValue(statisticQuery);
+		case OPERAND_NOT_SET -> null;
+		};
+	}
+
+	String getStringValue(GrpcVorgangStatisticQuery statisticQuery) {
+		var operandStringValue = statisticQuery.getOperandStringValue();
+		if ("null".equalsIgnoreCase(operandStringValue)) {
+			return null;
+		} else if (operandStringValue.endsWith(")")) {
+			return operandFunctionParser.parse(operandStringValue);
+		}
+		return operandStringValue;
+	}
+
+	public GrpcVorgangStatisticResponse mapToVorgangStatisticResponse(Statistic statistic) {
+		return GrpcVorgangStatisticResponse.newBuilder()
+				.addAllResult(mapCountByPathStatistic(statistic.getCountResult()))
+				.addAllResult(mapIsFieldExistsStatistic(statistic.getExistsResult()))
+				.build();
+	}
+
+	List<GrpcVorgangStatisticResult> mapCountByPathStatistic(Map<String, Integer> countByPathStatistic) {
+		return countByPathStatistic.entrySet().stream().map(entry -> mapToCountResult(entry.getKey(), entry.getValue())).toList();
+	}
+
+	GrpcVorgangStatisticResult mapToCountResult(String key, Integer value) {
+		return GrpcVorgangStatisticResult.newBuilder().setName(key).setResultIntValue(value).build();
+	}
+
+	List<GrpcVorgangStatisticResult> mapIsFieldExistsStatistic(Map<String, Boolean> isFieldExistsStatistic) {
+		return isFieldExistsStatistic.entrySet().stream().map(entry -> mapToIsFieldExistsResult(entry.getKey(), entry.getValue())).toList();
+	}
+
+	GrpcVorgangStatisticResult mapToIsFieldExistsResult(String key, Boolean value) {
+		return GrpcVorgangStatisticResult.newBuilder().setName(key).setResultBoolValue(value).build();
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ce04e6bcb291a584f979793342cf3c21b87a1df
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticRepository.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import org.bson.Document;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.aggregation.AddFieldsOperation;
+import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
+import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
+import org.springframework.data.mongodb.core.aggregation.AggregationResults;
+import org.springframework.data.mongodb.core.aggregation.GroupOperation;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import lombok.NonNull;
+
+@Repository
+class StatisticRepository {
+
+	@Autowired
+	private MongoOperations mongoOperations;
+
+	public List<CountResult> countVorgangByStatus(StatisticFilter filter) {
+		var aggregationOperations = initAggregationOperations(filter);
+		var groupOperation = group(Vorgang.MONGODB_FIELDNAME_STATUS).count().as(CountResult.KEY_VALUE);
+		aggregationOperations.add(groupOperation);
+		var projectOperation = project(CountResult.KEY_VALUE).and(CountResult.KEY_NAME).previousOperation();
+		aggregationOperations.add(projectOperation);
+
+		return executeAggregation(CountResult.class, aggregationOperations).getMappedResults();
+	}
+
+	public List<CountResult> countVorgangByPath(CountByPath countByPaths, Operator operator, StatisticFilter filter) {
+		var aggregationOperations = initAggregationOperations(filter);
+		aggregationOperations.add(buildAddFieldOperation(countByPaths.getAlias(), operator.getAggregationExpression()));
+		aggregationOperations.add(buildGroupOperation(countByPaths));
+
+		var countByPathResults = executeAggregation(Document.class, aggregationOperations);
+		return mapCountByPathResults(countByPathResults.getUniqueMappedResult(), countByPaths.getAlias());
+	}
+
+	List<AggregationOperation> initAggregationOperations(StatisticFilter filter) {
+		var aggregationOperations = new ArrayList<AggregationOperation>();
+		aggregationOperations.add(match(filter.getCriteria()));
+		return aggregationOperations;
+	}
+
+	AddFieldsOperation buildAddFieldOperation(String alias, AggregationExpression aggregationExpression) {
+		return addFields().addFieldWithValue(alias, aggregationExpression).build();
+	}
+
+	GroupOperation buildGroupOperation(CountByPath countByPaths) {
+		return group().sum(countByPaths.getAlias()).as(countByPaths.getAlias());
+	}
+
+	List<CountResult> mapCountByPathResults(Document countByPathResults, String resultAlias) {
+		if (Objects.isNull(countByPathResults)) {
+			return List.of(buildZeroResult(resultAlias));
+		}
+
+		return mapCountByPathResults(countByPathResults);
+	}
+
+	private CountResult buildZeroResult(String resultAlias) {
+		return CountResult.builder().name(resultAlias).value(0).build();
+	}
+
+	private List<CountResult> mapCountByPathResults(@NonNull Document countByPathResults) {
+		return countByPathResults.entrySet().stream().filter(entry -> !"_id".equals(entry.getKey())).map(this::mapCountResult).toList();
+	}
+
+	CountResult mapCountResult(Map.Entry<String, Object> entry) {
+		return CountResult.builder().name(entry.getKey()).value((Integer) entry.getValue()).build();
+	}
+
+	<O> AggregationResults<O> executeAggregation(Class<O> outputType, List<AggregationOperation> aggregationOperations) {
+		return mongoOperations.aggregate(newAggregation(aggregationOperations), Vorgang.COLLECTION_NAME, outputType);
+	}
+
+	public boolean isFieldsExists(StatisticFilter filter) {
+		return mongoOperations.exists(Query.query(filter.getCriteria()), Vorgang.COLLECTION_NAME);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a0635754806c544c3fb5ce8b43e9c03c7c91f98
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/StatisticService.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.apache.commons.collections4.CollectionUtils.*;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.common.operator.OperatorFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+
+@Service
+class StatisticService {
+
+	@Autowired
+	private StatisticRepository statisticRepository;
+	@Autowired
+	private CurrentUserService currentUserService;
+	@Autowired
+	private OperatorFactory operatorFactory;
+
+	public Statistic countVorgang(VorgangCountRequest request) {
+		return Statistic.builder().countByStatus(countVorgangByStatus()).countResult(countVorgangByPathsOld(request.getCountByPaths())).build();
+	}
+
+	Map<String, Integer> countVorgangByPathsOld(List<CountByPath> countByPaths) {
+		var organisationsEinheitIds = getOrganisationsEinheitIds();
+		if (organisationsEinheitIds.isEmpty()) {
+			return countByPaths.stream().collect(Collectors.toMap(CountByPath::getAlias, counterByPath -> 0));
+		}
+		var statisticFilter = StatisticFilter.builder().organisationsEinheitIds(organisationsEinheitIds.get()).build();
+		return countByPaths.stream()
+				.flatMap(
+						countByPath -> statisticRepository.countVorgangByPath(countByPath, buildFieldExistsStatisticQuery(countByPath.getFieldPath()),
+								statisticFilter).stream())
+				.collect(Collectors.toMap(CountResult::getName, CountResult::getValue));
+	}
+
+	Operator buildFieldExistsStatisticQuery(String fieldPath) {
+		return operatorFactory.newUnequalOperatorBuilder().fieldPath(fieldPath).operand(null).build();
+	}
+
+	Map<Vorgang.Status, Integer> countVorgangByStatus() {
+		var organisationsEinheitIds = getOrganisationsEinheitIds();
+		if (organisationsEinheitIds.isEmpty()) {
+			return fillMissingStatusCounters(Collections.emptyMap());
+		}
+		var statisticFilter = StatisticFilter.builder().organisationsEinheitIds(organisationsEinheitIds.get()).build();
+		List<CountResult> countResults = statisticRepository.countVorgangByStatus(statisticFilter);
+		return fillMissingStatusCounters(mapCountResults(countResults));
+	}
+
+	Map<Vorgang.Status, Integer> mapCountResults(List<CountResult> countResults) {
+		var countByStatus = new EnumMap<Vorgang.Status, Integer>(Vorgang.Status.class);
+		countResults.forEach(countResult -> countByStatus.put(Vorgang.Status.valueOf(countResult.getName()), countResult.getValue()));
+		return countByStatus;
+	}
+
+	Map<Vorgang.Status, Integer> fillMissingStatusCounters(Map<Vorgang.Status, Integer> countByStatus) {
+		var resultMap = new EnumMap<Vorgang.Status, Integer>(Vorgang.Status.class);
+		resultMap.putAll(countByStatus);
+		Arrays.stream(Vorgang.Status.values()).forEach(status -> resultMap.putIfAbsent(status, 0));
+		return resultMap;
+	}
+
+	public Statistic collectStatistic(Collection<VorgangStatisticRequest> statisticRequests) {
+		return Statistic.builder()
+				.countResult(countVorgangByPaths(getCountRequests(statisticRequests)))
+				.existsResult(collectFieldExistsStatistic(getExistsRequests(statisticRequests)))
+				.build();
+	}
+
+	Set<VorgangStatisticRequest> getCountRequests(Collection<VorgangStatisticRequest> statisticRequests) {
+		return statisticRequests.stream().filter(request -> request.getStatisticGroupMethod() == StatisticGroupMethod.COUNT)
+				.collect(Collectors.toSet());
+	}
+
+	Set<VorgangStatisticRequest> getExistsRequests(Collection<VorgangStatisticRequest> statisticRequests) {
+		return statisticRequests.stream().filter(request -> request.getStatisticGroupMethod() == StatisticGroupMethod.EXISTS)
+				.collect(Collectors.toSet());
+	}
+
+	Map<String, Integer> countVorgangByPaths(Collection<VorgangStatisticRequest> statisticRequests) {
+		return statisticRequests.stream().flatMap(this::countVorgangByPath).collect(Collectors.toMap(CountResult::getName, CountResult::getValue));
+	}
+
+	Stream<CountResult> countVorgangByPath(VorgangStatisticRequest statisticRequest) {
+		var organisationsEinheitIds = getOrganisationsEinheitIds();
+		if (organisationsEinheitIds.isEmpty()) {
+			return Stream.of(CountResult.builder().name(statisticRequest.getResultName()).value(0).build());
+		}
+		var statisticFilter = StatisticFilter.builder().organisationsEinheitIds(organisationsEinheitIds.get()).build();
+		return statisticRepository
+				.countVorgangByPath(CountByPath.fromStatisticRequest(statisticRequest), statisticRequest.getOperator(), statisticFilter).stream();
+	}
+
+	Map<String, Boolean> collectFieldExistsStatistic(Collection<VorgangStatisticRequest> fieldExistsRequests) {
+		return fieldExistsRequests.stream().collect(Collectors.toMap(VorgangStatisticRequest::getResultName, this::isFieldExists));
+	}
+
+	boolean isFieldExists(VorgangStatisticRequest fieldExistsRequest) {
+		var organisationsEinheitIds = getOrganisationsEinheitIds();
+		if (organisationsEinheitIds.isEmpty()) {
+			return false;
+		}
+		var filter = StatisticFilter.builder().filterCriteria(fieldExistsRequest.getOperator().getCriteria())
+				.organisationsEinheitIds(organisationsEinheitIds.get()).build();
+		return statisticRepository.isFieldsExists(filter);
+	}
+
+	Optional<Collection<String>> getOrganisationsEinheitIds() {
+		var callContextUser = currentUserService.getUser();
+		if (callContextUser.isOrganisationEinheitenIdCheckNecessary()) {
+			if (isEmpty(callContextUser.getOrganisatorischeEinheitenIds())) {
+				return Optional.empty();
+			}
+			return Optional.of(callContextUser.getOrganisatorischeEinheitenIds());
+		}
+		return Optional.of(Collections.emptyList());
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangCountRequest.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangCountRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ec38d3e30425b0ca9fc06ffc992d52692d43837
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangCountRequest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import java.util.List;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Singular;
+
+@Getter
+@Builder
+class VorgangCountRequest {
+
+	@Singular
+	private List<CountByPath> countByPaths;
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangStatisticBadRequestException.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangStatisticBadRequestException.java
new file mode 100644
index 0000000000000000000000000000000000000000..6adb0c25612a1c3f97144b79b683715470e86f38
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangStatisticBadRequestException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import de.ozgcloud.vorgang.common.errorhandling.FunctionalException;
+
+public class VorgangStatisticBadRequestException extends FunctionalException {
+
+	public VorgangStatisticBadRequestException(String message) {
+		super(message, () -> "COUNT_VORGANG.BAD_REQUEST");
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangStatisticRequest.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangStatisticRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..60527e5d8fc6626f4a2d84f67b4f00940d79ddff
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/statistic/VorgangStatisticRequest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import de.ozgcloud.vorgang.common.operator.Operator;
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class VorgangStatisticRequest {
+
+	private String resultName;
+	private String fieldPath;
+	private StatisticGroupMethod statisticGroupMethod;
+	private Operator operator;
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/StatusChangedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusChangedEvent.java
similarity index 85%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/StatusChangedEvent.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusChangedEvent.java
index 5d19f8e539f3a0757d254b68a0d2d059a3e5b978..307ec1c1185af5c91d23e7da66bfd6351cd2cff6 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/StatusChangedEvent.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusChangedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.status;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandExecutedEvent;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
 
 public class StatusChangedEvent extends CommandExecutedEvent {
 
@@ -37,5 +37,4 @@ public class StatusChangedEvent extends CommandExecutedEvent {
 	StatusChangedEvent(String commandId) {
 		super(commandId);
 	}
-
 }
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusEventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..64a41e965b756b1eaf4525db571232d3349e386f
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusEventListener.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.status;
+
+import static de.ozgcloud.vorgang.vorgang.Vorgang.*;
+
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandRevokeFailedEvent;
+import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Log4j2
+class StatusEventListener {
+	@Autowired
+	private StatusService statusService;
+	@Autowired
+	private VorgangService vorgangService;
+	@Autowired
+	private CommandService commandService;
+
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	private static final String IS_ABSCHLIESSEN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_ABSCHLIESSEN_EVENT.test(event.getSource())}";
+	private static final String IS_ANNEHMEN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_ANNEHMEN_EVENT.test(event.getSource())}";
+	private static final String IS_VERWERFEN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_VERWERFEN_EVENT.test(event.getSource())}";
+	private static final String IS_BEARBEITEN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_BEARBEITEN_EVENT.test(event.getSource())}";
+	private static final String IS_BESCHEIDEN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_BESCHEIDEN_EVENT.test(event.getSource())}";
+	private static final String IS_WIEDEREROEFFNEN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_WIEDEREROEFFNEN_EVENT.test(event.getSource())}";
+	private static final String IS_ZURUECKHOLEN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_ZURUECKHOLEN_EVENT.test(event.getSource())}";
+	private static final String IS_ZURUECKSTELLEN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_ZURUECKSTELLEN_EVENT.test(event.getSource())}";
+	private static final String IS_ZUMLOESCHENMARKIEREN = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_ZUMLOESCHENMARKIEREN_EVENT.test(event.getSource())}";
+	private static final String IS_STATUS_CHANGE = "{T(de.ozgcloud.vorgang.status.StatusEventListener).IS_STATUS_CHANGE_EVENT.test(event.getSource())}";
+
+	public static final Predicate<Command> IS_ABSCHLIESSEN_EVENT = command -> command.getOrder().equals(Order.VORGANG_ABSCHLIESSEN.name());
+	public static final Predicate<Command> IS_ANNEHMEN_EVENT = command -> command.getOrder().equals(Order.VORGANG_ANNEHMEN.name());
+	public static final Predicate<Command> IS_VERWERFEN_EVENT = command -> command.getOrder().equals(Order.VORGANG_VERWERFEN.name());
+	public static final Predicate<Command> IS_BEARBEITEN_EVENT = command -> command.getOrder().equals(Order.VORGANG_BEARBEITEN.name());
+	public static final Predicate<Command> IS_BESCHEIDEN_EVENT = command -> command.getOrder().equals(Order.VORGANG_BESCHEIDEN.name());
+	public static final Predicate<Command> IS_WIEDEREROEFFNEN_EVENT = command -> command.getOrder().equals(Order.VORGANG_WIEDEREROEFFNEN.name());
+	public static final Predicate<Command> IS_ZURUECKHOLEN_EVENT = command -> command.getOrder().equals(Order.VORGANG_ZURUECKHOLEN.name());
+	public static final Predicate<Command> IS_ZURUECKSTELLEN_EVENT = command -> command.getOrder().equals(Order.VORGANG_ZURUECKSTELLEN.name());
+	public static final Predicate<Command> IS_ZUMLOESCHENMARKIEREN_EVENT = command -> command.getOrder()
+			.equals(Order.VORGANG_ZUM_LOESCHEN_MARKIEREN.name());
+	public static final Predicate<Command> IS_STATUS_CHANGE_EVENT = command -> command.getOrder().startsWith("VORGANG_");
+
+	@EventListener(condition = IS_ABSCHLIESSEN)
+	public void abschiessen(CommandCreatedEvent event) {
+		processEvent(event, statusService::abschliessen);
+	}
+
+	@EventListener(condition = IS_ANNEHMEN)
+	public void annehmen(CommandCreatedEvent event) {
+		processEvent(event, statusService::annehmen);
+	}
+
+	@EventListener(condition = IS_VERWERFEN)
+	public void verwerfen(CommandCreatedEvent event) {
+		processEvent(event, statusService::verwerfen);
+	}
+
+	@EventListener(condition = IS_BEARBEITEN)
+	public void bearbeiten(CommandCreatedEvent event) {
+		processEvent(event, statusService::bearbeiten);
+	}
+
+	@EventListener(condition = IS_BESCHEIDEN)
+	public void bescheiden(CommandCreatedEvent event) {
+		processEvent(event, statusService::bescheiden);
+	}
+
+	@EventListener(condition = IS_WIEDEREROEFFNEN)
+	public void wiedereroeffnen(CommandCreatedEvent event) {
+		processEvent(event, statusService::wiedereroeffnen);
+	}
+
+	@EventListener(condition = IS_ZURUECKHOLEN)
+	public void zurueckholen(CommandCreatedEvent event) {
+		processEvent(event, statusService::setStatusNeu);
+	}
+
+	@EventListener(condition = IS_ZURUECKSTELLEN)
+	public void zurueckstellen(CommandCreatedEvent event) {
+		processEvent(event, statusService::annehmen);
+	}
+
+	@EventListener(condition = IS_ZUMLOESCHENMARKIEREN)
+	public void zuLoeschenMarkieren(CommandCreatedEvent event) {
+		processEvent(event, statusService::zumLoeschenMarkieren);
+	}
+
+	private void processEvent(CommandCreatedEvent event, Consumer<Command> eventConsumer) {
+		var command = event.getSource();
+		try {
+			command = setPreviousState(command);
+			eventConsumer.accept(command);
+		} catch (NotFoundException e) {
+			handleError("Error processing event because related vorgang (%s) not found.".formatted(command.getVorgangId()), e, command.getId());
+		} catch (Exception e) {
+			handleError("Unexpected Error on handling Status event.", e, command.getId());
+		}
+	}
+
+	Command setPreviousState(Command command) {
+		var vorgang = vorgangService.getById(command.getVorgangId());
+		commandService.setPreviousState(command.getId(), getPreviousStateMap(vorgang));
+		return commandService.findCommand(command.getId())
+				.orElseThrow(() -> new NoSuchElementException("No command with Id %s found".formatted(command.getId())));
+	}
+
+	Map<String, Object> getPreviousStateMap(Vorgang vorgang) {
+		return Map.of(MONGODB_FIELDNAME_STATUS, vorgang.getStatus());
+	}
+
+	@EventListener(condition = IS_STATUS_CHANGE)
+	public void statusRevokedEvent(RevokeCommandEvent event) {
+		var command = event.getSource();
+		try {
+			statusService.revokeStatusChange(command);
+		} catch (Exception e) {
+			LOG.error("Unexpected error on command revoke.", e);
+			publisher.publishEvent(new CommandRevokeFailedEvent(command.getId(), "Unexpected error on command revoke"));
+		}
+	}
+
+	private void handleError(String message, Exception e, String commandId) {
+		LOG.error(message, e);
+		publisher.publishEvent(new CommandFailedEvent(commandId, message));
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..40da49597e87dd6b36d98f310cddc9e010ea51a3
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusRepository.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.status;
+
+import static de.ozgcloud.vorgang.common.db.CriteriaUtil.*;
+import static de.ozgcloud.vorgang.vorgang.Vorgang.*;
+import static org.springframework.data.mongodb.core.query.Query.*;
+
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Update;
+import org.springframework.stereotype.Repository;
+
+import com.mongodb.client.result.UpdateResult;
+
+import de.ozgcloud.vorgang.common.db.CollisionVerifier;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import lombok.extern.log4j.Log4j2;
+
+@Repository
+@Log4j2
+class StatusRepository {
+
+	@Autowired
+	private MongoOperations mongoOperations;
+
+	private CollisionVerifier collisionVerifier;
+
+	@PostConstruct
+	void init() {
+		collisionVerifier = createCollisionVerifier();
+	}
+
+	CollisionVerifier createCollisionVerifier() {
+		return new CollisionVerifier(this::doVorgangExist);
+	}
+
+	boolean doVorgangExist(String vorgangId) {
+		return mongoOperations.exists(query(isId(vorgangId)), Vorgang.COLLECTION_NAME);
+	}
+
+	public void updateStatusWithoutVersionCheck(String vorgangId, Status status) {
+		var update = new Update()
+				.inc(MONGODB_FIELDNAME_VERSION, 1)
+				.set(MONGODB_FIELDNAME_STATUS, status);
+		updateFirst(new Criteria(MONGODB_FIELDNAME_ID).is(vorgangId), update);
+	}
+
+	public void patch(String vorgangId, long version, Map<String, Object> patch) {
+		var update = new Update().inc(MONGODB_FIELDNAME_VERSION, 1);
+		patch.forEach(update::set);
+
+		collisionVerifier.verify(updateFirst(whereIdAndVersion(vorgangId, version), update), vorgangId);
+	}
+
+	private UpdateResult updateFirst(Criteria queryObj, Update update) {
+		var result = mongoOperations.updateFirst(query(queryObj), update, Vorgang.class);
+		LOG.debug("Update result: {}", result);
+		return result;
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c5a5a985f55ce923435515e40a0f6ce0d1ee747
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/status/StatusService.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.status;
+
+import java.util.ConcurrentModificationException;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.apache.commons.collections4.MapUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandRevokedEvent;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.command.PersistedCommand;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import lombok.extern.log4j.Log4j2;
+
+@Service
+@Log4j2
+public class StatusService {
+	private static final String CONCURRENT_MODIFICATION_ERROR_CODE = "concurrent_modification";
+
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	@Autowired
+	private StatusRepository repository;
+
+	void setStatusNeu(Command command) {
+		executeStatusChangeCommand(command, Status.NEU);
+	}
+
+	public void annehmen(Command command) {
+		executeStatusChangeCommand(command, Status.ANGENOMMEN);
+	}
+
+	public void verwerfen(Command command) {
+		executeStatusChangeCommand(command, Status.VERWORFEN);
+	}
+
+	public void bescheiden(Command command) {
+		executeStatusChangeCommand(command, Status.BESCHIEDEN);
+	}
+
+	public void abschliessen(Command command) {
+		executeStatusChangeCommand(command, Status.ABGESCHLOSSEN);
+	}
+
+	public void wiedereroeffnen(Command command) {
+		bearbeiten(command);
+	}
+
+	public void bearbeiten(Command command) {
+		executeStatusChangeCommand(command, Status.IN_BEARBEITUNG);
+	}
+
+	public void zumLoeschenMarkieren(Command command) {
+		executeStatusChangeCommand(command, Status.ZU_LOESCHEN);
+	}
+
+	public void executeStatusChangeCommand(Command command, Status status) {
+		try {
+			doUpdateStatus(command.getRelationId(), command.getRelationVersion(), status.name());
+			publisher.publishEvent(new StatusChangedEvent(command));
+		} catch (ConcurrentModificationException e) {
+			LOG.warn("Concurrent modification on changeing status.");
+			publisher.publishEvent(new CommandFailedEvent(command.getId(), CONCURRENT_MODIFICATION_ERROR_CODE));
+		}
+	}
+
+	public void setStatusToInBearbeitung(String vorgangId, long version) {
+		doUpdateStatus(vorgangId, version, Status.IN_BEARBEITUNG.name());
+	}
+
+	public void revokeStatusChange(Command command) {
+		try {
+			doUpdateStatus(command.getRelationId(), command.getRelationVersion() + 1,
+					getPreviousStatus(command).orElseThrow(() -> new TechnicalException("Malformed or missing previous state for status revoke.")));
+
+			publisher.publishEvent(new CommandRevokedEvent(command));
+		} catch (ConcurrentModificationException e) {
+			publisher.publishEvent(new CommandFailedEvent(command.getId(), CONCURRENT_MODIFICATION_ERROR_CODE));
+		}
+	}
+
+	Optional<String> getPreviousStatus(Command command) {
+		return Optional.ofNullable(((PersistedCommand) command).getPreviousState())
+				.map(previousState -> MapUtils.getString(previousState, Vorgang.MONGODB_FIELDNAME_STATUS))
+				.filter(Objects::nonNull);
+	}
+
+	void doUpdateStatus(String vorgangId, long version, String statusValue) {
+		Map<String, Object> patch = Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, statusValue);
+
+		repository.patch(vorgangId, version, patch);
+	}
+
+	public void setStatusToWeitergeleitet(String vorgangId, String commandId) {
+		doUpdateStatusWithoutVerisonCheck(vorgangId, Status.WEITERGELEITET, commandId);
+	}
+
+	public void setStatusToInBearbeitung(String vorgangId, String commandId) {
+		doUpdateStatusWithoutVerisonCheck(vorgangId, Status.IN_BEARBEITUNG, commandId);
+	}
+
+	void doUpdateStatusWithoutVerisonCheck(String vorgangId, Status newStatus, String commandId) {
+		repository.updateStatusWithoutVersionCheck(vorgangId, newStatus);
+
+		publisher.publishEvent(new StatusChangedEvent(commandId));
+	}
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/system/SystemStatusGrpcService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/system/SystemStatusGrpcService.java
similarity index 93%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/system/SystemStatusGrpcService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/system/SystemStatusGrpcService.java
index 32cdd9f5a1d1cdeae55fb51da4437eb69790b18d..344db6f8876ce3abb58336523d80e017c4bf4fee 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/system/SystemStatusGrpcService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/system/SystemStatusGrpcService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.system;
+package de.ozgcloud.vorgang.system;
+
+import java.util.Objects;
 
-import de.itvsh.ozg.pluto.common.search.SearchService;
-import io.grpc.stub.StreamObserver;
-import net.devh.boot.grpc.server.service.GrpcService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.info.BuildProperties;
 
-import java.util.Objects;
+import de.ozgcloud.vorgang.common.search.SearchService;
+import io.grpc.stub.StreamObserver;
+import net.devh.boot.grpc.server.service.GrpcService;
 
 @GrpcService
 public class SystemStatusGrpcService extends SystemStatusServiceGrpc.SystemStatusServiceImplBase {
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/DeleteUserScheduler.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/DeleteUserScheduler.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ac9e70d2121724af7da714231cc62447a47eb47
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/DeleteUserScheduler.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.user;
+
+import static java.util.function.Predicate.*;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.vorgang.command.CommandService;
+import lombok.extern.log4j.Log4j2;
+import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
+
+@Component
+@Profile("!itcase")
+@Log4j2
+public class DeleteUserScheduler {
+
+	@Autowired
+	private UserService userService;
+	@Autowired
+	private CommandService commandService;
+
+	 @Scheduled(cron = "${ozgcloud.user.cleanup.cron:0 0 1 * * *}")
+	 @SchedulerLock(name = "DeleteUserScheduler")
+	public void deleteUsers() {
+		try {
+			LOG.debug("Deleting inactive users.");
+			userService.findInactiveUserIds().filter(not(commandService::existsCommandWithUserId)).forEach(userService::deleteInactiveUser);
+		} catch (RuntimeException e) {
+			LOG.error("Cannot delete inactive users.", e);
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/UserProfileRemoteService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/UserProfileRemoteService.java
new file mode 100644
index 0000000000000000000000000000000000000000..69fd57af6803df212d53b1ad6b988f0ac632c546
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/UserProfileRemoteService.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.user;
+
+import java.util.stream.Stream;
+
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.user.grpc.userprofile.UserProfileServiceGrpc.UserProfileServiceBlockingStub;
+import de.ozgcloud.user.userprofile.GrpcDeleteInactiveUserRequest;
+import de.ozgcloud.user.userprofile.GrpcFindInactiveUserIdsRequest;
+import de.ozgcloud.user.userprofile.GrpcFindInactiveUserIdsResponse;
+import de.ozgcloud.user.userprofile.GrpcUserProfileId;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@Service
+class UserProfileRemoteService {
+
+	@GrpcClient("user-manager")
+	private UserProfileServiceBlockingStub userProfileServiceGrpc;
+
+	public Stream<String> findInactiveUserIds() {
+		var response = getUserServiceStub().findInactiveUserIds(GrpcFindInactiveUserIdsRequest.newBuilder().build());
+		return mapFindInactiveUserIdsResponse(response);
+	}
+
+	Stream<String> mapFindInactiveUserIdsResponse(GrpcFindInactiveUserIdsResponse response) {
+		return response.getUserProfileIdsList().stream().map(GrpcUserProfileId::getId);
+	}
+
+	public void deleteInactiveUser(String userId) {
+		getUserServiceStub().deleteInactiveUser(buildDeleteInactiveUsersRequest(userId));
+	}
+
+	UserProfileServiceBlockingStub getUserServiceStub() {
+		return userProfileServiceGrpc.withInterceptors(new VorgangManagerCallContextAttachingInterceptor());
+	}
+
+	GrpcDeleteInactiveUserRequest buildDeleteInactiveUsersRequest(String userId) {
+		return GrpcDeleteInactiveUserRequest.newBuilder().setUserId(userId).build();
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/UserService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/UserService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e682a062bb2643b42d04635395bf95e3a2b89ddd
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/UserService.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.user;
+
+import java.util.stream.Stream;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+class UserService {
+
+	@Autowired
+	private UserProfileRemoteService userRemoteService;
+
+	public Stream<String> findInactiveUserIds() {
+		return userRemoteService.findInactiveUserIds();
+	}
+
+	public void deleteInactiveUser(String userId) {
+		userRemoteService.deleteInactiveUser(userId);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/VorgangManagerCallContextAttachingInterceptor.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/VorgangManagerCallContextAttachingInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..ad6747c8b5190462273b2bf23adb2e65637d0b6f
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/user/VorgangManagerCallContextAttachingInterceptor.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.user;
+
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
+
+import java.util.UUID;
+
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.ClientInterceptor;
+import io.grpc.ForwardingClientCall.SimpleForwardingClientCall;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+
+public class VorgangManagerCallContextAttachingInterceptor implements ClientInterceptor {
+
+	static final String KEY_USER_ID = "USER_ID-bin";
+	static final String KEY_CLIENT_NAME = "CLIENT_NAME-bin";
+	static final String KEY_REQUEST_ID = "REQUEST_ID-bin";
+
+	public static final String VORGANG_MANAGER_CLIENT_NAME = "OzgCloudVorgangManager";
+	static final String VORGANG_MANAGER_SENDER_USER_ID = "system-vorgang_manager-delete_user";
+
+	// <A> = Request, <B> = Response
+	@Override
+	public <A, B> ClientCall<A, B> interceptCall(MethodDescriptor<A, B> method, CallOptions callOptions, Channel next) {
+		return new CallContextAttachingClientCall<>(next.newCall(method, callOptions));
+	}
+
+	final class CallContextAttachingClientCall<A, B> extends SimpleForwardingClientCall<A, B> {
+
+		protected CallContextAttachingClientCall(ClientCall<A, B> delegate) {
+			super(delegate);
+		}
+
+		@Override
+		public void start(Listener<B> responseListener, Metadata headers) {
+			headers.merge(buildCallContextMetadata());
+			super.start(responseListener, headers);
+		}
+
+		private Metadata buildCallContextMetadata() {
+			var metadata = new Metadata();
+
+			metadata.put(createKeyOf(KEY_USER_ID), VORGANG_MANAGER_SENDER_USER_ID.getBytes());
+			metadata.put(createKeyOf(KEY_CLIENT_NAME), VORGANG_MANAGER_CLIENT_NAME.getBytes());
+			metadata.put(createKeyOf(KEY_REQUEST_ID), generateRequestId().getBytes());
+
+			return metadata;
+		}
+
+		// TODO requestId in Scheduler erzeugen
+		private String generateRequestId() {
+			return UUID.randomUUID().toString();
+		}
+
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProvider.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProvider.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProvider.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProvider.java
index bf302ec2448ca2d34fbd587518da4cd76d40ecf5..7f947996e2d86c795f8bb08b5e7d45722b077819 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProvider.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 interface AktenzeichenProvider {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderConfiguration.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderConfiguration.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderConfiguration.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderConfiguration.java
index c18463e4445e0b4696bea715c962f2768a20a0d6..1de0b92e53bd8e6c380b2061c547bcdac8aa2aa9 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderConfiguration.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.Optional;
@@ -31,7 +31,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
+import de.ozgcloud.common.errorhandling.TechnicalException;
 
 @Configuration
 public class AktenzeichenProviderConfiguration {
@@ -39,8 +39,8 @@ public class AktenzeichenProviderConfiguration {
 	private static final String MSG_CLASSNOTFOUND_TEMPL = "Class '%s' for AktenzeichenProvider not found";
 	private static final String MSG_INSTANCE = "Error on getInstance for aktenzeichen provider.";
 
-	// TODO configruations-hirachie verwenden
-	@Value("${aktenzeichen:#{null}}")
+	// TODO configruations-hierachie verwenden
+	@Value("${ozgcloud.aktenzeichen:#{null}}")
 	private Optional<String> aktenzeichenCalculator;
 
 	@Bean
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderEA.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderEA.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderEA.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderEA.java
index 8b1c87fd3b108b607da6963442086ca86f175b77..cb6f864d8f460732b7daa1a47a5e890276938aae 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderEA.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderEA.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import lombok.NoArgsConstructor;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Antragsteller.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Antragsteller.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Antragsteller.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Antragsteller.java
index 2b12ab112b3b1abdcfd10d35611d22cc3285ba69..9f14fada41dd8f0570a27b114e44da97b23bdba2 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Antragsteller.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Antragsteller.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.Map;
 
 import lombok.Builder;
 import lombok.Getter;
-import lombok.ToString;
 
-@ToString
 @Getter
 @Builder
 public class Antragsteller {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AntragstellerMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AntragstellerMapper.java
similarity index 93%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AntragstellerMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AntragstellerMapper.java
index 29a74369190e65c03853ea539bce18b0c0f17b1c..ef3d3e6a00f872d626479fdc9c815ff3da7e012e 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/AntragstellerMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/AntragstellerMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcFormDataMapper;
+import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper;
 
 @Mapper(uses = { GrpcFormDataMapper.class }, nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
 		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/CustomVorgangHeaderRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/CustomVorgangHeaderRepository.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/CustomVorgangHeaderRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/CustomVorgangHeaderRepository.java
index 048f25c8e9a0a084e592b0e61a50a4c5f73dd76b..406571d4446555973a2aa9def2c74f086327e02b 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/CustomVorgangHeaderRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/CustomVorgangHeaderRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.springframework.data.domain.Page;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/DefaultAktenzeichenProvider.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/DefaultAktenzeichenProvider.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/DefaultAktenzeichenProvider.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/DefaultAktenzeichenProvider.java
index f46e735cdf77189d36d3e1cd46bde2ff1d751c5b..d7577039ecb359df8ad72b1e7a7d5993d8c00253 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/DefaultAktenzeichenProvider.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/DefaultAktenzeichenProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import lombok.NoArgsConstructor;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Eingang.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Eingang.java
similarity index 93%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Eingang.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Eingang.java
index efce3499ebd170161f1182cff5bf6902a68bda06..20fd2b8e8683724237fd80c73bd594d971848271 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Eingang.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Eingang.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.List;
 import java.util.Map;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeader.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangHeader.java
similarity index 84%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeader.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangHeader.java
index 2cd52758861f199a646e81bb6cc023eaa27af27d..ace40bf0bc2faaf3ded119474b6f3773f525e70d 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeader.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangHeader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.time.ZonedDateTime;
 
+import de.ozgcloud.vorgang.servicekonto.ServiceKonto;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.ToString;
@@ -40,6 +41,8 @@ public class EingangHeader {
 	private String formName;
 	private String formEngineName;
 
-	private String sender;
+	private String vorgangNummer;
 
+	private String sender;
+	private ServiceKonto serviceKonto;
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangHeaderMapper.java
similarity index 75%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangHeaderMapper.java
index 8120b9891853a3296a317e213fdfd8f29eeb9640..30df00c923ef26f296395efba52a979b380375fd 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangHeaderMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
@@ -29,8 +29,15 @@ import java.time.format.DateTimeFormatter;
 import org.mapstruct.Mapper;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
+import org.mapstruct.ReportingPolicy;
 
-@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoMapper;
+
+@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, //
+		unmappedSourcePolicy = ReportingPolicy.WARN, //
+		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
+		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, //
+		uses = ServiceKontoMapper.class)
 interface EingangHeaderMapper {
 
 	EingangHeader fromGrpc(GrpcEingangHeader grpcEingangHeader);
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangMapper.java
similarity index 84%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangMapper.java
index cfa1cf1ad2482ac38c17254a3003dde8300e8d78..35d3de3bf179ab9b14af9830d9307ff19edfdb49 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/EingangMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
-
-import java.util.Map.Entry;
-import java.util.function.Predicate;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.mapstruct.CollectionMappingStrategy;
 import org.mapstruct.Mapper;
@@ -32,7 +29,7 @@ import org.mapstruct.Mapping;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcFormDataMapper;
+import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper;
 
 @Mapper(uses = { AntragstellerMapper.class,
 		EingangHeaderMapper.class, IncomingFileMapper.class, GrpcFormDataMapper.class }, //
@@ -41,8 +38,6 @@ import de.itvsh.kop.pluto.common.grpc.GrpcFormDataMapper;
 		collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
 interface EingangMapper {
 
-	static final Predicate<Entry<String, Object>> IS_FIELD_VALUE = entry -> entry.getValue() instanceof String;
-
 	@Mapping(source = "attachmentsList", target = "attachments")
 	@Mapping(source = "representationsList", target = "representations")
 	Eingang fromGrpc(GrpcEingang grpcEingang);
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterByMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterByMapper.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterByMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterByMapper.java
index 13787195b6159032543d517c3cb1c6ddcf8a4357..856ef02463da2edc8bc80f273f060f9acc44c642 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterByMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterByMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.Collection;
 
@@ -32,8 +32,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 import com.google.protobuf.ProtocolStringList;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUser;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.callcontext.CallContextUser;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
 
 @Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
 abstract class FilterByMapper {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterCriteria.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterCriteria.java
similarity index 84%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterCriteria.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterCriteria.java
index bf312171f90d65b2c8fd7417aad6cb4eb5f995b3..c69f555186e06d32d02b300dc1ea01365bb67178 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterCriteria.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterCriteria.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.List;
 
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Singular;
@@ -39,5 +39,7 @@ public class FilterCriteria {
 	private List<String> organisationseinheitIds;
 	@Singular("singleStatus")
 	private List<Status> status;
+	private boolean filterByAssignedTo;
 	private String assignedTo;
+	private boolean hasNextWiedervorlageFrist;
 }
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterCriteriaDefault.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterCriteriaDefault.java
similarity index 90%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterCriteriaDefault.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterCriteriaDefault.java
index b03edd671ad77c1a2740d577cba37f71bada9aad..c170de65db3e615c73befe816dcb48df4623ffe8 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FilterCriteriaDefault.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FilterCriteriaDefault.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 enum FilterCriteriaDefault {
 	SHOW_ALL,
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangQuery.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangQuery.java
new file mode 100644
index 0000000000000000000000000000000000000000..8404ace093bc9ad2cee02e35112eba29e938d981
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangQuery.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import java.util.List;
+
+import de.ozgcloud.vorgang.common.operator.Operator;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Singular;
+
+@Builder
+@Getter
+public class FindVorgangQuery {
+
+	public enum LogicalOperator {
+		AND, OR
+	}
+
+	private LogicalOperator logicalOperator;
+	@Singular
+	private List<Operator> operators;
+	private FindVorgangQuery nestedQuery;
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..7071d26150dd90d6b1d04f95dcdd1b34b6d0193f
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryMapper.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import org.mapstruct.Mapper;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ozgcloud.vorgang.common.operator.OperandFunctionParser;
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+
+@Mapper
+abstract class FindVorgangQueryMapper {
+
+	@Autowired
+	private OperandFunctionParser operandFunctionParser;
+
+	public FindVorgangQuery fromQuery(GrpcQuery query) {
+		var findVorgangQueryBuilder = FindVorgangQuery.builder()
+				.logicalOperator(fromLogicalOperator(query.getLogicalOperator()));
+		query.getExpressionsList().stream().map(this::buildOperator).forEach(findVorgangQueryBuilder::operator);
+		if (hasSubQuery(query)) {
+			findVorgangQueryBuilder.nestedQuery(fromQuery(query.getNestedQuery()));
+		}
+		return findVorgangQueryBuilder.build();
+	}
+
+	boolean hasSubQuery(GrpcQuery query) {
+		return !GrpcQuery.getDefaultInstance().equals(query.getNestedQuery());
+	}
+
+	FindVorgangQuery.LogicalOperator fromLogicalOperator(GrpcLogicalOperator operator) {
+		return FindVorgangQuery.LogicalOperator.valueOf(operator.name());
+	}
+
+	Operator buildOperator(GrpcVorgangQueryExpression queryExpression) {
+		return OperatorBuilder.from(queryExpression.getOperator())
+				.fieldPath(queryExpression.getPath())
+				.operand(getValue(queryExpression)).build();
+	}
+
+	Object getValue(GrpcVorgangQueryExpression queryExpression) {
+		return switch (queryExpression.getOperandCase()) {
+			case OPERANDBOOLVALUE -> queryExpression.getOperandBoolValue();
+			case OPERANDINTVALUE -> queryExpression.getOperandIntValue();
+			case OPERANDSTRINGVALUE -> getStringValue(queryExpression);
+			case OPERAND_NOT_SET -> null;
+		};
+	}
+
+	String getStringValue(GrpcVorgangQueryExpression queryExpression) {
+		var operandStringValue = queryExpression.getOperandStringValue();
+		if ("null".equalsIgnoreCase(operandStringValue)) {
+			return null;
+		} else if (operandStringValue.endsWith(")")) {
+			return operandFunctionParser.parse(operandStringValue);
+		}
+		return operandStringValue;
+	}
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequest.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequest.java
similarity index 85%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequest.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequest.java
index ed3cb51713691ea5e5e58e2ed56d296f15b07eab..eef7387c7c9db40c4163b8caf50af755313fbc8a 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequest.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import lombok.Builder;
 import lombok.Getter;
@@ -31,11 +31,12 @@ import lombok.Getter;
 public class FindVorgangRequest {
 
 	enum OrderCriteria {
-		PRIORITY, EA_PRIORITY
+		PRIORITY, EA_PRIORITY, CREATED_AT_DESC, NEXT_WIEDERVORLAGE_FRIST
 	}
 
 	private FilterCriteria filterBy;
 	private String searchBy;
+	private FindVorgangQuery findVorgangQuery;
 	@Builder.Default
 	private OrderCriteria orderBy = OrderCriteria.PRIORITY;
 	@Builder.Default
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestMapper.java
similarity index 84%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestMapper.java
index 7cd3357cd6a11ed1ce0236aaa2904dc966fc015e..43330d7f058939f1cd4c272ba3832303482e3624 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,18 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.apache.commons.lang3.StringUtils;
 import org.mapstruct.CollectionMappingStrategy;
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
 import org.mapstruct.MappingConstants;
 import org.mapstruct.ValueMapping;
 
-@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, uses = { FilterByMapper.class })
+@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, uses = { FilterByMapper.class, FindVorgangQueryMapper.class })
 interface FindVorgangRequestMapper {
 
 	@ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL)
+	@Mapping(target = "findVorgangQuery", source = "query")
 	FindVorgangRequest fromFindVorgangRequest(GrpcFindVorgangRequest vorgangRequest);
 
 	default String emptyToNull(String inString) {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangService.java
similarity index 79%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangService.java
index 5744a6f59dd71d583fcd49b69bd1dd247c40df29..fe60cea7cb9fd47a27a225f77ab8ac3ef116fa42 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
@@ -51,35 +51,20 @@ class GrpcVorgangService extends VorgangServiceGrpc.VorgangServiceImplBase {
 	@Autowired
 	private IncomingFileGroupMapper incomingFileGroupMapper;
 
-	/**
-	 * @deprecated Kann nach dem Ausrollen von Version 0.23.0 entfernt werden
-	 * @param eingang
-	 * @return
-	 */
-	@Deprecated(since = "0.22.0", forRemoval = true)
-	@Override
-	public void createVorgang(GrpcCreateVorgangRequest request, StreamObserver<GrpcCreateVorgangResponse> responseObserver) {
-		var vorgang = vorgangService.createVorgang(eingangMapper.fromGrpc(request.getEingang()));
-
-		completeRequest(responseObserver, vorgang);
-	}
-
 	@Override
 	public void startCreation(GrpcCreateVorgangRequest request, StreamObserver<GrpcCreateVorgangResponse> responseObserver) {
-		var vorgang = vorgangService.startCreation(eingangMapper.fromGrpc(request.getEingang()));
+		GrpcCreateVorgangResponse response = buildCreateVorgangResponse(startVorgangCreation(request.getEingang()));
 
-		completeRequest(responseObserver, vorgang);
+		responseObserver.onNext(response);
+		responseObserver.onCompleted();
 	}
 
-	private void completeRequest(StreamObserver<GrpcCreateVorgangResponse> responseObserver, Vorgang vorgang) {
-		responseObserver.onNext(buildCreateVorgangResponse(vorgang));
-		responseObserver.onCompleted();
+	private Vorgang startVorgangCreation(GrpcEingang eingang) {
+		return vorgangService.startCreation(eingangMapper.fromGrpc(eingang));
 	}
 
 	private GrpcCreateVorgangResponse buildCreateVorgangResponse(Vorgang vorgang) {
-		return GrpcCreateVorgangResponse.newBuilder()
-				.setVorgangId(vorgang.getId())
-				.setMessage("ok").build();
+		return GrpcCreateVorgangResponse.newBuilder().setVorgangId(vorgang.getId()).setMessage("ok").build();
 	}
 
 	@Override
@@ -108,7 +93,7 @@ class GrpcVorgangService extends VorgangServiceGrpc.VorgangServiceImplBase {
 	private GrpcFindVorgangResponse buildFindVorgangResponse(Page<VorgangHeader> page) {
 		var replyBuilder = page.getContent().stream()
 				.map(vorgangHeaderMapper::toGrpcVorgangHeader)//
-				.collect(GrpcFindVorgangResponse::newBuilder, (builder, header) -> builder.addVorgang(header),
+				.collect(GrpcFindVorgangResponse::newBuilder, GrpcFindVorgangResponse.Builder::addVorgang,
 						(builder1, builder2) -> builder1.addAllVorgang(builder2.getVorgangList()));
 
 		return replyBuilder.setTotal(page.getTotalElements()).build();
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFile.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFile.java
similarity index 88%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFile.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFile.java
index 1336b1622b17377590cdcef0c6c1218717c4b2e3..6d10523ce1e3414f86f2639b9b3bbb06ab0f8721 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFile.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import de.itvsh.ozg.pluto.files.FileId;
+import de.ozgcloud.vorgang.files.FileId;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.ToString;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroup.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroup.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroup.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroup.java
index e5aec0c16aaa279d746152bc95186fc992ce914a..5d6da950d97b0a9d309196a433733705e74d900c 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroup.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.List;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupMapper.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupMapper.java
index 32d8a63d50b2d67ad0001bb3038ab6262bc1c484..2ecad62a2c9e63c26a42939056bf5e3c02bf6941 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 
+
 @Mapper(uses = IncomingFileMapper.class)
 interface IncomingFileGroupMapper {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapper.java
similarity index 88%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapper.java
index 45da1de091f39d3a82548413ff0fc40b9b206f8b..e176fa9ad9037e7608999eea926eb908736bc221 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/IncomingFileMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.mapstruct.Mapper;
 
 import com.google.protobuf.ByteString;
 
-import de.itvsh.ozg.pluto.files.FileIdMapper;
+import de.ozgcloud.vorgang.files.FileIdMapper;
 
 @Mapper(uses = FileIdMapper.class)
 public interface IncomingFileMapper {
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/LabelProcessor.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/LabelProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..28e9d5288bb90466b3d079178205a54dc71b587c
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/LabelProcessor.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static java.util.stream.Collectors.*;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.springframework.stereotype.Component;
+
+import lombok.NonNull;
+
+@Component
+class LabelProcessor {
+
+	static final String CONTROL_DATA_KEY = "_kopControlData";
+
+	static final String LABELS_KEY = "labels";
+	static final String META_DATA = "metaData";
+
+	public static final String VALUE_KEY = "value";
+	public static final String LABEL_KEY = "label";
+
+	private static final Predicate<Entry<String, Object>> IS_NOT_CONTROL_DATA = entry -> !StringUtils.equals(entry.getKey(), CONTROL_DATA_KEY);
+
+	public Eingang moveLabelsToControlData(Eingang eingang) {
+		var mappedFormData = moveLabelsToControlData(eingang.getFormData());
+		return eingang.toBuilder().formData(mappedFormData).build();
+	}
+
+	Map<String, Object> moveLabelsToControlData(Map<String, Object> formData) {
+		Map<String, Object> formDataWithoutLables = formData.entrySet().stream()
+				.filter(IS_NOT_CONTROL_DATA)
+				.map(entry -> Pair.of(entry.getKey(), entry.getValue()))
+				.map(this::removeLabels)
+				.map(this::doRecursionIfSubForm)
+				.collect(toMap(Pair::getKey, Pair::getValue, this::merge, LinkedHashMap::new));
+
+		return replaceControlData(formDataWithoutLables, addLabelsToControlData(formData));
+	}
+
+	private Pair<String, Object> removeLabels(Pair<String, Object> formEntry) {
+		return Pair.of(formEntry.getKey(), getValueWithoutLabel(formEntry.getValue()));
+	}
+
+	Map<String, Object> addLabelsToControlData(Map<String, Object> formData) {
+		var controlData = new HashMap<>(getControlData(formData));
+		var labels = getLabelsFromFormData(formData);
+		if (MapUtils.isNotEmpty(labels)) {
+			controlData.put(LABELS_KEY, labels);
+		}
+
+		return controlData;
+	}
+
+	Map<String, Object> replaceControlData(Map<String, Object> formData, Map<String, Object> controlData) {
+		if (controlData.isEmpty()) {
+			return formData;
+		}
+
+		var editableFormData = new LinkedHashMap<String, Object>(formData);
+		editableFormData.put(CONTROL_DATA_KEY, Collections.unmodifiableMap(controlData));
+
+		return Collections.unmodifiableMap(editableFormData);
+	}
+
+	Pair<String, Object> doRecursionIfSubForm(Pair<String, Object> formEntry) {
+		if (isSubFormValue(formEntry.getValue())) {
+			return Pair.of(formEntry.getKey(), moveLabelsToControlData(castToSubFormMap(formEntry.getValue())));
+		}
+		return formEntry;
+	}
+
+	Map<String, String> getLabelsFromFormData(Map<String, Object> formData) {
+		return formData.entrySet().stream()
+				.filter(IS_NOT_CONTROL_DATA)
+				.map(entry -> Pair.of(entry.getKey(), getLabelFromFieldValue(entry.getValue())))
+				.filter(optPair -> optPair.getValue().isPresent())
+				.collect(toMap(Pair::getKey, pair -> pair.getValue().get()));
+	}
+
+	Optional<String> getLabelFromFieldValue(Object value) {
+		if (isMap(value)) {
+			return Optional.ofNullable((String) castToSubFormMap(value).get(LABEL_KEY));
+		}
+		return Optional.empty();
+	}
+
+	Object getValueWithoutLabel(Object value) {
+		if (isMap(value)) {
+			return castToSubFormMap(value).getOrDefault(VALUE_KEY, value);
+		}
+		return value;
+	}
+
+	public Eingang addLabels(Eingang eingang) {
+		var mappedFormData = addLabels(eingang.getFormData());
+		return eingang.toBuilder().formData(mappedFormData).build();
+	}
+
+	Map<String, Object> addLabels(Map<String, Object> originFormData) {
+		return originFormData.entrySet().stream().filter(IS_NOT_CONTROL_DATA)
+				.map(entry -> Pair.of(entry.getKey(), addLabel(entry.getKey(), entry.getValue(), getLabels(originFormData))))
+				.collect(toMap(Pair::getKey, Pair::getValue, this::merge, LinkedHashMap::new));
+	}
+
+	private Object merge(Object m1, Object m2) {
+		throw new IllegalStateException("Collision in mapping function.");
+	}
+
+	@SuppressWarnings("unchecked")
+	private Map<String, String> getLabels(@NonNull Map<String, Object> formData) {
+		return (Map<String, String>) getControlData(formData).getOrDefault(LABELS_KEY, Collections.emptyMap());
+	}
+
+	private Map<String, Object> getControlData(@NonNull Map<String, Object> formData) {
+		return castToSubFormMap(formData.getOrDefault(CONTROL_DATA_KEY, Collections.emptyMap()));
+	}
+
+	Map<String, Object> addLabel(String fieldName, Object fieldValue, Map<String, String> labels) {
+		if (isFieldValue(fieldValue)) {
+			return addLabelToFieldValue(fieldName, fieldValue, labels);
+		} else {
+			return addLabelsToSubForm(castToSubFormMap(fieldValue), Optional.ofNullable(labels.get(fieldName)));
+		}
+	}
+
+	Map<String, Object> addLabelToFieldValue(String fieldName, Object fieldValue, Map<String, String> labels) {
+		if (labels.containsKey(fieldName)) {
+			return Map.of(
+					LABEL_KEY, labels.get(fieldName),
+					VALUE_KEY, fieldValue);
+		} else {
+			return Map.of(VALUE_KEY, fieldValue);
+		}
+	}
+
+	Map<String, Object> addLabelsToSubForm(Map<String, Object> subForm, Optional<String> subFormLabel) {
+		Map<String, Object> subFormMap = new LinkedHashMap<>();
+		subFormLabel.ifPresent(label -> subFormMap.put(LABEL_KEY, label));
+
+		subFormMap.put(VALUE_KEY, addLabels(subForm));
+		return Collections.unmodifiableMap(subFormMap);
+	}
+
+	boolean isFieldValue(Object value) {
+		if (isNotMap(value)) {
+			return true;
+		}
+
+		var valueMap = castToSubFormMap(value);
+		if (!valueMap.containsKey(LABEL_KEY)) {
+			return false;
+		}
+
+		return isNotMap(valueMap.get(VALUE_KEY));
+	}
+
+	boolean isSubFormValue(Object value) {
+		return !isFieldValue(value);
+	}
+
+	private boolean isMap(Object object) {
+		return object instanceof Map<?, ?>;
+	}
+
+	Object getFieldValue(Object fieldValue) {
+		if (isNotMap(fieldValue) || !castToSubFormMap(fieldValue).containsKey(LABEL_KEY)) {
+			return fieldValue;
+		}
+
+		return castToSubFormMap(fieldValue).get(VALUE_KEY);
+	}
+
+	private boolean isNotMap(Object object) {
+		return !isMap(object);
+	}
+
+	@SuppressWarnings("unchecked")
+	private Map<String, Object> castToSubFormMap(Object value) {
+		return (Map<String, Object>) value;
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/QueryCriteriaBuilder.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/QueryCriteriaBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f035d2f7bdab96cbd4b7f62a34f648919e3cb26
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/QueryCriteriaBuilder.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static java.util.Objects.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.vorgang.FindVorgangQuery.LogicalOperator;
+
+@Component
+public class QueryCriteriaBuilder {
+
+	public Criteria from(FindVorgangQuery query) {
+		var criterias = new ArrayList<Criteria>();
+		if (nonNull(query.getNestedQuery())) {
+			criterias.add(from(query.getNestedQuery()));
+		}
+		addFromOperators(criterias, query.getOperators());
+		return connect(query.getLogicalOperator(), criterias);
+	}
+
+	void addFromOperators(Collection<Criteria> criterias, Collection<Operator> operators) {
+		operators.stream().map(Operator::getCriteria).forEach(criterias::add);
+	}
+
+	Criteria connect(LogicalOperator logicalOperator, Collection<Criteria> criterias) {
+		if (criterias.isEmpty()) {
+			return new Criteria();
+		}
+		if (criterias.size() == 1) {
+			return criterias.iterator().next();
+		}
+		return switch (logicalOperator) {
+			case AND -> new Criteria().andOperator(criterias);
+			case OR -> new Criteria().orOperator(criterias);
+		};
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/SetAktenzeichenCompletedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/SetAktenzeichenCompletedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..42b04b2deccbfa7c813f09970a97fc5d11677b3b
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/SetAktenzeichenCompletedEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
+
+public class SetAktenzeichenCompletedEvent extends CommandExecutedEvent {
+
+	public SetAktenzeichenCompletedEvent(Command command) {
+		super(command);
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgagnQueryExpression.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgagnQueryExpression.java
new file mode 100644
index 0000000000000000000000000000000000000000..994b926d25c2fbd6da7d6c8d6a9cd0b735f2d5bb
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgagnQueryExpression.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+public class VorgagnQueryExpression {
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Vorgang.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Vorgang.java
similarity index 70%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Vorgang.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Vorgang.java
index 8d1226091c31a6fb3e32f29a5c0225e2085a19c5..0506c512cdc9a39960afcc242007e30336536c0b 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Vorgang.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Vorgang.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
@@ -31,8 +31,8 @@ import org.springframework.data.annotation.Id;
 import org.springframework.data.annotation.TypeAlias;
 import org.springframework.data.mongodb.core.mapping.Document;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributesMap;
-import de.itvsh.ozg.pluto.vorgang.redirect.Forwarding;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
+import de.ozgcloud.vorgang.vorgang.redirect.Forwarding;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Singular;
@@ -45,25 +45,24 @@ public class Vorgang {
 	public static final String COLLECTION_NAME = "vorgang";
 
 	public static final String MONGODB_FIELDNAME_ID = "_id";
-	static final String MONGODB_FIELDNAME_VERSION = "version";
-	static final String MONGODB_FIELDNAME_STATUS = "status";
+	public static final String MONGODB_FIELDNAME_VERSION = "version";
+	public static final String MONGODB_FIELDNAME_STATUS = "status";
 	static final String MONGODB_FIELDNAME_CREATED_AT = "createdAt";
-	static final String MONGODB_FIELDNAME_ASSIGNED_TO = "assignedTo";
-	static final String MONGODB_FIELDNAME_IN_CREATION = "inCreation";
+	public static final String MONGODB_FIELDNAME_ASSIGNED_TO = "assignedTo";
+	public static final String MONGODB_FIELDNAME_IN_CREATION = "inCreation";
 
-	static final String FIELD_EINGANGSKENNZ = "eingangs.header.requestId";
-	static final String FIELD_AKTENZEICHEN = "aktenzeichen";
-	static final String FIELD_ANTRAGSTELLER_VORNAME = "eingangs.antragsteller.vorname";
-	static final String FIELD_ANTRAGSTELLER_NACHNAME = "eingangs.antragsteller.nachname";
-	static final String FIELD_NAME = "name";
-	static final String FIELD_NUMMER = "nummer";
+	public static final String FIELD_EINGANGSKENNZ = "eingangs.header.requestId";
+	public static final String FIELD_AKTENZEICHEN = "aktenzeichen";
+	public static final String FIELD_ANTRAGSTELLER_VORNAME = "eingangs.antragsteller.vorname";
+	public static final String FIELD_ANTRAGSTELLER_NACHNAME = "eingangs.antragsteller.nachname";
+	public static final String FIELD_NAME = "name";
+	public static final String FIELD_NUMMER = "nummer";
 
 	public static final String FIELD_ORGANISATIONSEINHEIT = "eingangs.zustaendigeStelle.organisationseinheitenId";
-	static final String FIELD_WIEDERVORLAGE = "wiedervorlages";
 	public static final String FIELD_CLIENT_ATTRIBUTES = "clientAttributes";
 
 	public enum Status {
-		NEU, ANGENOMMEN, VERWORFEN, IN_BEARBEITUNG, BESCHIEDEN, ABGESCHLOSSEN, WEITERGELEITET;
+		NEU, ANGENOMMEN, VERWORFEN, IN_BEARBEITUNG, BESCHIEDEN, ABGESCHLOSSEN, WEITERGELEITET, ZU_LOESCHEN, DELETED;
 	}
 
 	@Id
@@ -84,6 +83,8 @@ public class Vorgang {
 	private Status status = Status.NEU;
 	private String aktenzeichen;
 
+	private VorgangHead header;
+
 	@Singular
 	private List<Eingang> eingangs;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangAssignedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java
similarity index 83%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangAssignedEvent.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java
index 662454e9a398563989ed95edfe569832cfb88252..c1c4216901708799a10cc38eeebb9f6fee9f9155 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangAssignedEvent.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAssignedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandExecutedEvent;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
 import lombok.Getter;
 
 @Getter
 public class VorgangAssignedEvent extends CommandExecutedEvent {
-	private Command command;
+	private transient Command command;
 
 	private static final long serialVersionUID = 1L;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangAuthorizationService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAuthorizationService.java
similarity index 95%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangAuthorizationService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAuthorizationService.java
index a3fc30ae8f69b5c5086428d1268ce126e42da0ba..c293f0336ed3c9d46e0978e34a73162021a10d07 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangAuthorizationService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangAuthorizationService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.Optional;
 
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangDeletedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangDeletedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..11ca2d744fbbe3d534f56e4f1e4c8ac6193e2588
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangDeletedEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
+import lombok.Getter;
+
+@Getter
+public class VorgangDeletedEvent extends CommandExecutedEvent {
+
+	protected VorgangDeletedEvent(Command command) {
+		super(command);
+	}
+
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangEventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..d826941c63331fb588da3616f62a04031c83f66c
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangEventListener.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import java.util.Collections;
+import java.util.function.Predicate;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.CommandExecutedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.status.StatusService;
+import de.ozgcloud.vorgang.vorgang.redirect.VorgangForwardFailedEvent;
+import de.ozgcloud.vorgang.vorgang.redirect.VorgangRedirectedEvent;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Log4j2
+public class VorgangEventListener {
+
+	private static final String IS_ASSIGN_COMMAND_CONDITION = "{T(de.ozgcloud.vorgang.vorgang.VorgangEventListener).IS_ASSIGN_COMMAND.test(event.getSource())}";
+	private static final String IS_LOESCHEN_COMMAND_CONDITION = "{T(de.ozgcloud.vorgang.vorgang.VorgangEventListener).IS_LOESCHEN_COMMAND.test(event.getSource())}";
+	private static final String IS_SET_AKTENZEICHEN_COMMAND_CONDITION = "{T(de.ozgcloud.vorgang.vorgang.VorgangEventListener).IS_SET_AKTENZEICHEN_COMMAND.test(event.getSource())}";
+	public static final Predicate<Command> IS_ASSIGN_COMMAND = command -> Order.ASSIGN_USER.isMeant(command.getOrder());
+	public static final Predicate<Command> IS_LOESCHEN_COMMAND = command -> Order.VORGANG_LOESCHEN.isMeant(command.getOrder());
+	public static final Predicate<Command> IS_SET_AKTENZEICHEN_COMMAND = command -> Order.SET_AKTENZEICHEN.isMeant(command.getOrder());
+
+	@Autowired
+	private StatusService statusService;
+	@Autowired
+	private VorgangService vorgangService;
+	@Autowired
+	private VorgangHeaderService vorgangHeaderService;
+	@Autowired
+	private FileService fileService;
+	@Autowired
+	private CommandService commandService;
+
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	@EventListener
+	public void updateStatus(VorgangRedirectedEvent event) {
+		statusService.setStatusToWeitergeleitet(event.getSource().getVorgangId(), event.getSource().getCreatedByCommand());
+	}
+
+	@EventListener
+	public void updateStatus(VorgangForwardFailedEvent event) {
+		statusService.setStatusToInBearbeitung(event.getVorgangId(), event.getSource());
+	}
+
+	@EventListener(condition = IS_ASSIGN_COMMAND_CONDITION)
+	public void assignToUser(CommandCreatedEvent event) {
+		vorgangService.assignToUser(event.getSource());
+	}
+
+	@EventListener(condition = IS_LOESCHEN_COMMAND_CONDITION)
+	public void onVorgangLoeschen(CommandCreatedEvent event) {
+		Command command = event.getSource();
+		try {
+			String vorgangId = command.getVorgangId();
+			vorgangService.deleteVorgang(vorgangId);
+			fileService.deleteAllByVorgang(vorgangId);
+
+			publishEvent(new VorgangDeletedEvent(command));
+		} catch (RuntimeException e) {
+			LOG.error("Unexpected Error on deleting Vorgang.", e);
+			publisher.publishEvent(new CommandFailedEvent(command.getId(), e.getMessage()));
+		}
+	}
+
+	@EventListener(condition = IS_SET_AKTENZEICHEN_COMMAND_CONDITION)
+	public void onSetAktenzeichen(CommandCreatedEvent event) {
+		var command = event.getSource();
+		try {
+			updatePreviousState(command);
+			vorgangService.setAktenzeichen(command);
+			publisher.publishEvent(new SetAktenzeichenCompletedEvent(command));
+		} catch (RuntimeException e) {
+			LOG.error("Unexpected Error setting Aktenzeichen.", e);
+			publisher.publishEvent(new CommandFailedEvent(command.getId(), e.getMessage()));
+		}
+	}
+
+	void publishEvent(CommandExecutedEvent event) {
+		LOG.debug("Command {} executed", event.getSource());
+		publisher.publishEvent(event);
+	}
+
+	private void updatePreviousState(Command command) {
+		commandService.setPreviousState(command.getId(),
+				Collections.singletonMap(VorgangService.BODY_OBJECT_AKTENZEICHEN, getAktenzeichen(command.getVorgangId())));
+	}
+
+	private String getAktenzeichen(String vorgangId) {
+		return vorgangHeaderService.getById(vorgangId).getAktenzeichen();
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHead.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHead.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0d4c2e4103ef49ba84fc0b69c79636a32bb0996
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHead.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import org.springframework.data.annotation.TypeAlias;
+
+import de.ozgcloud.vorgang.servicekonto.ServiceKonto;
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+@TypeAlias("VorgangHeader")
+public class VorgangHead {
+
+	private ServiceKonto serviceKonto;
+
+	private String organisationsEinheitId;
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeader.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeader.java
similarity index 87%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeader.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeader.java
index 0420a4bc227385fd9b41f878da00e62d9f9207be..4dcd971d731d1ac42c4a6078b6ae7a2e13470a86 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeader.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.time.ZonedDateTime;
 
 import org.springframework.data.mongodb.core.mapping.Document;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributesMap;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.ToString;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderMapper.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderMapper.java
index e98b69676d0a9527e7d9c20b98ee38e57675aaba..e4c435ec8130cacd095a0d43ffa82aaebf979e0e 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
@@ -29,7 +29,7 @@ import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributeMapper;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeMapper;
 
 @Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
 		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, uses = ClientAttributeMapper.class)
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepository.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepository.java
index 160c5aa7e337ee42ab5c91ab6b3fa32cb0aa8dd0..92c37a57852b3c0c308fbdd2afdc71f02ae25f95 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.springframework.data.mongodb.repository.MongoRepository;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImpl.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImpl.java
similarity index 72%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImpl.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImpl.java
index e29aec8b9edc50c4b7be65369b521f379f40622d..2c0c7962b72ee40daeac0626bb475ad2267f94f7 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImpl.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import static de.itvsh.ozg.pluto.vorgang.Vorgang.*;
+import static de.ozgcloud.vorgang.vorgang.Vorgang.*;
 
-import java.time.LocalDate;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
@@ -48,17 +47,18 @@ import org.springframework.data.mongodb.core.aggregation.UnionWithOperation;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 
-import de.itvsh.ozg.pluto.vorgang.FindVorgangRequest.OrderCriteria;
+import de.ozgcloud.vorgang.common.db.CriteriaUtil;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest.OrderCriteria;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
 
 @Log4j2
 class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 
-	static final String DEFAULT_CLIENT = "Goofy";
-
 	@Autowired
 	private MongoTemplate template;
+	@Autowired
+	private QueryCriteriaBuilder queryCriteriaBuilder;
 
 	@Override
 	public Page<VorgangHeader> findAll(FindVorgangRequest request) {
@@ -73,15 +73,16 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 	}
 
 	private List<VorgangHeader> executeRequest(FindVorgangRequest request) {
-		return execAggration(aggregationBuilder(buildPageable(request))
-				.withSearchBy(StringUtils.trimToNull(request.getSearchBy()))
-				.withFilterBy(request.getFilterBy())
-				.build(request.getOrderBy()));
+		var aggregationBuilder = aggregationBuilder(buildPageable(request))
+				.withFilterBy(request.getFilterBy());
+		Optional.ofNullable(request.getFindVorgangQuery())
+				.ifPresentOrElse(aggregationBuilder::withQuery, () -> aggregationBuilder.withSearchBy(StringUtils.trimToNull(request.getSearchBy())));
+		return execAggration(aggregationBuilder.build(request.getOrderBy()));
 	}
 
 	private boolean hasNoPermissionByOrganisationseinheitenId(FilterCriteria filterCriteria) {
-		return Objects.nonNull(filterCriteria)//
-				&& filterCriteria.getOrganisationseinheitIds().isEmpty()//
+		return Objects.nonNull(filterCriteria)
+				&& filterCriteria.getOrganisationseinheitIds().isEmpty()
 				&& filterCriteria.isFilterByOrganisationseinheitenId();
 	}
 
@@ -105,8 +106,10 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 		var organisationseinheitenIdCriteria = buildOrganisationseinheitenCriteria(filterCriteria);
 		var assignedToCriteria = buildAssignedToCriteria(filterCriteria);
 		var statusCriteria = buildStatusCriteria(filterCriteria);
+		var hasNextWiedervorlageFrist = buildHasNextWiedervorlageCriteria(filterCriteria);
 
-		return CriteriaUtil.vorgangInCreation().andOperator(organisationseinheitenIdCriteria, assignedToCriteria, statusCriteria);
+		return CriteriaUtil.vorgangNotInCreation().andOperator(organisationseinheitenIdCriteria, assignedToCriteria, statusCriteria,
+				hasNextWiedervorlageFrist);
 	}
 
 	private Criteria buildOrganisationseinheitenCriteria(FilterCriteria filterCriteria) {
@@ -119,17 +122,32 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 
 	private Criteria buildAssignedToCriteria(FilterCriteria filterCriteria) {
 		return Optional.ofNullable(filterCriteria)
+				.filter(FilterCriteria::isFilterByAssignedTo)
 				.map(FilterCriteria::getAssignedTo)
-				.filter(StringUtils::isNotEmpty)
-				.map(CriteriaUtil::vorgangIsAssignedTo)
+				.map(this::getAssigendToCriteria)
 				.orElseGet(Criteria::new);
 	}
 
+	private Criteria getAssigendToCriteria(String assignedTo) {
+		if (StringUtils.isNotEmpty(assignedTo)) {
+			return CriteriaUtil.vorgangIsAssignedTo(assignedTo);
+		} else {
+			return CriteriaUtil.vorgangIsUnassigned();
+		}
+	}
+
 	private Criteria buildStatusCriteria(FilterCriteria filterCriteria) {
 		return Optional.ofNullable(filterCriteria)
 				.map(FilterCriteria::getStatus)
 				.filter(CollectionUtils::isNotEmpty)
 				.map(CriteriaUtil::vorgangInStatus)
+				.orElseGet(CriteriaUtil::isNotDeleted);
+	}
+
+	private Criteria buildHasNextWiedervorlageCriteria(FilterCriteria filterCriteria) {
+		return Optional.ofNullable(filterCriteria)
+				.filter(FilterCriteria::isHasNextWiedervorlageFrist)
+				.map(criteria -> CriteriaUtil.nextWiedervorlageFristExists())
 				.orElseGet(Criteria::new);
 	}
 
@@ -141,6 +159,7 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 	private class AggregationBuilder {
 		private final Pageable pageRequest;
 		private Optional<String> searchBy = Optional.empty();
+		private Optional<FindVorgangQuery> findVorgangQuery = Optional.empty();
 		private Optional<FilterCriteria> filterCriteria = Optional.empty();
 
 		AggregationBuilder withSearchBy(String searchBy) {
@@ -148,6 +167,11 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 			return this;
 		}
 
+		AggregationBuilder withQuery(FindVorgangQuery findVorgangQuery) {
+			this.findVorgangQuery = Optional.ofNullable(findVorgangQuery);
+			return this;
+		}
+
 		AggregationBuilder withFilterBy(FilterCriteria filterCriteria) {
 			this.filterCriteria = Optional.ofNullable(filterCriteria);
 			return this;
@@ -159,6 +183,10 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 				return buildSortedByEAPriority();
 			case PRIORITY:
 				return buildSortedByPriority();
+			case CREATED_AT_DESC:
+				return buildSortedByCreatedAtDesc();
+			case NEXT_WIEDERVORLAGE_FRIST:
+				return buildSortedNextWiedervorlageFrist();
 			default:
 				LOG.warn("Unkown order by expression '{}'. Using default order.", orderBy);
 				return buildSortedByPriority();
@@ -176,7 +204,6 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 					unionWithVorgang().pipeline(buildRemainingStatusPipeline())));
 
 			addPageableAggregations(operations);
-
 			return Aggregation.newAggregation(operations);
 		}
 
@@ -191,7 +218,24 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 					unionWithVorgang().pipeline(buildRemainingStatusPipeline())));
 
 			addPageableAggregations(operations);
+			return Aggregation.newAggregation(operations);
+		}
+
+		private Aggregation buildSortedByCreatedAtDesc() {
+			var operations = buildSearchAndFilterAggregation();
+
+			operations.add(Aggregation.sort(Sort.by(MONGODB_FIELDNAME_CREATED_AT).descending()));
+
+			addPageableAggregations(operations);
+			return Aggregation.newAggregation(operations);
+		}
 
+		private Aggregation buildSortedNextWiedervorlageFrist() {
+			var operations = buildSearchAndFilterAggregation();
+
+			operations.add(Aggregation.sort(Sort.by(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).ascending()));
+
+			addPageableAggregations(operations);
 			return Aggregation.newAggregation(operations);
 		}
 
@@ -201,9 +245,7 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 
 		private List<AggregationOperation> findAndSortExpiredWiedervorlagen() {
 			return List.of(
-					Aggregation.match(Criteria.where(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY).ne(null)
-							.andOperator(Criteria.where(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY)
-									.lte(getLocalTimeAsString()))),
+					Aggregation.match(CriteriaUtil.nextWiedervorlageFristInThePast()),
 					Aggregation.sort(Sort.by(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).ascending()));
 		}
 
@@ -211,17 +253,12 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 			var operations = buildSearchAndFilterAggregation();
 
 			operations.addAll(List.of(
-					Aggregation.match(Criteria.where(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_KEY).ne(null)
-							.andOperator(
-									Criteria.where(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).gt(getLocalTimeAsString()))),
+					Aggregation
+							.match(CriteriaUtil.nextWiedervorlageFristInTheFuture()),
 					Aggregation.sort(Sort.by(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST_VALUE_KEY).ascending())));
 			return Aggregation.newAggregation(operations).getPipeline();
 		}
 
-		private String getLocalTimeAsString() {
-			return LocalDate.now().toString();
-		}
-
 		private AggregationPipeline buildZuBearbeitendePipeline() {
 			var operations = buildSearchAndFilterAggregation();
 			operations.addAll(List.of(
@@ -256,7 +293,7 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 			var operations = buildSearchAndFilterAggregation();
 
 			operations.addAll(List.of(
-					Aggregation.match(Criteria.where(FIELD_WIEDERVORLAGE).exists(false)),
+					Aggregation.match(CriteriaUtil.withoutNextWiedervorlageFrist()),
 					Aggregation.match(CriteriaUtil.vorgangRemainingStatus()),
 					Aggregation.sort(Sort.by(MONGODB_FIELDNAME_CREATED_AT).descending())));
 
@@ -268,21 +305,22 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 			operations.add(buildInCreationCriteria());
 
 			buildMatchOrganisationseinheitenId(filterCriteria).ifPresent(operations::add);
-			buildMatchSearchBy(searchBy).ifPresent(operations::add);
+			buildMatchQuery().or(this::buildMatchSearchBy).ifPresent(operations::add);
 			buildMatchStatus(filterCriteria).ifPresent(operations::add);
 			buildMatchAssignedTo(filterCriteria).ifPresent(operations::add);
+			buildHasNextWiedervorlagenFrist(filterCriteria).ifPresent(operations::add);
 
 			return operations;
 		}
 
 		private void addPageableAggregations(List<AggregationOperation> aggregations) {
-			aggregations.add(Aggregation.project(VorgangHeader.class));
 			aggregations.add(Aggregation.skip(pageRequest.getOffset()));
 			aggregations.add(Aggregation.limit(pageRequest.getPageSize()));
+			aggregations.add(Aggregation.project(VorgangHeader.class));
 		}
 
 		private AggregationOperation buildInCreationCriteria() {
-			return Aggregation.match(CriteriaUtil.vorgangInCreation());
+			return Aggregation.match(CriteriaUtil.vorgangNotInCreation());
 		}
 
 		private Optional<AggregationOperation> buildMatchOrganisationseinheitenId(Optional<FilterCriteria> filterCriteria) {
@@ -291,8 +329,12 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 					.map(organisationseinheitIds -> Aggregation.match(CriteriaUtil.inOrganisationseinheitenIds(organisationseinheitIds)));
 		}
 
-		private Optional<AggregationOperation> buildMatchSearchBy(Optional<String> searchStr) {
-			return searchStr.map(search -> Aggregation.match(CriteriaUtil.searchCriteria(search)));
+		private Optional<AggregationOperation> buildMatchQuery() {
+			return findVorgangQuery.map(queryCriteriaBuilder::from).map(Aggregation::match);
+		}
+
+		private Optional<AggregationOperation> buildMatchSearchBy() {
+			return searchBy.map(search -> Aggregation.match(CriteriaUtil.searchCriteria(search)));
 		}
 
 		private Optional<AggregationOperation> buildMatchStatus(Optional<FilterCriteria> filterCriteria) {
@@ -302,9 +344,14 @@ class VorgangHeaderRepositoryImpl implements CustomVorgangHeaderRepository {
 		}
 
 		private Optional<AggregationOperation> buildMatchAssignedTo(Optional<FilterCriteria> filterCriteria) {
-			return filterCriteria.map(FilterCriteria::getAssignedTo)
-					.filter(StringUtils::isNotEmpty)
-					.map(assignedTo -> Aggregation.match(CriteriaUtil.vorgangIsAssignedTo(assignedTo)));
+			return filterCriteria.filter(FilterCriteria::isFilterByAssignedTo)
+					.map(FilterCriteria::getAssignedTo)
+					.map(assignedTo -> Aggregation.match(getAssigendToCriteria(assignedTo)));
+		}
+
+		private Optional<AggregationOperation> buildHasNextWiedervorlagenFrist(Optional<FilterCriteria> filterCriteria) {
+			return filterCriteria.filter(FilterCriteria::isHasNextWiedervorlageFrist)
+					.map(hasNextWiedervorlageFrist -> Aggregation.match(CriteriaUtil.nextWiedervorlageFristExists()));
 		}
 	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderService.java
similarity index 76%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderService.java
index ee4c7c33da9c8a0050d504effa81ad429b869539..42740a993ccd83ae96328ad5ff6206a7da1f5eb3 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,16 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import java.util.Objects;
+import static java.util.Objects.*;
+
+import java.util.Optional;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.ozg.pluto.common.search.SearchService;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.common.search.SearchService;
 
 @Service
 class VorgangHeaderService {
@@ -45,7 +48,7 @@ class VorgangHeaderService {
 	private SearchService searchService;
 
 	public Page<VorgangHeader> findAll(FindVorgangRequest request) {
-		if (Objects.nonNull(searchService) && Objects.nonNull(request.getSearchBy())) {
+	if (nonNull(searchService) && nonNull(request.getSearchBy())) {
 			return removeUnpermitted(searchService.find(request));
 		}
 		return removeUnpermitted(repository.findAll(request));
@@ -64,4 +67,12 @@ class VorgangHeaderService {
 				.clientAttributes(vorgangService.removeUnpermitted(vorgangHeader.getClientAttributes()))
 				.build();
 	}
+
+	public Optional<VorgangHeader> findById(String vorgangId) {
+		return repository.findById(vorgangId);
+	}
+
+	public VorgangHeader getById(String vorgangId) {
+		return findById(vorgangId).orElseThrow(() -> new TechnicalException(vorgangId + " could not be found"));
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangRepository.java
similarity index 62%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangRepository.java
index 27ce3bd63f0bbd80833348ad37b4ffc4496ce02d..8fb43e18ab105099c004f6dffc30e1c4ee825123 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,23 +21,28 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import static org.springframework.data.mongodb.core.query.Query.query;
+import static de.ozgcloud.vorgang.common.db.CriteriaUtil.*;
+import static org.springframework.data.mongodb.core.query.Query.*;
 
 import java.util.Collection;
 import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Stream;
 
+import jakarta.annotation.PostConstruct;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.stereotype.Repository;
 
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import com.mongodb.client.result.UpdateResult;
+
+import de.ozgcloud.vorgang.common.db.CollisionVerifier;
+import de.ozgcloud.vorgang.common.db.CriteriaUtil;
 
 @Repository
 class VorgangRepository {
@@ -45,6 +50,13 @@ class VorgangRepository {
 	@Autowired
 	private MongoOperations mongoOperations;
 
+	private CollisionVerifier collisionVerifier;
+
+	@PostConstruct
+	void init() {
+		collisionVerifier = new CollisionVerifier(this::exists);
+	}
+
 	public Optional<Vorgang> findById(String vorgangId) {
 		return Optional.ofNullable(findOne(CriteriaUtil.isId(vorgangId)));
 	}
@@ -54,31 +66,19 @@ class VorgangRepository {
 	}
 
 	private Vorgang findOne(Criteria queryObj) {
-		return mongoOperations.findOne(query(queryObj), Vorgang.class);
+		return mongoOperations.findOne(query(queryObj.andOperator(CriteriaUtil.isNotDeleted())), Vorgang.class);
 	}
 
 	public Vorgang save(Vorgang vorgang) {
 		return mongoOperations.save(vorgang);
 	}
 
-	public Stream<Vorgang> findAll() {
-		return mongoOperations.stream(Query.query(Criteria.where(Vorgang.MONGODB_FIELDNAME_IN_CREATION).is(false)), Vorgang.class).stream();
-	}
-
-	/** @deprecated use {@link #patch(String, long, Map)} */
-	@Deprecated
-	public void updateStatus(String vorgangId, long version, Status status) {
-		var update = new Update()
-				.inc(Vorgang.MONGODB_FIELDNAME_VERSION, 1)
-				.set(Vorgang.MONGODB_FIELDNAME_STATUS, status);
-		updateFirst(whereIdAndVersion(vorgangId, version), update);
+	public void saveStub(VorgangStub vorgangStub) {
+		mongoOperations.save(vorgangStub);
 	}
 
-	public void updateStatusWithoutVersionCheck(String vorgangId, Status status) {
-		var update = new Update()
-				.inc(Vorgang.MONGODB_FIELDNAME_VERSION, 1)
-				.set(Vorgang.MONGODB_FIELDNAME_STATUS, status);
-		updateFirst(CriteriaUtil.isId(vorgangId), update);
+	public Stream<Vorgang> findAll() {
+		return mongoOperations.stream(query(CriteriaUtil.vorgangNotInCreation().andOperator(CriteriaUtil.isNotDeleted())), Vorgang.class);
 	}
 
 	public void patch(String vorgangId, long version, Map<String, Object> patch) {
@@ -88,17 +88,28 @@ class VorgangRepository {
 		updateFirst(whereIdAndVersion(vorgangId, version), update);
 	}
 
-	private void updateFirst(Criteria queryObj, Update update) {
-		mongoOperations.updateFirst(query(queryObj), update, Vorgang.class);
+	public void setAktenzeichen(String vorgangId, long version, String akteneinsicht) {
+		var updateResult = updateFirst(whereIdAndVersion(vorgangId, version), new Update().set(Vorgang.FIELD_AKTENZEICHEN, akteneinsicht));
+		collisionVerifier.verify(updateResult, vorgangId);
+	}
+
+	private UpdateResult updateFirst(Criteria queryObj, Update update) {
+		return mongoOperations.updateFirst(query(queryObj), update, Vorgang.class);
 	}
 
 	private Criteria whereIdAndVersion(String vorgangId, long version) {
 		return CriteriaUtil.isId(vorgangId).and(Vorgang.MONGODB_FIELDNAME_VERSION).is(version);
 	}
 
+	public boolean exists(String vorgangId) {
+		return mongoOperations.exists(query(isId(vorgangId)), Vorgang.class);
+	}
+
 	public boolean exists(String vorgangId, Collection<String> organisationEinheitenIds) {
 		return mongoOperations.exists(
-				query(CriteriaUtil.isId(vorgangId).and(Vorgang.FIELD_ORGANISATIONSEINHEIT).in(organisationEinheitenIds)),
+				query(isId(vorgangId)
+						.andOperator(inOrganisationseinheitenIds(organisationEinheitenIds)
+								.andOperator(isNotDeleted()))),
 				Vorgang.class);
 	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
similarity index 55%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
index ea9471b9ca60255f998e66125ac93064cff1b21e..6bc4085d681759b66031c1af6ed205ee6b59dbab 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.Collection;
 import java.util.List;
@@ -30,25 +30,29 @@ import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.stream.Stream;
 
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.security.access.AccessDeniedException;
 import org.springframework.stereotype.Service;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributeMap;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributeReadPermitted;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributesMap;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.PersistedCommand;
-import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
-import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.redirect.Forwarding;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeMap;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.servicekonto.ServiceKonto;
+import lombok.NonNull;
 
 @Service
 public class VorgangService {
 
+	private static final String BODY_ASSIGNED_TO_FIELD = "assignedTo";
+	public static final String BODY_OBJECT_AKTENZEICHEN = "aktenzeichen";
+
 	@Autowired
 	private VorgangAuthorizationService vorgangAuthenticationService;
 	@Autowired
@@ -62,37 +66,53 @@ public class VorgangService {
 	@Autowired
 	private ClientAttributeReadPermitted readIsPermitted;
 
-	/**
-	 * @deprecated Kann nach dem Ausrollen von Version 0.23.0 entfernt werden
-	 * @param eingang
-	 * @return
-	 */
-	@Deprecated
-	public Vorgang createVorgang(Eingang eingang) {
-		var vorgang = repository.save(buildVorgang(eingang, false));
-
-		publishVorgangeCreatedEvent(vorgang);
+	@Autowired
+	private LabelProcessor kopControlDataMapper;
 
-		return vorgang;
-	}
+	@Autowired
+	private VorgangStubMapper stubMapper;
 
 	public Vorgang startCreation(Eingang eingang) {
-		return repository.save(buildVorgang(eingang, true));
+		var mappedEingang = kopControlDataMapper.moveLabelsToControlData(eingang);
+
+		return repository.save(buildVorgang(mappedEingang, true));
 	}
 
 	private Vorgang buildVorgang(Eingang eingang, boolean inCreation) {
 		return Vorgang.builder()
 				.name(eingang.getHeader().getFormName())
 				.aktenzeichen(aktenzeichenProvider.provideAktenzeichen(eingang))
-				.nummer(eingang.getHeader().getRequestId())
+				.nummer(getVorgangNummer(eingang.getHeader()))
 				.formEngineName(eingang.getHeader().getFormEngineName())
 				.inCreation(inCreation)
+				.header(buildVorgangHead(eingang))
 				.eingang(eingang)
 				.build();
 	}
 
+	String getVorgangNummer(@NonNull EingangHeader header) {
+		return Optional.ofNullable(header.getVorgangNummer())
+				.orElseGet(header::getRequestId);
+	}
+
+	private Optional<ServiceKonto> getServiceKonto(Eingang eingang) {
+		return Optional.ofNullable(eingang.getHeader().getServiceKonto());
+	}
+
+	private VorgangHead buildVorgangHead(Eingang eingang) {
+		var vorgangHeadBuilder = VorgangHead.builder();
+
+		getServiceKonto(eingang).ifPresent(vorgangHeadBuilder::serviceKonto);
+
+		return vorgangHeadBuilder.build();
+	}
+
 	public void finishCreation(String vorgangId, List<IncomingFileGroup> attachments, List<IncomingFile> representations) {
-		var vorgang = addAttachmentsAndRepresentations(getById(vorgangId), attachments, representations).inCreation(false).build();
+		// TODO nicht den ganzen Vorgang laden und überschreiben sondern nur die
+		// notwendigen Felder anpassen (patch)
+		var loaded = repository.findById(vorgangId)
+				.orElseThrow(() -> new IllegalStateException("Cannot load vorgang for finishing creation -" + vorgangId));
+		var vorgang = addAttachmentsAndRepresentations(loaded, attachments, representations).inCreation(false).build();
 
 		var savedVorgang = repository.save(vorgang);
 
@@ -113,74 +133,6 @@ public class VorgangService {
 		publisher.publishEvent(new VorgangCreatedEvent(vorgang.getId()));
 	}
 
-	public Vorgang setStatusNeu(Command command) {
-		return executeStatusChangeCommand(command, Status.NEU);
-	}
-
-	public Vorgang annehmen(Command command) {
-		return executeStatusChangeCommand(command, Status.ANGENOMMEN);
-	}
-
-	public Vorgang verwerfen(Command command) {
-		return executeStatusChangeCommand(command, Status.VERWORFEN);
-	}
-
-	public Vorgang bescheiden(Command command) {
-		return executeStatusChangeCommand(command, Status.BESCHIEDEN);
-	}
-
-	public Vorgang abschliessen(Command command) {
-		return executeStatusChangeCommand(command, Status.ABGESCHLOSSEN);
-	}
-
-	public Vorgang wiedereroeffnen(Command command) {
-		return bearbeiten(command);
-	}
-
-	public Vorgang bearbeiten(Command command) {
-		return executeStatusChangeCommand(command, Status.IN_BEARBEITUNG);
-	}
-
-	Vorgang executeStatusChangeCommand(Command command, Status status) {
-		var vorgang = doUpdateStatus(command.getRelationId(), command.getRelationVersion(), status);
-
-		publisher.publishEvent(new StatusChangedEvent(command.getId()));
-
-		return vorgang;
-	}
-
-	public Vorgang setStatusToWeitergeleitet(Forwarding forwarding) {
-		return doUpdateStatusWithoutVerisonCheck(forwarding.getVorgangId(), Status.WEITERGELEITET, forwarding.getCreatedByCommand());
-	}
-
-	public Vorgang setStatusToInBearbeitung(String commandId, String vorgangId) {
-		return doUpdateStatusWithoutVerisonCheck(vorgangId, Status.IN_BEARBEITUNG, commandId);
-	}
-
-	Vorgang doUpdateStatusWithoutVerisonCheck(String vorgangId, Status newStatus, String commandId) {
-		repository.updateStatusWithoutVersionCheck(vorgangId, newStatus);
-
-		publisher.publishEvent(new StatusChangedEvent(commandId));
-
-		return getById(vorgangId);
-	}
-
-	public Vorgang revokeStatusChange(PersistedCommand command) {
-		return doUpdateStatus(command.getRelationId(), command.getRelationVersion() + 1, command.getPreviousStatus());
-	}
-
-	public void setStatusToInBearbeitung(String vorgangId, long version) {
-		doUpdateStatus(vorgangId, version, Status.IN_BEARBEITUNG);
-	}
-
-	Vorgang doUpdateStatus(String vorgangId, long version, Status status) {
-		Map<String, Object> patch = Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, status);
-
-		repository.patch(vorgangId, version, patch);
-
-		return getById(vorgangId);
-	}
-
 	public Vorgang getById(String vorgangId, FilterCriteria filterCriteria) {
 		var vorgang = getById(vorgangId);
 
@@ -196,7 +148,14 @@ public class VorgangService {
 	}
 
 	public Vorgang getById(String vorgangId) {
-		return removeUnpermittedClientAttributes(repository.findById(vorgangId).orElseThrow(() -> new NotFoundException(Vorgang.class, vorgangId)));
+		var loaded = removeUnpermittedClientAttributes(loadById(vorgangId));
+
+		return addLabels(loaded);
+	}
+
+	public void setAktenzeichen(Command command) {
+		var aktenzeichen = StringUtils.trimToNull(MapUtils.getString(command.getBodyObject(), BODY_OBJECT_AKTENZEICHEN));
+		repository.setAktenzeichen(command.getVorgangId(), command.getRelationVersion(), aktenzeichen);
 	}
 
 	Vorgang removeUnpermittedClientAttributes(Vorgang vorgang) {
@@ -206,7 +165,8 @@ public class VorgangService {
 	ClientAttributesMap removeUnpermitted(ClientAttributesMap attributes) {
 		var result = new ClientAttributesMap();
 
-		Optional.ofNullable(attributes).ifPresent(attri -> attri.entrySet().stream().map(this::removeUnpermitted)
+		Optional.ofNullable(attributes).ifPresent(attri -> attri.entrySet().stream()
+				.map(this::removeUnpermitted)
 				.filter(pair -> !pair.getValue().isEmpty())
 				.forEach(pair -> result.put(pair.getKey(), pair.getValue())));
 
@@ -215,14 +175,15 @@ public class VorgangService {
 
 	private Pair<String, ClientAttributeMap> removeUnpermitted(Entry<String, ClientAttributeMap> entry) {
 		var resultAttributeMap = new ClientAttributeMap();
-		entry.getValue().entrySet().stream().filter(e -> readIsPermitted.test(e.getValue()))
+		entry.getValue().entrySet().stream()
+				.filter(e -> readIsPermitted.test(e.getValue()))
 				.forEach(e -> resultAttributeMap.put(e.getKey(), e.getValue()));
 
 		return Pair.of(entry.getKey(), resultAttributeMap);
 	}
 
 	public void assignToUser(Command command) {
-		Map<String, Object> patch = Map.of(Vorgang.MONGODB_FIELDNAME_ASSIGNED_TO, command.getBody().get("assignedTo"));
+		var patch = Map.<String, Object>of(Vorgang.MONGODB_FIELDNAME_ASSIGNED_TO, command.getBody().get(BODY_ASSIGNED_TO_FIELD));
 
 		repository.patch(command.getRelationId(), command.getRelationVersion(), patch);
 
@@ -236,4 +197,21 @@ public class VorgangService {
 	public boolean exists(String vorgangId, Collection<String> organisationEinheitenIds) {
 		return repository.exists(vorgangId, organisationEinheitenIds);
 	}
+
+	Vorgang addLabels(Vorgang vorgang) {
+		var mappedEingaenge = vorgang.getEingangs().stream().map(kopControlDataMapper::addLabels).toList();
+
+		return vorgang.toBuilder().clearEingangs().eingangs(mappedEingaenge).build();
+	}
+
+	public void deleteVorgang(String vorgangId) {
+		// TODO check version
+		var stub = stubMapper.fromVorgang(loadById(vorgangId));
+
+		repository.saveStub(stub);
+	}
+
+	Vorgang loadById(String vorgangId) {
+		return repository.findById(vorgangId).orElseThrow(() -> new NotFoundException(Vorgang.class, vorgangId));
+	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangStub.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangStub.java
new file mode 100644
index 0000000000000000000000000000000000000000..11b74908865be193761e0744317f47b235f96f02
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangStub.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import java.time.ZonedDateTime;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.annotation.TypeAlias;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+@Document(collection = Vorgang.COLLECTION_NAME)
+@TypeAlias("VorgangStub")
+class VorgangStub {
+
+	@Id
+	private String id;
+	@Builder.Default
+	private Vorgang.Status status = Vorgang.Status.DELETED;
+
+	private String name;
+	private ZonedDateTime createdAt;
+	@Builder.Default
+	private ZonedDateTime deletedAt = ZonedDateTime.now();
+
+	private VorgangHeadStub header;
+
+	private EingangStub eingangs;
+
+}
+
+@Builder
+@Getter
+class VorgangHeadStub {
+	private String organisationsEinheitId;
+}
+
+@Builder
+@Getter
+class EingangStub {
+	private ZustaendigeStelleStub zustaendigeStelle;
+}
+
+@Builder
+@Getter
+class ZustaendigeStelleStub {
+	private String organisationseinheitenId;
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangStubMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangStubMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..2cff577369539d97d7a2aee22ab449baf175a46e
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangStubMapper.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import java.util.Optional;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+@Mapper
+interface VorgangStubMapper {
+
+	@Mapping(target = "deletedAt", ignore = true)
+	@Mapping(target = "status", constant = "DELETED")
+	@Mapping(target = "header", expression = "java(extractStubHeader(vorgang))")
+	@Mapping(target = "eingangs", expression = "java(extractStubEingang(vorgang))")
+	VorgangStub fromVorgang(Vorgang vorgang);
+
+	default VorgangHeadStub extractStubHeader(Vorgang vorgang) {
+		var builder = VorgangHeadStub.builder();
+		getOrganisationsEinheitenId(vorgang).ifPresent(builder::organisationsEinheitId);
+		return builder.build();
+	}
+
+	default EingangStub extractStubEingang(Vorgang vorgang) {
+		var builder = EingangStub.builder();
+		getOrganisationsEinheitenId(vorgang)
+				.map(orgaId -> ZustaendigeStelleStub.builder().organisationseinheitenId(orgaId).build())
+				.ifPresent(builder::zustaendigeStelle);
+		return builder.build();
+
+	}
+
+	default Optional<String> getOrganisationsEinheitenId(Vorgang vorgang) {
+		try {
+			return Optional.ofNullable(vorgang.getEingangs().get(0).getZustaendigeStelle().getOrganisationseinheitenId());
+		} catch (NullPointerException | IndexOutOfBoundsException e) {
+			return Optional.empty();
+		}
+	}
+
+}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangWithEingangMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangWithEingangMapper.java
similarity index 80%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangWithEingangMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangWithEingangMapper.java
index 55470c68f37ec74598e7232dda79ae81099cf3d6..476625793ffe0c6b237cf831798d38f57d90b93b 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/VorgangWithEingangMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangWithEingangMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.List;
 
@@ -32,11 +32,12 @@ import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributeMapper;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeMapper;
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoMapper;
 
-@Mapper(uses = { EingangMapper.class, ClientAttributeMapper.class }, //
-		nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
-		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
+@Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
+		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, //
+		uses = { EingangMapper.class, ClientAttributeMapper.class, ServiceKontoMapper.class })
 public abstract class VorgangWithEingangMapper {
 
 	@Autowired
@@ -59,5 +60,4 @@ public abstract class VorgangWithEingangMapper {
 		}
 		return eingaenge.get(0);
 	}
-
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelle.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelle.java
similarity index 78%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelle.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelle.java
index e639dd1459be5aeb6c38a964ac314d406481ff43..159d0b683de8fd40705bbfcbf48791ae18c66b04 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelle.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import lombok.Builder;
 import lombok.Getter;
@@ -35,4 +35,10 @@ public class ZustaendigeStelle {
 	private String organisationseinheitenId;
 	private String bezeichnung;
 	private String email;
+	private String gemeindeSchluessel;
+	private String amtlicherRegionalSchluessel;
+	private String hausanschriftStrasse;
+	private String hausanschriftPlz;
+	private String hausanschriftOrt;
+	private String telefon;
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleMapper.java
similarity index 93%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleMapper.java
index 61111fce307db394af1404a54bd7a1d4132a3a63..64418995e3a281f331d851b2853ddb954edc01fa 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import org.mapstruct.Mapper;
 import org.mapstruct.NullValueCheckStrategy;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/Forwarding.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/Forwarding.java
similarity index 94%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/Forwarding.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/Forwarding.java
index 1794efff21a3084dc39f50b56f21e3427c2f21e8..85600cea474d29120f5cb92daf9f4eeb6889fd04 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/Forwarding.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/Forwarding.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListener.java
similarity index 60%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListener.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListener.java
index f5aa9c5a00b801bce206dbc61bf7c6fe97b41d6c..8c653528a702854382b1799f8c8f2bb20d76dd60 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListener.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,28 +21,33 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
+import java.util.ConcurrentModificationException;
 import java.util.function.Predicate;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Component;
 
-import de.itvsh.ozg.mail.email.MailSendErrorEvent;
-import de.itvsh.ozg.mail.email.MailSendRequest;
-import de.itvsh.ozg.mail.email.MailSentEvent;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEvent;
-import de.itvsh.ozg.pluto.command.Order;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.nachrichten.email.MailSendErrorEvent;
+import de.ozgcloud.nachrichten.email.MailSendRequest;
+import de.ozgcloud.nachrichten.email.MailSentEvent;
+import de.ozgcloud.vorgang.command.Order;
+import lombok.extern.log4j.Log4j2;
 
 @Component
+@Log4j2
 public class ForwardingEventListener {
 
-	private static final String IS_REDIRECT_EVENT_CONDITION = "{T(de.itvsh.ozg.pluto.vorgang.redirect.ForwardingEventListener).IS_REDIRECT_MAIL_REQ.test(event.getSource())}";
-	private static final String IS_SUCCESSFULL_ORDER_CONDITION = "{T(de.itvsh.ozg.pluto.vorgang.redirect.ForwardingEventListener).IS_SUCCESSFULL_ORDER.test(event.getSource())}";
-	private static final String IS_FAILED_ORDER_CONDITION = "{T(de.itvsh.ozg.pluto.vorgang.redirect.ForwardingEventListener).IS_FAILED_ORDER.test(event.getSource())}";
-	private static final String IS_FORWARD_ORDER_CONDITION = "{T(de.itvsh.ozg.pluto.vorgang.redirect.ForwardingEventListener).IS_FORWARD_ORDER.test(event.getSource())}";
+	private static final String IS_REDIRECT_EVENT_CONDITION = "{T(de.ozgcloud.vorgang.vorgang.redirect.ForwardingEventListener).IS_REDIRECT_MAIL_REQ.test(event.getSource())}";
+	private static final String IS_SUCCESSFULL_ORDER_CONDITION = "{T(de.ozgcloud.vorgang.vorgang.redirect.ForwardingEventListener).IS_SUCCESSFULL_ORDER.test(event.getSource())}";
+	private static final String IS_FAILED_ORDER_CONDITION = "{T(de.ozgcloud.vorgang.vorgang.redirect.ForwardingEventListener).IS_FAILED_ORDER.test(event.getSource())}";
+	private static final String IS_FORWARD_ORDER_CONDITION = "{T(de.ozgcloud.vorgang.vorgang.redirect.ForwardingEventListener).IS_FORWARD_ORDER.test(event.getSource())}";
 
 	public static final Predicate<MailSendRequest> IS_REDIRECT_MAIL_REQ = req -> req.getRequestReference() instanceof Forwarding;
 	public static final Predicate<Command> IS_SUCCESSFULL_ORDER = command -> Order.FORWARD_SUCCESSFULL.isMeant(command.getOrder());
@@ -52,9 +57,12 @@ public class ForwardingEventListener {
 	@Autowired
 	private ForwardingService service;
 
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
 	@EventListener(condition = IS_FORWARD_ORDER_CONDITION)
 	public void onForwardOrder(CommandCreatedEvent event) {
-		service.forwardByCommand(event.getSource());
+		handleException(() -> service.forwardByCommand(event.getSource()), event.getSource().getId());
 	}
 
 	@EventListener(condition = IS_REDIRECT_EVENT_CONDITION)
@@ -73,11 +81,27 @@ public class ForwardingEventListener {
 
 	@EventListener(condition = IS_SUCCESSFULL_ORDER_CONDITION)
 	public void markAsSuccessfull(CommandCreatedEvent event) {
-		service.markAsSuccessfull(event.getSource());
+		handleException(() -> service.markAsSuccessfull(event.getSource()), event.getSource().getId());
 	}
 
 	@EventListener(condition = IS_FAILED_ORDER_CONDITION)
 	public void markAsFailed(CommandCreatedEvent event) {
 		service.markAsFailed(event.getSource());
 	}
+
+	private void handleException(Runnable runnable, String commandId) {
+		try {
+			runnable.run();
+		} catch (ConcurrentModificationException e) {
+			LOG.warn("Concurrent modification in executing Forwarding.");
+			publishFailedEvent(commandId, "Concurrent modification in executing Forwarding.");
+		} catch (RuntimeException e) {
+			LOG.error("Command failed with Exception", e);
+			publishFailedEvent(commandId, "Command Failed on Error");
+		}
+	}
+
+	private void publishFailedEvent(String commandId, String message) {
+		publisher.publishEvent(new CommandFailedEvent(commandId, message));
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingGrpcService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingGrpcService.java
similarity index 83%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingGrpcService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingGrpcService.java
index 91de06ebd2b14a2d1c1b6c13a1389a7edbf98980..0601c557ef04404c4a67f694cdaba8ba580d187b 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingGrpcService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingGrpcService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.ozg.pluto.forwarding.ForwardingServiceGrpc.ForwardingServiceImplBase;
-import de.itvsh.ozg.pluto.forwarding.GrpcFindForwardingsRequest;
-import de.itvsh.ozg.pluto.forwarding.GrpcForwardingsResponse;
+import de.ozgcloud.vorgang.forwarding.ForwardingServiceGrpc.ForwardingServiceImplBase;
+import de.ozgcloud.vorgang.forwarding.GrpcFindForwardingsRequest;
+import de.ozgcloud.vorgang.forwarding.GrpcForwardingsResponse;
 import io.grpc.stub.StreamObserver;
 import net.devh.boot.grpc.server.service.GrpcService;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingMapper.java
similarity index 88%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingMapper.java
index 1b0033d2629cc0bc77d23defc2ba52ba706dd826..5764a4c1242a4c80a6d74a33159f940b2688dc5e 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import org.mapstruct.Mapper;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 
-import de.itvsh.ozg.pluto.forwarding.GrpcForwarding;
+import de.ozgcloud.vorgang.forwarding.GrpcForwarding;
 
 @Mapper(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, //
 		nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRepository.java
similarity index 95%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingRepository.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRepository.java
index 1eca4f01bdf431d63aa6cd4b3a2fd8e8246e69a9..54b9a9d63e6a34bc3d82f7f0103223aa159b62f0 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingRepository.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRepository.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import static org.springframework.data.mongodb.core.query.Criteria.*;
 import static org.springframework.data.mongodb.core.query.Query.*;
@@ -39,7 +39,7 @@ import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.stereotype.Repository;
 
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
 
 @Repository
 class ForwardingRepository {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java
similarity index 86%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java
index 1e7382421261118dacc23e72cbce25df86a33bc2..bafd5600b2a8c63f8c33add5b5604c2d28398230 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -32,9 +32,6 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Stream;
 
-import javax.mail.util.ByteArrayDataSource;
-
-import de.itvsh.ozg.mail.email.MailRecipient;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -44,20 +41,25 @@ import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
 import org.springframework.util.MimeTypeUtils;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.ozg.mail.email.MailSendRequest;
-import de.itvsh.ozg.mail.email.MailSendRequest.MailAttachment;
-import de.itvsh.ozg.mail.email.MailService;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.PersistedCommand;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
-import de.itvsh.ozg.pluto.vorgang.redirect.Forwarding.Status;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.nachrichten.email.MailRecipient;
+import de.ozgcloud.nachrichten.email.MailSendRequest;
+import de.ozgcloud.nachrichten.email.MailSendRequest.MailAttachment;
+import de.ozgcloud.nachrichten.email.MailService;
+import de.ozgcloud.vorgang.command.PersistedCommand;
+import de.ozgcloud.vorgang.status.StatusService;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.redirect.Forwarding.Status;
 import freemarker.template.Configuration;
 import freemarker.template.Template;
 import freemarker.template.TemplateException;
+import jakarta.mail.util.ByteArrayDataSource;
+import lombok.extern.log4j.Log4j2;
 
 @Service
+@Log4j2
 public class ForwardingService {
 
 	static final String MAIL_TEMPLATE = "/mail/redirect.txt.ftlh";
@@ -99,26 +101,37 @@ public class ForwardingService {
 	@Autowired
 	private VorgangService vorgangService;
 
+	// TODO abhängigkeit entfernen
+	@Autowired
+	private StatusService statusService;
+
 	@Autowired
 	private ApplicationEventPublisher publisher;
 
-	@Value("${pluto.redirect.mail-from}")
+	@Value("${ozgcloud.redirect.mail-from}")
 	private String mailFrom;
-	@Value("${pluto.forwarding.reply-to:#{null}}")
+	@Value("${ozgcloud.forwarding.reply-to:#{null}}")
 	private Optional<String> replyTo;
-	@Value("${kop.production}")
+	@Value("${ozgcloud.production}")
 	private boolean production;
 
 	public Vorgang forwardByCommand(Command command) {
-		// TODO verify vorgang version _befor_ doing forward
 		var vorgang = vorgangService.getById(command.getRelationId());
-		redirectVorgang(vorgang, command);
-
-		vorgangService.setStatusToInBearbeitung(command.getRelationId(), command.getRelationVersion());
+		if (vorgang.getVersion() == command.getRelationVersion()) {
+			doRedirect(command, vorgang);
+		} else {
+			LOG.warn("concurrend modification on forwarding Vorgang");
+			markAsFailed(command);
+		}
 
 		return vorgang;
 	}
 
+	void doRedirect(Command command, Vorgang vorgang) {
+		statusService.setStatusToInBearbeitung(command.getRelationId(), command.getRelationVersion());
+		redirectVorgang(vorgang, command);
+	}
+
 	void redirectVorgang(Vorgang vorgang, Command command) {
 		var forwarding = saveForwarding(command);
 
@@ -189,7 +202,7 @@ public class ForwardingService {
 
 	private void setForwardingSent(Forwarding forwarding) {
 		repository.patch(forwarding.getId(),
-				Map.of(Forwarding.FIELD_STATUS, Forwarding.Status.SENT, Forwarding.FIELD_SENT_AT, ZonedDateTime.now(ZoneOffset.UTC)));
+				Map.of(Forwarding.FIELD_STATUS, Status.SENT, Forwarding.FIELD_SENT_AT, ZonedDateTime.now(ZoneOffset.UTC)));
 	}
 
 	public void sendRedirectConfirmationMail(Forwarding forwarding) {
@@ -227,7 +240,7 @@ public class ForwardingService {
 	}
 
 	private void setForwardingSendError(Forwarding forwarding, String errorMessage) {
-		repository.patch(forwarding.getId(), Map.of(Forwarding.FIELD_STATUS, Forwarding.Status.SEND_ERROR, Forwarding.FIELD_ERROR_MSG, errorMessage));
+		repository.patch(forwarding.getId(), Map.of(Forwarding.FIELD_STATUS, Status.SEND_ERROR, Forwarding.FIELD_ERROR_MSG, errorMessage));
 	}
 
 	MailSendRequest.MailSendRequestBuilder createRedirectMailRequestBuilder() {
@@ -302,13 +315,13 @@ public class ForwardingService {
 	}
 
 	public void markAsSuccessfull(Command command) {
-		repository.patch(command.getRelationId(), Map.of(Forwarding.FIELD_STATUS, Forwarding.Status.SUCCESSFULL));
+		repository.patch(command.getRelationId(), Map.of(Forwarding.FIELD_STATUS, Status.SUCCESSFULL));
 
 		publisher.publishEvent(new VorgangForwardSuccessfullEvent(command));
 	}
 
 	public void markAsFailed(Command command) {
-		repository.patch(command.getRelationId(), Map.of(Forwarding.FIELD_STATUS, Forwarding.Status.FAILED));
+		repository.patch(command.getRelationId(), Map.of(Forwarding.FIELD_STATUS, Status.FAILED));
 
 		publisher.publishEvent(new VorgangForwardFailedEvent(command));
 	}
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequest.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequest.java
similarity index 92%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequest.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequest.java
index 78ba579813d16cd33014330445210b1a9f9d5700..bb6c38c14dfad21c25a8f3a5240b4f718c052483 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequest.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequestMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequestMapper.java
similarity index 85%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequestMapper.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequestMapper.java
index e791933f8a196725bfc0a2dd5ec0e5fef760990d..19b702ed09c9a9e8188000a50cfa426d133ede45 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequestMapper.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequestMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import org.mapstruct.Mapper;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcRedirectRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcRedirectRequest;
 
 @Mapper
 public interface RedirectRequestMapper {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardFailedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardFailedEvent.java
similarity index 85%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardFailedEvent.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardFailedEvent.java
index 26491e2f59867a8450c1b7881e73369854172095..31681faef643b4de0449b8921ac496e6abf7027f 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardFailedEvent.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardFailedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandExecutedEvent;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
 import lombok.Getter;
 
 public class VorgangForwardFailedEvent extends CommandExecutedEvent {
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardSuccessfullEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardSuccessfullEvent.java
similarity index 84%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardSuccessfullEvent.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardSuccessfullEvent.java
index a51dcc0d1a363e9a0dcd60bab2ae06da4a559fa7..3734840459645532aa5600a3d1eb448b0c7125fc 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardSuccessfullEvent.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardSuccessfullEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandExecutedEvent;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
 
 public class VorgangForwardSuccessfullEvent extends CommandExecutedEvent {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectFailedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectFailedEvent.java
similarity index 87%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectFailedEvent.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectFailedEvent.java
index 2cfeff759ad6140466ff82999fa553d8db1638f9..e7052765bee7abc5870ba14f2a5cda4685d72adc 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectFailedEvent.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectFailedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
-import de.itvsh.ozg.pluto.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
 
 public class VorgangRedirectFailedEvent extends CommandFailedEvent {
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectedEvent.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectedEvent.java
similarity index 91%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectedEvent.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectedEvent.java
index c307ddfafba832e099c838fe9efed8b34135ae80..32c0ab6e85514cb893b4b1017a0d328710cca99d 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectedEvent.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import org.springframework.context.ApplicationEvent;
 
diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ZipBuilderService.java
similarity index 87%
rename from pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderService.java
rename to vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ZipBuilderService.java
index 5d022eed00a6b940903f4b722aafe8483d219b5d..296a88309e0b35ca4a06b3b7efe30a6b04f90356 100644
--- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/redirect/ZipBuilderService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -32,12 +32,12 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.MimeTypeUtils;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.ozg.pluto.files.FileService;
-import de.itvsh.ozg.pluto.vorgang.Eingang;
-import de.itvsh.ozg.pluto.vorgang.IncomingFile;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileGroup;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.vorgang.Eingang;
+import de.ozgcloud.vorgang.vorgang.IncomingFile;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroup;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
 import net.lingala.zip4j.io.outputstream.ZipOutputStream;
 import net.lingala.zip4j.model.ZipParameters;
 import net.lingala.zip4j.model.enums.AesKeyStrength;
@@ -101,7 +101,7 @@ class ZipBuilderService {
 		}
 
 		private String folderByContentType(String contentType) {
-			return StringUtils.equals(contentType, MimeTypeUtils.APPLICATION_XML_VALUE) ? FOLDER_NAME_XML : "/";
+			return StringUtils.equals(contentType, MimeTypeUtils.APPLICATION_XML_VALUE) ? FOLDER_NAME_XML : "";
 		}
 
 		private void addAttachments() {
@@ -113,7 +113,7 @@ class ZipBuilderService {
 		}
 
 		void addFile(String folder, IncomingFile file) {
-			var fileName = String.format(FILE_NAME_TEMPLATE, folder, file.getName());
+			var fileName = StringUtils.isEmpty(folder) ? file.getName() : String.format(FILE_NAME_TEMPLATE, folder, file.getName());
 
 			try {
 				zipOut.putNextEntry(buildZipParameter(fileName));
diff --git a/pluto-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/vorgang-manager-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json
similarity index 65%
rename from pluto-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json
rename to vorgang-manager-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index 8eff43ef35a026d11421528306fa3084a84fcd50..b56b784a5c67abbabf186369114185f7903da74e 100644
--- a/pluto-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/vorgang-manager-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -1,37 +1,37 @@
 {"properties": [
   {
-    "name": "pluto.redirect.mail-from",
+    "name": "ozgcloud.redirect.mail-from",
     "type": "java.lang.String",
     "description": "Mail address for forwarding"
   },
   {
-    "name": "pluto.production",
+    "name": "ozgcloud.production",
     "type": "java.lang.String",
     "description": "Enables/Disables the production mode. (default: false)"
   },
   {
-    "name": "pluto.forwarding.lninfo.url",
+    "name": "ozgcloud.forwarding.lninfo.url",
     "type": "java.lang.String",
     "description": "Source of landesnetzinfo given as url(http://) or filepath(classpath:)"
   },
   {
-    "name": "pluto.forwarding.reply-to",
+    "name": "ozgcloud.forwarding.reply-to",
     "type": "java.lang.String",
     "description": "Mail replyTo address for forwarding"
   },
   {
-    "name": "kop.production",
+    "name": "ozgcloud.osi.postfach.scheduler.enabled",
     "type": "java.lang.String",
-    "description": "Enable production mode"
+    "description": "Enable or disable polling of osi postfach for new messages"
   },
   {
-    "name": "kop.osi.postfach.scheduler.enabled",
+    "name": "ozgcloud.user-manager.url",
     "type": "java.lang.String",
-    "description": "Enable or disable polling of osi postfach for new messages"
+    "description": "Url of the user manager migration endpoint"
   },
   {
-    "name": "kop.usermanager.url",
+    "name": "ozgcloud.notification.mail-from",
     "type": "java.lang.String",
-    "description": "Url of the user manager migration endpoint"
+    "description": "The sender email address used in notification emails"
   }
 ]}
\ No newline at end of file
diff --git a/pluto-server/src/main/resources/META-INF/mime.types b/vorgang-manager-server/src/main/resources/META-INF/mime.types
similarity index 100%
rename from pluto-server/src/main/resources/META-INF/mime.types
rename to vorgang-manager-server/src/main/resources/META-INF/mime.types
diff --git a/vorgang-manager-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/vorgang-manager-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000000000000000000000000000000000000..08abec6c597ed602bc6a36d5de3111b9a0d66a74
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,20 @@
+net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientMetricAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientHealthAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientSecurityAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcClientTraceAutoConfiguration
+net.devh.boot.grpc.client.autoconfigure.GrpcDiscoveryClientAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonCodecAutoConfiguration
+net.devh.boot.grpc.common.autoconfigure.GrpcCommonTraceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcAdviceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcHealthServiceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataConsulConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataEurekaConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataNacosConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcMetadataZookeeperConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcReflectionServiceAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerMetricAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerSecurityAutoConfiguration
+net.devh.boot.grpc.server.autoconfigure.GrpcServerTraceAutoConfiguration
diff --git a/vorgang-manager-server/src/main/resources/application-a12proc.yml b/vorgang-manager-server/src/main/resources/application-a12proc.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ad31c61be02a08b82b7401c0c3eec085bfff5487
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/application-a12proc.yml
@@ -0,0 +1,23 @@
+ozgcloud:
+  processors:
+    - address: https://a12-client-a12presales-ozg-poc.mgm-demo.com/api/v1/ozg/process-request
+      name: mgm-demo
+      forms:
+        - formId: mob_dtickerst/mob_dtickerst
+          formEngineName: AFM
+          
+---
+
+spring:
+  config:
+    activate:
+      on-profile:
+      - nf
+      
+ozgcloud:
+  processors:
+    - address: http://a12-data-services:8080/api/v1/ozg/process-request
+      name: ticketCheck
+      forms:
+        - formId: mob_dtickerst/mob_dtickerst
+          formEngineName: AFM
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/resources/application-bayern.yml b/vorgang-manager-server/src/main/resources/application-bayern.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5a5b1a1d06ce9d320088689a1ce33a6f8dc7eb45
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/application-bayern.yml
@@ -0,0 +1,29 @@
+spring:
+  config:
+    activate:
+      on-profile:
+      - dev
+ozgcloud:
+  antragsraum:
+    url: dev.antragsraum.de
+
+---
+spring:
+  config:
+    activate:
+      on-profile:
+        - test
+ozgcloud:
+  antragsraum:
+    url: test.antragsraum.de
+
+---
+spring:
+  config:
+    activate:
+      on-profile:
+        - prod
+ozgcloud:
+  antragsraum:
+    url: www.antragsraum.de
+
diff --git a/vorgang-manager-server/src/main/resources/application-dev.yml b/vorgang-manager-server/src/main/resources/application-dev.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1deba0a36997fd105df02532f5b84151169c7efb
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/application-dev.yml
@@ -0,0 +1,9 @@
+
+ozgcloud:
+  redirect:
+    mail-from: dev-environment@ozg-cloud.de
+  notification:
+    mail-from: dev-environment@ozg-cloud.de
+  user:
+    cleanup:
+      cron: 0 */10 * * * *
diff --git a/vorgang-manager-server/src/main/resources/application-e2e.yml b/vorgang-manager-server/src/main/resources/application-e2e.yml
new file mode 100644
index 0000000000000000000000000000000000000000..78afbf9321c58f1c24a5cd313145e829ac211c7b
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/application-e2e.yml
@@ -0,0 +1,14 @@
+mongock:
+  enabled: false
+
+ozgcloud:
+  osi:
+    postfach:
+      scheduler:
+        enabled: false
+      proxyapi:
+        url: mockedForE2E
+        key: mockedForE2E
+        realm: mockedForE2E
+  elasticsearch:
+    index: e2e-test-index
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/resources/application-local.yml b/vorgang-manager-server/src/main/resources/application-local.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4b2b1a5e2a2a26d07c8cec055319b1972ee11a09
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/application-local.yml
@@ -0,0 +1,124 @@
+logging:
+  level:
+    root: WARN,
+    '[de.ozgcloud]': DEBUG
+    '[org.elasticsearch.client]': WARN
+    '[io.grpc]': WARN
+  config: classpath:log4j2-local.xml
+
+server:
+  port: 8085
+  
+management:
+  server.port: 8083
+  health:
+    elasticsearch:
+      enabled: false
+  endpoint:
+    health:
+      show-details: always
+
+grpc:
+  client:
+    user-manager:
+      address: static://127.0.0.1:9000
+      negotiationType: PLAINTEXT
+    zufi-manager:
+      address: static://127.0.0.1:9190
+      negotiationType: PLAINTEXT
+
+spring:
+  data:
+    mongodb:
+      database: vorgang-manager-local
+  mail:
+    username: ea@ozg-sh.de
+    password: 
+    host: mail.bruns.com.de
+    port: 587
+    properties:
+      '[mail.smtp.starttls.enable]': true
+
+ozgcloud:
+  aktenzeichen: de.ozgcloud.vorgang.vorgang.AktenzeichenProviderEA
+  notification:
+    mail-from: ea@ozg-sh.de
+  redirect:
+    mail-from: ea@ozg-sh.de
+  user-manager:
+    url: http://localhost:9092/migration/user
+  bescheid:
+    smart-documents:
+      url: https://demo-de.smartdocuments.com/wsxmldeposit/deposit/unattended
+      basicAuth:
+        username:
+        password: 
+      templateGroup: Kiel
+      template: Halteverbot
+#      proxy:
+#        host: http://localhost
+#        port: 8080
+#        username: theo
+#        password: 
+  user:
+    cleanup:
+      cron: 0 */5 * * * *
+  elasticsearch:
+    initEnabled: true
+    index: test-index
+
+
+mongock:
+  transactionEnabled: false
+
+---
+
+spring:
+  config:
+    activate:
+      on-profile:
+      - with-elastic
+ozgcloud:
+  elasticsearch:
+    address: localhost:9200
+    username: elastic
+    password: 
+    useSsl: false
+
+---
+
+spring:
+  config:
+    activate:
+      on-profile: osi
+
+ozgcloud:
+  osi:
+    postfach:
+      scheduler:
+        enabled: false
+        fixedDelay: 10000
+      proxyapi:
+        url: https://postfach.serviceportal-stage.schleswig-holstein.de/ApiProxy/V1/Message
+        key: db03d369-438a-4c1a-bcb8-9de951f5ef41
+        realm: urn:osp:names:realm:stage:sh
+
+---
+
+spring:
+  config:
+    activate:
+      on-profile: bayern-id
+ozgcloud:
+  osi:
+  bayernid:
+    enabled: true
+    absender:
+      name: Test Name
+      mandant: Fürth
+      dienst: Stadtverwaltung
+grpc:
+  client:
+    bayern-id:
+      address: static://127.0.0.1:9099
+      negotiationType: PLAINTEXT
diff --git a/pluto-server/src/main/resources/application-oc.yml b/vorgang-manager-server/src/main/resources/application-oc.yml
similarity index 100%
rename from pluto-server/src/main/resources/application-oc.yml
rename to vorgang-manager-server/src/main/resources/application-oc.yml
diff --git a/vorgang-manager-server/src/main/resources/application-prod.yml b/vorgang-manager-server/src/main/resources/application-prod.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3b582a12f15415965257e74bd51ea17790203a2b
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/application-prod.yml
@@ -0,0 +1,3 @@
+
+ozgcloud:
+  production: true
\ No newline at end of file
diff --git a/pluto-server/src/main/resources/application-stage.yml b/vorgang-manager-server/src/main/resources/application-stage.yml
similarity index 55%
rename from pluto-server/src/main/resources/application-stage.yml
rename to vorgang-manager-server/src/main/resources/application-stage.yml
index 73d4bd441c5354139515513c190d660937f92861..daeb1b5196313707d5c9a11df3385de03f9c36bf 100644
--- a/pluto-server/src/main/resources/application-stage.yml
+++ b/vorgang-manager-server/src/main/resources/application-stage.yml
@@ -1,3 +1,4 @@
 spring:
   mail:
+    host: 10.61.127.74
     port: 25
diff --git a/vorgang-manager-server/src/main/resources/application-test.yml b/vorgang-manager-server/src/main/resources/application-test.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ea66e7a80d5a857600704a7db51a11cc44ba5a37
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/application-test.yml
@@ -0,0 +1,7 @@
+
+     
+ozgcloud:
+  redirect:
+    mail-from: test-environment@ozg-cloud.de
+  notification:
+    mail-from: test-environment@ozg-cloud.de
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/resources/application-withdevdb.yml b/vorgang-manager-server/src/main/resources/application-withdevdb.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6004167c5430dcfdd60660b5ba6cfb9ca7222d8a
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/application-withdevdb.yml
@@ -0,0 +1,5 @@
+spring:
+  data:
+    mongodb:
+      database: vorgang-manager-database
+      uri: mongodb://vorgang-manager-user:XnHhfznNWg65NNd@192.168.101.199:30225/admin?ssl=false
\ No newline at end of file
diff --git a/pluto-server/src/main/resources/application.yml b/vorgang-manager-server/src/main/resources/application.yml
similarity index 53%
rename from pluto-server/src/main/resources/application.yml
rename to vorgang-manager-server/src/main/resources/application.yml
index 3864230aee4ada47c4e04c62de9af908d132e27c..a00f11e850e69fe95312019f1afa2f689dbd2cbd 100644
--- a/pluto-server/src/main/resources/application.yml
+++ b/vorgang-manager-server/src/main/resources/application.yml
@@ -1,38 +1,41 @@
 logging:
   level:
     ROOT: WARN
-    '[de.itvsh]': INFO
+    '[de.ozgcloud]': INFO
 
 mongock:
   runner-type: initializingbean
   migration-scan-package: 
-    - de.itvsh.ozg.pluto.common.migration
+    - de.ozgcloud.vorgang.common.migration
   enabled: true
   transactionEnabled: false
 
 spring:
   application:
-    name: Pluto
+    name: OzgCloud_VorgangManager
   data:
     mongodb:
       authentication-database: admin
   freemarker:
     cache: true
-    
 grpc:
   client:
     pluto:
       address: self:self
       negotiationType: PLAINTEXT
+    vorgang-manager:
+      address: self:self
+      negotiationType: PLAINTEXT
     user-manager:
-      address: static://127.0.0.1:9000
-      negotiationType: PLAINTEXT  
+      negotiationType: TLS  
     email:
       address: self:self
-      negotiationType: PLAINTEXT    
-pluto:
-  redirect:
-    mail-from: EA-Poststelle@itvsh.de
+      negotiationType: PLAINTEXT
+    nachrichten-manager:
+      address: self:self
+      negotiationType: PLAINTEXT
+    info-manager:
+      negotiationType: TLS
 
 management:
   server:
@@ -57,11 +60,25 @@ management:
       exposure:
         include: health,prometheus
 
-kop:
+ozgcloud:
   production: false
   osi:
     postfach:
       scheduler:
         enabled: true
+  redirect:
+    mail-from: EA-Poststelle@itvsh.de
   notification:
-    mail-from: hilfe@kop.support
+    mail-from: hilfe@ozgcloud.support
+#  vorgang-manager:
+#    address: self:self
+#    negotiation-type: plaintext
+#  file-manager:
+#    address: ${ozgcloud.vorgang-manager.address}
+#    negotiation-type: plaintext
+  command-manager:
+    address: self:self
+    negotiation-type: plaintext
+  user-manager:
+    address: ${grpc.client.user-manager.address:false}
+    negotiation-type: ${grpc.client.user-manager.negotiationType}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/resources/banner.txt b/vorgang-manager-server/src/main/resources/banner.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8f04f0a4cc084646ccf9273125819c899c317b56
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/banner.txt
@@ -0,0 +1,7 @@
+ __      ______  _____   _____          _   _  _____        __  __          _   _          _____ ______ _____
+ \ \    / / __ \|  __ \ / ____|   /\   | \ | |/ ____|      |  \/  |   /\   | \ | |   /\   / ____|  ____|  __ \
+  \ \  / / |  | | |__) | |  __   /  \  |  \| | |  __ ______| \  / |  /  \  |  \| |  /  \ | |  __| |__  | |__) |
+   \ \/ /| |  | |  _  /| | |_ | / /\ \ | . ` | | |_ |______| |\/| | / /\ \ | . ` | / /\ \| | |_ |  __| |  _  /
+    \  / | |__| | | \ \| |__| |/ ____ \| |\  | |__| |      | |  | |/ ____ \| |\  |/ ____ \ |__| | |____| | \ \
+     \/   \____/|_|  \_\\_____/_/    \_\_| \_|\_____|      |_|  |_/_/    \_\_| \_/_/    \_\_____|______|_|  \_\
+${spring-boot.version}		${application.version}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/main/resources/elastic/settings.json b/vorgang-manager-server/src/main/resources/elastic/settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..0fdf5ea8551a7b3ff2186a459eaf45be80b48867
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/elastic/settings.json
@@ -0,0 +1,10 @@
+{
+  "analysis": {
+    "normalizer": {
+      "lowercase_normalizer": {
+        "type": "custom",
+        "filter": [ "lowercase" ]
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/pluto-server/src/main/resources/images/logo-ea-sh.png b/vorgang-manager-server/src/main/resources/images/logo-ea-sh.png
similarity index 100%
rename from pluto-server/src/main/resources/images/logo-ea-sh.png
rename to vorgang-manager-server/src/main/resources/images/logo-ea-sh.png
diff --git a/pluto-server/src/main/resources/images/logo-itvsh.png b/vorgang-manager-server/src/main/resources/images/logo-itvsh.png
similarity index 100%
rename from pluto-server/src/main/resources/images/logo-itvsh.png
rename to vorgang-manager-server/src/main/resources/images/logo-itvsh.png
diff --git a/vorgang-manager-server/src/main/resources/log4j2-local.xml b/vorgang-manager-server/src/main/resources/log4j2-local.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c2dccf3ded007b92c1bf3129ec93031384b276a3
--- /dev/null
+++ b/vorgang-manager-server/src/main/resources/log4j2-local.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<configuration>
+	<Appenders>
+		<Console name="CONSOLE" target="SYSTEM_OUT">
+			<PatternLayout pattern="[%-5level] %c{1.} %msg%n"/>
+		</Console>
+	</Appenders>
+
+	<Loggers>
+		<Root level="WARN">
+			<appender-ref ref="CONSOLE" />
+		</Root>
+	</Loggers>
+</configuration>
\ No newline at end of file
diff --git a/pluto-server/src/main/resources/templates/mail/redirect.confirmation.txt.ftlh b/vorgang-manager-server/src/main/resources/templates/mail/redirect.confirmation.txt.ftlh
similarity index 97%
rename from pluto-server/src/main/resources/templates/mail/redirect.confirmation.txt.ftlh
rename to vorgang-manager-server/src/main/resources/templates/mail/redirect.confirmation.txt.ftlh
index ad1f80e3413be5d70f2b3234309f640383d6e261..0199a0303eb83a46bc4fd47a49f5b586bdf5723b 100644
--- a/pluto-server/src/main/resources/templates/mail/redirect.confirmation.txt.ftlh
+++ b/vorgang-manager-server/src/main/resources/templates/mail/redirect.confirmation.txt.ftlh
@@ -1,6 +1,6 @@
 <#--
 
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
diff --git a/pluto-server/src/main/resources/templates/mail/redirect.txt.ftlh b/vorgang-manager-server/src/main/resources/templates/mail/redirect.txt.ftlh
similarity index 97%
rename from pluto-server/src/main/resources/templates/mail/redirect.txt.ftlh
rename to vorgang-manager-server/src/main/resources/templates/mail/redirect.txt.ftlh
index 5ddfc936fc7ab6e22ca085cc6987629e8bc3e7ee..36e67356233b9b93f753ece6d048e3ffc05dc09f 100644
--- a/pluto-server/src/main/resources/templates/mail/redirect.txt.ftlh
+++ b/vorgang-manager-server/src/main/resources/templates/mail/redirect.txt.ftlh
@@ -1,6 +1,6 @@
 <#--
 
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeITCase.java
similarity index 83%
rename from pluto-server/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeITCase.java
index 840a7412fab8278e13036b8f2a49d240b7321bbd..10518201b0e9dfd81fd736febd5dd3b880d30ce9 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/mail/attributes/ClientAttributeITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/attributes/ClientAttributeITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.attributes;
+package de.ozgcloud.nachrichten.attributes;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -38,11 +38,11 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.test.annotation.DirtiesContext;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.mail.common.grpc.NachrichtenCallContextAttachingInterceptor;
-import de.itvsh.ozg.pluto.PlutoServerApplication;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttribute;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.nachrichten.common.grpc.NachrichtenCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.VorgangManagerServerApplication;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.Metadata;
 import io.grpc.Metadata.Key;
 import io.grpc.ServerCall;
@@ -52,7 +52,7 @@ import io.grpc.ServerInterceptor;
 import lombok.Getter;
 import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor;
 
-@SpringBootTest(classes = { PlutoServerApplication.class }, properties = {
+@SpringBootTest(classes = { VorgangManagerServerApplication.class }, properties = {
 		"grpc.server.inProcessName=test",
 		"grpc.server.port=-1",
 		"grpc.client.pluto.address=in-process:test"
@@ -66,12 +66,12 @@ class ClientAttributeITCase {
 	@Autowired
 	private ServerTestCallContextHandleInterceptor serverTestInterceptor;
 
-	// Um die Abhängigkeit zum Pluto-Code zu entfernen, kann man eine Server Dummy
+	// Um die Abhängigkeit zum VorgangManager-Code zu entfernen, kann man eine Server Dummy
 	// Implementierung machen
 	// siehe
 	// https://yidongnan.github.io/grpc-spring-boot-starter/en/client/testing.html#running-a-dummy-server
 	@MockBean
-	private de.itvsh.ozg.pluto.clientattribute.ClientAttributeService serverService;
+	private de.ozgcloud.vorgang.clientattribute.ClientAttributeService serverService;
 	@Captor
 	private ArgumentCaptor<ClientAttribute> attributeCaptor;
 
@@ -101,7 +101,7 @@ class ClientAttributeITCase {
 		}
 
 		private ClientAttribute createHasPostfachNachrichtAttribute() {
-			return de.itvsh.ozg.pluto.clientattribute.ClientAttributeTestFactory.createBuilder()
+			return de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory.createBuilder()
 					.clientName(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_CLIENT_NAME)
 					.attributeName(ClientAttributeService.ATTRIBUTE_NAME_HAS_POSTFACH_NACHRICHT)
 					.boolValue(Optional.of(true)).intValue(Optional.empty())
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/PostfachEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java
similarity index 67%
rename from pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/PostfachEventListenerITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java
index 5b34c1bce1e8866819fd0b839ea0ec185ef99be1..87eac4fcfde99bad92bb92d5362ba5c3c8333d14 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/PostfachEventListenerITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachEventListenerITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,27 +21,33 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Optional;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.boot.test.mock.mockito.SpyBean;
 import org.springframework.context.ApplicationEventPublisher;
 
-import de.itvsh.kop.common.test.ITCase;
-import de.itvsh.ozg.pluto.PlutoServerApplication;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEvent;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.VorgangManagerServerApplication;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
 
 @ITCase
-@SpringBootTest(classes = { PlutoServerApplication.class })
+@SpringBootTest(classes = { VorgangManagerServerApplication.class })
 class PostfachEventListenerITCase {
 
 	@Autowired
@@ -53,6 +59,12 @@ class PostfachEventListenerITCase {
 	@SpyBean
 	private PostfachEventListener listener;
 
+	@MockBean
+	private VorgangService vorgangService;
+
+	@MockBean
+	private CommandService commandService;
+
 	@Nested
 	class TestSendPostfachNachricht {
 
@@ -61,6 +73,11 @@ class PostfachEventListenerITCase {
 			when(command.getOrder()).thenReturn("SEND_POSTFACH_NACHRICHT");
 		}
 
+		@BeforeEach
+		void initServices() {
+			when(commandService.findCommand(any())).thenReturn(Optional.of(CommandTestFactory.create()));
+		}
+
 		@Test
 		void shouldCallService() {
 			doNothing().when(listener).sendPostfachNachricht(any());
@@ -68,7 +85,7 @@ class PostfachEventListenerITCase {
 
 			publisher.publishEvent(event);
 
-			verify(listener).sendPostfachNachricht(any());
+			verify(listener, timeout(500)).sendPostfachNachricht(any());
 		}
 	}
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachMailITCase.java
similarity index 68%
rename from pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachMailITCase.java
index 03d90f971d51523b7dead5b26f878cfb5b99bcfb..9dcdc08b3554b0bc133eb9b18eeebf4603d9ad75 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/PostfachMailITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachMailITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,8 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach;
 
+import static org.assertj.core.api.Assertions.*;
+import static org.awaitility.Awaitility.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
@@ -30,7 +32,9 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
 
 import java.time.ZonedDateTime;
 import java.time.temporal.ChronoUnit;
+import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
@@ -41,6 +45,7 @@ import org.mockito.Mock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.boot.test.mock.mockito.SpyBean;
 import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.MediaType;
@@ -49,21 +54,29 @@ import org.springframework.test.web.client.ExpectedCount;
 import org.springframework.test.web.client.MockRestServiceServer;
 import org.springframework.web.client.RestTemplate;
 
-import static org.assertj.core.api.Assertions.*;
-
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.mail.attributes.ClientAttributeService;
-import de.itvsh.ozg.pluto.PlutoServerApplication;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem;
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.files.FileId;
-import de.itvsh.ozg.pluto.files.FileService;
-import de.itvsh.ozg.pluto.files.OzgFile;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.nachrichten.attributes.ClientAttributeService;
+import de.ozgcloud.nachrichten.postfach.osi.MessageAttachmentTestFactory;
+import de.ozgcloud.nachrichten.postfach.osi.MessageJsonReplyTestFactory;
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+import de.ozgcloud.nachrichten.postfach.osi.OsiPostfachProperties;
+import de.ozgcloud.vorgang.VorgangManagerServerApplication;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.files.FileId;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.files.OzgFile;
 import io.grpc.stub.StreamObserver;
 
-@SpringBootTest(classes = { PlutoServerApplication.class, OsiPostfachProperties.class })
-@DataITCase
+@SpringBootTest(classes = { VorgangManagerServerApplication.class, OsiPostfachProperties.class }, properties = {
+		"ozgcloud.osi.postfach.proxyapi.url=http://localhost/ApiProxy/V1/Message",
+		"ozgcloud.osi.postfach.proxyapi.key=1234",
+		"ozgcloud.osi.postfach.proxyapi.realm=test-realm",
+		"ozgcloud.osi.postfach.notification.mail-from=test@local.host"
+})
 @WithMockUser
+@DataITCase
 class PostfachMailITCase {
 
 	private static final String TEST_OSI_POSTFACH_URI = "http://localhost/ApiProxy/V1/Message";
@@ -88,6 +101,9 @@ class PostfachMailITCase {
 	@MockBean
 	private ClientAttributeService clientAttributeService;
 
+	@SpyBean
+	private CommandService commandService;
+
 	@BeforeEach
 	void prepareDatabase() {
 		mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
@@ -126,9 +142,9 @@ class PostfachMailITCase {
 				mockServerSendSuccess();
 
 				callGrpcEndpoint();
-				var mails = callGrpcListEndpoint();
+				var mails = await().atMost(5, TimeUnit.SECONDS)
+						.until(PostfachMailITCase.this::callGrpcListEndpoint, PostfachMailITCase.this::hasAtLeastOneElement);
 
-				assertThat(mails).hasSize(1);
 				assertThat(mails.get(0).getCreatedAt()).isNotNull();
 				assertThat(mails.get(0).getDirection()).isEqualTo(GrpcDirection.OUT);
 				assertThat(mails.get(0).getSentAt()).isNotNull();
@@ -140,17 +156,27 @@ class PostfachMailITCase {
 		@Nested
 		class TestSendingFailed {
 
+			@BeforeEach
+			void init() {
+				mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
+			}
+
 			@Test
 			void shouldMarkFailed() {
 				mockServerSendFailed();
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+					assertThat(callGrpcListEndpoint()).isEmpty();
+				});
 
 				callGrpcEndpoint();
-				var mails = callGrpcListEndpoint();
 
-				assertThat(mails).hasSize(1);
-				assertThat(mails.get(0).getSentAt()).isNotNull();
-				assertThat(ZonedDateTime.parse(mails.get(0).getSentAt())).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS));
-				assertThat(mails.get(0).getSentSuccessful()).isFalse();
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+					assertThat(callGrpcListEndpoint()).hasSize(1).first().satisfies(mail -> {
+						assertThat(mail.getSentAt()).isNotNull();
+						assertThat(ZonedDateTime.parse(mail.getSentAt())).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS));
+						assertThat(mail.getSentSuccessful()).isFalse();
+					});
+				});
 			}
 
 			@Test
@@ -159,13 +185,13 @@ class PostfachMailITCase {
 				mockServerSendSuccess();
 				callGrpcEndpoint();
 
-				var mails = callGrpcListEndpoint();
+				var mails = await().atMost(5, TimeUnit.SECONDS)
+						.until(PostfachMailITCase.this::callGrpcListEndpoint, PostfachMailITCase.this::hasAtLeastOneElement);
 				var mailId = mails.get(0).getId();
 
 				callResendGrpcEndpoint(mailId);
-
-				mails = callGrpcListEndpoint();
-				assertThat(mails.get(0).getSentSuccessful()).isTrue();
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(
+						() -> assertThat(callGrpcListEndpoint()).hasSize(1).first().extracting(GrpcPostfachMail::getSentSuccessful).isEqualTo(true));
 			}
 
 			@Test
@@ -174,14 +200,15 @@ class PostfachMailITCase {
 				mockServerSendFailed();
 
 				callGrpcEndpoint();
-				var mails = callGrpcListEndpoint();
+				var mails = await().atMost(5, TimeUnit.SECONDS)
+						.until(PostfachMailITCase.this::callGrpcListEndpoint, PostfachMailITCase.this::hasAtLeastOneElement);
 				var mailId = mails.get(0).getId();
 
 				callResendGrpcEndpoint(mailId);
 
 				mails = callGrpcListEndpoint();
 				assertThat(mails.get(0).getSentSuccessful()).isFalse();
-				assertThat(mails.get(0).getMessageCode()).isEqualTo(OsiPostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE.getMessageCode());
+				assertThat(mails.get(0).getMessageCode()).isEqualTo(PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE.getMessageCode());
 			}
 		}
 
@@ -202,7 +229,7 @@ class PostfachMailITCase {
 		}
 
 		private GrpcSendPostfachMailRequest buildSendPostfachMailRequestWithoutAttachments() {
-			var grpcPostfachMail = GrpcPostfachMailTestFactory.createBuilder().clearAttachment().clearCreatedAt().clearDirection().build();
+			var grpcPostfachMail = GrpcPostfachMailTestFactory.createBuilder().clearId().clearAttachment().clearCreatedAt().clearDirection().build();
 			return GrpcSendPostfachMailRequestTestFactory.createBuilder().setMail(grpcPostfachMail).build();
 		}
 
@@ -234,9 +261,9 @@ class PostfachMailITCase {
 
 			@Test
 			void shouldListNachrichten() {
-				mockServerReceiveReply(OsiPostfachServiceTest.buildReplyJson());
+				mockServerReceiveReply(MessageJsonReplyTestFactory.buildReplyJson());
 
-				service.fetchAndPersistReplies();
+				fetchAndPersistReplies();
 
 				var mails = callGrpcListEndpoint();
 				assertThat(mails).hasSize(1);
@@ -248,9 +275,9 @@ class PostfachMailITCase {
 
 			@Test
 			void shouldContainAttachment() {
-				mockServerReceiveReply(OsiPostfachServiceTest.buildReplyJson());
+				mockServerReceiveReply(MessageJsonReplyTestFactory.buildReplyJson());
 
-				service.fetchAndPersistReplies();
+				fetchAndPersistReplies();
 
 				var mails = callGrpcListEndpoint();
 				assertThat(mails).hasSize(1);
@@ -260,17 +287,22 @@ class PostfachMailITCase {
 			@Test
 			void shouldHaveContentTypeDOCX() {
 				var attachment = MessageAttachmentTestFactory.createBuilder().fileName("wort-datei.docx").build();
+				mockServerReceiveReply(MessageJsonReplyTestFactory.buildReplyJson(MessageTestFactory.create(), attachment));
 
-				mockServerReceiveReply(OsiPostfachServiceTest.buildReplyJson(MessageTestFactory.create(),
-						attachment));
+				fetchAndPersistReplies();
 
-				service.fetchAndPersistReplies();
 				var mails = callGrpcListEndpoint();
-
+				assertThat(mails).hasSize(1);
 				var binaryFile = fileService.findFilesMetaData(List.of(FileId.from(mails.get(0).getAttachmentList().get(0)))).findFirst()
 						.orElse(OzgFile.builder().build());
 				assertThat(binaryFile.getContentType()).isEqualTo("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
 			}
+
+			private void fetchAndPersistReplies() {
+				service.fetchAndPersistReplies();
+
+				verify(commandService, timeout(5000)).setCommandFinished(any(), any());
+			}
 		}
 
 	}
@@ -283,4 +315,7 @@ class PostfachMailITCase {
 		return responseCaptor.getValue().getMailsList();
 	}
 
+	private boolean hasAtLeastOneElement(Collection<GrpcPostfachMail> mails) {
+		return !mails.isEmpty();
+	}
 }
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachServiceConfigurationITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachServiceConfigurationITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b2dcfeb38c92a2a62e36292261f356d36581c83
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/bayernid/BayernIdPostfachServiceConfigurationITCase.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.nachrichten.postfach.bayernid;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.VorgangManagerServerApplication;
+
+class BayernIdPostfachServiceConfigurationITCase {
+
+	@Nested
+	@SpringBootTest(classes = { VorgangManagerServerApplication.class })
+	@ITCase
+	class BayernIdPostfachServiceNotConfiguredITCase {
+
+		@Autowired(required = false)
+		private BayernIdPostfachRemoteService bayernIdPostfachRemoteService;
+
+		@Test
+		void contextLoads() {
+			assertThat(bayernIdPostfachRemoteService).isNull();
+		}
+	}
+
+	@Nested
+	@SpringBootTest(classes = { VorgangManagerServerApplication.class }, properties = {
+			"ozgcloud.bayernid.enabled=false",
+	})
+	@ITCase
+	class BayernIdPostfachServiceDisabledITCase {
+
+		@Autowired(required = false)
+		private BayernIdPostfachRemoteService bayernIdPostfachRemoteService;
+
+		@Test
+		void contextLoads() {
+			assertThat(bayernIdPostfachRemoteService).isNull();
+		}
+	}
+
+	@Nested
+	@SpringBootTest(classes = { VorgangManagerServerApplication.class }, properties = {
+			"ozgcloud.bayernid.enabled=true",
+			"ozgcloud.bayernid.absender.name=Test Name",
+			"ozgcloud.bayernid.absender.mandant=Fürth",
+			"ozgcloud.bayernid.absender.dienst=Stadtverwaltung",
+	})
+	@ITCase
+	class BayernIdPostfachServiceConfiguredITCase {
+
+		@Autowired
+		private BayernIdPostfachRemoteService bayernIdPostfachRemoteService;
+
+		@Test
+		void contextLoads() { // NOSONAR empty test just starting spring-boot
+		}
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachApiTestCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachApiTestCase.java
similarity index 63%
rename from pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachApiTestCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachApiTestCase.java
index 74011a52e89f5a7e88d3a215e0c90801e8865caf..9359d93eb61d3decb6e1ebb7d07d089f60c8c15b 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachApiTestCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachApiTestCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
@@ -33,25 +33,29 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 
-import de.itvsh.kop.common.test.ITCase;
-import de.itvsh.ozg.pluto.PlutoServerApplication;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.vorgang.VorgangManagerServerApplication;
 
 @Disabled("Echter Test für OSI Postfach mit echtem Zugriff. Unbedingt defaultmäßig deaktivieren!!")
-@SpringBootTest(properties = {
-		"kop.osi.postfach.proxyapi.url=https://postfach.serviceportal-stage.schleswig-holstein.de/ApiProxy/V1/Message",
-		"kop.osi.postfach.proxyapi.key=db03d369-438a-4c1a-bcb8-9de951f5ef41",
-		"kop.osi.postfach.proxyapi.realm=urn:osp:names:realm:stage:sh",
-		"kop.osi.postfach.scheduler.enabled=false"
-}, classes = { PlutoServerApplication.class, OsiPostfachProperties.class })
+@SpringBootTest(
+		classes = { VorgangManagerServerApplication.class, OsiPostfachProperties.class },
+		properties = {
+				"ozgcloud.osi.postfach.proxyapi.url=https://postfach.serviceportal-stage.schleswig-holstein.de/ApiProxy/V1/Message",
+				"ozgcloud.osi.postfach.proxyapi.key=db03d369-438a-4c1a-bcb8-9de951f5ef41",
+				"ozgcloud.osi.postfach.proxyapi.realm=urn:osp:names:realm:stage:sh",
+				"ozgcloud.osi.postfach.scheduler.enabled=false"
+		})
 @ITCase
 class OsiPostfachApiTestCase {
 
 	@Autowired
-	private OsiPostfachService service;
+	private OsiPostfachRemoteService service;
 
 	@Test
 	void testGetAllMessages() {
-		Stream<Message> messages = service.getAllMessages();
+		Stream<PostfachNachricht> messages = service.getAllMessages();
 
 		assertThat(messages).hasSizeGreaterThan(0);
 	}
@@ -60,11 +64,11 @@ class OsiPostfachApiTestCase {
 	@Disabled("Echter Test für OSI Postfach mit echtem Zugriff. Unbedingt defaultmäßig deaktivieren!!")
 	void testSendMessage() {
 
-		Message message = MessageTestFactory.createBuilder() //
+		PostfachNachricht nachricht = PostfachNachrichtTestFactory.createBuilder()
 				.postfachId("2f5c78f8-4891-456f-269b-08d937ab9a72").vorgangId("98877665544").build();
 
 		assertDoesNotThrow(() -> {
-			service.sendMessage(message);
+			service.sendMessage(nachricht);
 		});
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteServiceITCase.java
similarity index 63%
rename from pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachServiceITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteServiceITCase.java
index f1e56bfc42bb515532f19dd60d5e7755c2e164d1..3903e946374dae7bcc5a6d36d5c7275616be6565 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/mail/postfach/OsiPostfachServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/osi/OsiPostfachRemoteServiceITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.mail.postfach;
+package de.ozgcloud.nachrichten.postfach.osi;
 
 import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
 import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
 import static org.springframework.test.web.client.response.MockRestResponseCreators.*;
 
@@ -32,16 +33,25 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.http.MediaType;
 import org.springframework.test.web.client.MockRestServiceServer;
 import org.springframework.web.client.RestTemplate;
 
-import de.itvsh.kop.common.test.ITCase;
-import de.itvsh.ozg.pluto.PlutoServerApplication;
-
-@SpringBootTest(classes = { PlutoServerApplication.class, OsiPostfachProperties.class })
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.nachrichten.postfach.FileId;
+import de.ozgcloud.nachrichten.postfach.PostfachException;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.vorgang.VorgangManagerServerApplication;
+
+@SpringBootTest(classes = { VorgangManagerServerApplication.class, OsiPostfachProperties.class }, properties = {
+		"ozgcloud.osi.postfach.proxyapi.url=http://localhost/ApiProxy/V1/Message",
+		"ozgcloud.osi.postfach.proxyapi.key=1234",
+		"ozgcloud.osi.postfach.proxyapi.realm=test-realm",
+		"ozgcloud.osi.postfach.scheduler.enabled=false"
+})
 @ITCase
-class OsiPostfachServiceITCase {
+class OsiPostfachRemoteServiceITCase {
 
 	// properties, configured in application-itcase.yml
 	static final String URL = "http://localhost/ApiProxy/V1/Message";
@@ -49,22 +59,28 @@ class OsiPostfachServiceITCase {
 	static final String API_REALM = "test-realm";
 
 	@Autowired
-	private OsiPostfachService service;
+	private OsiPostfachRemoteService service;
+
 	@Autowired
 	private RestTemplate restTemplate;
 
+	@MockBean
+	private MessageAttachmentService messageAttachmentService;
+
 	private MockRestServiceServer mockServer;
 
 	@BeforeEach
 	void initMockServer() {
 		mockServer = MockRestServiceServer.createServer(restTemplate);
+		when(messageAttachmentService.getMessageAttachment(FileId.from(PostfachNachrichtTestFactory.ATTACHMENT_FILE_ID)))
+				.thenReturn(MessageAttachmentTestFactory.create());
 	}
 
 	@Test
 	void shouldCallWithApiKeyHeader() {
 		mockServer.expect(header(PostfachConfiguration.HEADER_API_KEY, API_KEY)).andRespond(withSuccess());
 
-		service.sendMessage(MessageTestFactory.create());
+		service.sendMessage(PostfachNachrichtTestFactory.create());
 
 		mockServer.verify();
 	}
@@ -73,7 +89,7 @@ class OsiPostfachServiceITCase {
 	void shouldCallWithRealmHeader() {
 		mockServer.expect(header(PostfachConfiguration.HEADER_API_REALM, API_REALM)).andRespond(withSuccess());
 
-		service.sendMessage(MessageTestFactory.create());
+		service.sendMessage(PostfachNachrichtTestFactory.create());
 
 		mockServer.verify();
 	}
@@ -82,7 +98,18 @@ class OsiPostfachServiceITCase {
 	void shouldRequestBaseUrl() {
 		mockServer.expect(requestTo(URL)).andRespond(withSuccess());
 
-		service.sendMessage(MessageTestFactory.create());
+		service.sendMessage(PostfachNachrichtTestFactory.create());
+
+		mockServer.verify();
+	}
+
+	@Test
+	void shouldSendHtmlBody() {
+		mockServer.expect(jsonPath("$.isHtml").value(true))
+				.andExpect(jsonPath("$.body").value(MessageTestFactory.MAIL_BODY))
+				.andRespond(withSuccess());
+
+		service.sendMessage(PostfachNachrichtTestFactory.create());
 
 		mockServer.verify();
 	}
@@ -95,7 +122,7 @@ class OsiPostfachServiceITCase {
 			mockServer.expect(header(PostfachConfiguration.HEADER_API_REALM, API_REALM))
 					.andRespond(withSuccess(String.valueOf(true), MediaType.APPLICATION_JSON));
 
-			service.sendMessage(MessageTestFactory.create());
+			service.sendMessage(PostfachNachrichtTestFactory.create());
 
 			mockServer.verify();
 		}
@@ -105,7 +132,7 @@ class OsiPostfachServiceITCase {
 			mockServer.expect(header(PostfachConfiguration.HEADER_API_REALM, API_REALM))
 					.andRespond(withSuccess(String.valueOf(false), MediaType.APPLICATION_JSON));
 
-			assertThrows(OsiPostfachException.class, () -> service.sendMessage(MessageTestFactory.create()));// NOSONAR
+			assertThrows(PostfachException.class, () -> service.sendMessage(PostfachNachrichtTestFactory.create()));// NOSONAR
 
 			mockServer.verify();
 		}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/processor/ProcessorITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/processor/ProcessorITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..e1ad5ebc6a1e9e044dd208ee9702c0cd07c98848
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/processor/ProcessorITCase.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.processor;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.awaitility.Awaitility.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.time.ZonedDateTime;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.test.context.ActiveProfiles;
+
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.notification.postfach.PostfachService;
+import de.ozgcloud.processor.processor.ProcessorService;
+import de.ozgcloud.processor.vorgang.Vorgang;
+import de.ozgcloud.processor.vorgang.VorgangId;
+import de.ozgcloud.processor.vorgang.VorgangService;
+import de.ozgcloud.vorgang.VorgangManagerServerApplication;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CreateCommandRequest;
+import de.ozgcloud.vorgang.command.PersistedCommand;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+@SpringBootTest(properties = {
+		"ozgcloud.processors.0.name=test",
+		"ozgcloud.processors.0.address=http://localhost:8090/testprocessor",
+		"ozgcloud.processors.0.forms.0.formEngineName=testFormEngine",
+		"ozgcloud.processors.0.forms.0.formId=testForm",
+		"grpc.server.port=9091",
+		"ozgcloud.command-manager.address=static://127.0.0.1:9091"
+}, classes = { VorgangManagerServerApplication.class })
+@ActiveProfiles({ "local", "itcase" })
+class ProcessorITCase {
+
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	@MockBean
+	private VorgangService processorVorgangService;
+
+	@MockBean
+	private PostfachService postfachService;
+	@MockBean
+	private de.ozgcloud.notification.vorgang.VorgangService notificationService;
+
+	@MockBean
+	private CommandService commandService;
+	@MockBean
+	private ProcessorService processorService;
+
+	@Captor
+	private ArgumentCaptor<CreateCommandRequest> requestCaptor;
+
+	@BeforeEach
+	void init() {
+		when(processorVorgangService.getVorgang(any())).thenReturn(buildVorgang());
+
+		when(notificationService.getVorgang(any())).thenReturn(de.ozgcloud.notification.vorgang.Vorgang.builder().build());
+
+		when(processorService.processVorgang(any())).thenThrow(RuntimeException.class);
+	}
+
+	@BeforeEach
+	void setupCommandService() {
+		var commandBuilder = PersistedCommand.builder().id("42").status(CommandStatus.PENDING).createdAt(ZonedDateTime.now());
+
+		when(commandService.createCommand(any())).thenReturn(commandBuilder.build());
+		when(commandService.findCommand("42"))
+				.thenReturn(Optional.of(commandBuilder.status(CommandStatus.FINISHED).finishedAt(ZonedDateTime.now()).build()));
+	}
+
+	@Test
+	void triggerProcessorOnNewVorgang() {
+		publisher.publishEvent(new VorgangCreatedEvent(VorgangTestFactory.ID));
+
+		await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+			verify(processorVorgangService).getVorgang(any());
+			verify(commandService).createCommand(requestCaptor.capture());
+		});
+
+		var request = requestCaptor.getValue();
+		@SuppressWarnings("unchecked")
+		Map<String, Object> item = (Map<String, Object>) request.getBodyObject().get("item");
+		assertThat(item).containsEntry("text", "Es ist eine Fehler bei der Verarbeitung des Vorganges aufgetreten");
+	}
+
+	private Vorgang buildVorgang() {
+		return Vorgang.builder()
+				.id(VorgangId.from(VorgangTestFactory.ID))
+				.formEngineName("testFormEngine")
+				.formId("testForm")
+				.build();
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/DbInitializer.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/DbInitializer.java
similarity index 95%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/DbInitializer.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/DbInitializer.java
index 63df9e20c2d650ddfb12151ffc68112a2a365d78..90a000df7baa3db4981d3032ef980ed8de7f9b77 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/DbInitializer.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/DbInitializer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto;
+package de.ozgcloud.vorgang;
 
 import org.springframework.boot.test.util.TestPropertyValues;
 import org.springframework.context.ApplicationContextInitializer;
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/TestConfiguration.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/TestConfiguration.java
similarity index 88%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/TestConfiguration.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/TestConfiguration.java
index 986bb23d2a90cfdab4d96380c26127e4bbfe555f..8e89a1180d025d063f00fda96e9b9c92d5ce28e7 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/TestConfiguration.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/TestConfiguration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto;
+package de.ozgcloud.vorgang;
 
 import static org.mockito.Mockito.*;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.mail.javamail.JavaMailSender;
 
 @Configuration
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/PlutoServerApplicationTests.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/VorgangManagerServerApplicationTests.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/PlutoServerApplicationTests.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/VorgangManagerServerApplicationTests.java
index 04165a66b7dd358232b417c6e18487642f009d28..4dfae4b476c75ceffaa8f15d09fe457837490300 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/PlutoServerApplicationTests.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/VorgangManagerServerApplicationTests.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto;
+package de.ozgcloud.vorgang;
 
 import org.junit.jupiter.api.Test;
 
-import de.itvsh.kop.common.test.ITCase;
+import de.ozgcloud.common.test.ITCase;
 
 @ITCase
-class PlutoServerApplicationTests {
+class VorgangManagerServerApplicationTests {
 
 	@Test
 	void contextLoads() { // NOSONAR empty test just starting spring-boot
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcFindVorgangAttachedItemRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcFindVorgangAttachedItemRequestTestFactory.java
similarity index 84%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcFindVorgangAttachedItemRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcFindVorgangAttachedItemRequestTestFactory.java
index 106e64bf180daae961e150902d8ca6f257d9a02c..a425c70bca72cb3260c21cf5b01d34628958963d 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcFindVorgangAttachedItemRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcFindVorgangAttachedItemRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
 
 class GrpcFindVorgangAttachedItemRequestTestFactory {
 	static GrpcFindVorgangAttachedItemRequest create() {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemMapperTest.java
similarity index 90%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemMapperTest.java
index 349658dc1008c0a92a40c4cafc91cf625bdfbf9f..2d03898aa9ade7d4489423075b045b513c47789f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -31,9 +31,9 @@ import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem;
 
 class GrpcVorgangAttachedItemMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemRequestTestFactory.java
similarity index 86%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemRequestTestFactory.java
index 734d98faee313032fd66715f96aef3a026995ec1..5e8883bf6891ba8a138cbd0df2b55b6b3507f466 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
 
 class GrpcVorgangAttachedItemRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemResponseTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemResponseTestFactory.java
similarity index 86%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemResponseTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemResponseTestFactory.java
index 81a3a6ef7a552fd1218f00269b9d7b841d7682e1..7415bc1373295c50a980c487b3954d1955eeaa3f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemResponseTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemResponseTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemResponse;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemResponse;
 
 class GrpcVorgangAttachedItemResponseTestFactory {
 	static GrpcVorgangAttachedItemResponse create() {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemServiceTest.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemServiceTest.java
index 6ca7dcd7629777dd876d93f8d5f6d6168bc0aac1..62f7cdce03d41f7d6a3c18226425964cbb7bca14 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -37,12 +37,12 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemResponse;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemResponse;
 import io.grpc.stub.StreamObserver;
 
 class GrpcVorgangAttachedItemServiceTest {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemTestFactory.java
index 42edf9b52834a8205ffef8c07f7865532876188b..d8fb94611ebed74b2623f0dbd199a70e347971ca 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/GrpcVorgangAttachedItemTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/GrpcVorgangAttachedItemTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
-import de.itvsh.ozg.pluto.common.GrpcObject;
-import de.itvsh.ozg.pluto.common.GrpcProperty;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem;
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.common.GrpcProperty;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem;
 
 public class GrpcVorgangAttachedItemTestFactory {
 	public static final String PROPERTY_NAME = "propertyName";
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepositoryImplTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepositoryImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ec17fa5660d3bdfda71f9ba17eef56abe3d8dcc
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemCustomRepositoryImplTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.attached_item;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.data.mongodb.core.MongoOperations;
+
+import com.mongodb.client.result.DeleteResult;
+import com.mongodb.client.result.UpdateResult;
+
+import de.ozgcloud.vorgang.common.db.CollisionVerifier;
+
+class VorgangAttachedItemCustomRepositoryImplTest {
+
+	@Spy
+	@InjectMocks
+	private VorgangAttachedItemCustomRepositoryImpl repository;
+
+	@Mock
+	private MongoOperations mongoOperations;
+	@Mock
+	private CollisionVerifier collisionVerifier;
+
+	@Nested
+	class TestDelete {
+
+		@Test
+		void shouldCallCollisionVerifier() {
+			var deleteResult = mock(DeleteResult.class);
+			when(mongoOperations.remove(any(), anyString())).thenReturn(deleteResult);
+
+			repository.delete(VorgangAttachedItemTestFactory.ID, VorgangAttachedItemTestFactory.VERSION);
+
+			verify(collisionVerifier).verify(deleteResult, VorgangAttachedItemTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestMarkAsDeleted {
+
+		@Test
+		void shouldCallCollisionVerifier() {
+			var updateResult = mock(UpdateResult.class);
+			when(mongoOperations.updateFirst(any(), any(), anyString())).thenReturn(updateResult);
+
+			repository.updateDeleted(true, VorgangAttachedItemTestFactory.ID, VorgangAttachedItemTestFactory.VERSION);
+
+			verify(collisionVerifier).verify(updateResult, VorgangAttachedItemTestFactory.ID);
+		}
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java
similarity index 55%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListenerITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java
index 680f8bbee55495bb5ff805e06a72334113946228..2c17022b5ffda7ae5833ab9f9086fc90cb99d11b 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListenerITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
+import static org.awaitility.Awaitility.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
@@ -35,11 +37,15 @@ import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.boot.test.mock.mockito.SpyBean;
 import org.springframework.context.ApplicationEventPublisher;
 
-import de.itvsh.kop.common.test.ITCase;
-import de.itvsh.ozg.pluto.command.CommandCreatedEventTestFactory;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.command.Order;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.vorgang.VorgangDeletedEventTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 @ITCase
 class VorgangAttachedItemEventListenerITCase {
@@ -51,6 +57,10 @@ class VorgangAttachedItemEventListenerITCase {
 	private VorgangAttachedItemEventListener listener;
 	@MockBean
 	private VorgangAttachedItemService service;
+	@MockBean
+	private VorgangService vorgangService;
+	@MockBean
+	private CommandService commandService;
 
 	@Nested
 	class TestOnCreateItemCommand {
@@ -62,7 +72,7 @@ class VorgangAttachedItemEventListenerITCase {
 
 			publisher.publishEvent(event);
 
-			verify(listener).createItem(any());
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener).createItem(any()));
 		}
 	}
 
@@ -76,7 +86,7 @@ class VorgangAttachedItemEventListenerITCase {
 
 			publisher.publishEvent(event);
 
-			verify(listener).updateItem(any());
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener).updateItem(any()));
 		}
 	}
 
@@ -92,8 +102,49 @@ class VorgangAttachedItemEventListenerITCase {
 
 			publisher.publishEvent(event);
 
-			verify(listener).patchItem(any());
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener).patchItem(any()));
+		}
+	}
+
+	@Nested
+	class TestOnDeleteItemCommand {
+
+		@Test
+		void shouldCallListener() {
+			var command = CommandTestFactory.createBuilder().order(Order.DELETE_ATTACHED_ITEM.name()).build();
+			var event = CommandCreatedEventTestFactory.create(command);
+
+			publisher.publishEvent(event);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener).deleteItem(any()));
 		}
 	}
 
+	@Nested
+	class TestDeleteOnVorgangDeleted {
+
+		@Test
+		void shouldCallListener() {
+			publisher.publishEvent(VorgangDeletedEventTestFactory.create());
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(listener).onVorgangDeleted(any()));
+		}
+	}
+
+	@Nested
+	class TestOnRevokeDeleteItem {
+
+		@Test
+		void shouldCallUnmarkAsDeleted() {
+			var command = CommandTestFactory.createBuilder().order(Order.DELETE_ATTACHED_ITEM.name()).build();
+			var event = new RevokeCommandEvent(command);
+
+			publisher.publishEvent(event);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(
+					() -> verify(service).unmarkAsDeleteByIdAndVersion(CommandTestFactory.RELATION_ID, CommandTestFactory.RELATION_VERSION));
+		}
+
+	}
+
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java
similarity index 67%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListenerTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java
index 2daaf6b72b466c60f2bbd1f0674453fb555bcf85..d35c2a32ff6d80288417daa09965ba55f6b3324f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemEventListenerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemEventListenerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -30,7 +30,7 @@ import static org.mockito.Mockito.*;
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.validation.ValidationException;
+import jakarta.validation.ValidationException;
 
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -41,19 +41,26 @@ import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
+import org.springframework.context.ApplicationEventPublisher;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEventTestFactory;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandRevokeFailedEvent;
+import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangDeletedEventTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class VorgangAttachedItemEventListenerTest {
 
+	@Spy
 	@InjectMocks
 	private VorgangAttachedItemEventListener listener;
 
 	@Mock
 	private VorgangAttachedItemService service;
+	@Mock
+	private ApplicationEventPublisher publisher;
 	@Spy
 	private VorgangAttachedItemMapper mapper = Mappers.getMapper(VorgangAttachedItemMapper.class);
 
@@ -187,4 +194,75 @@ class VorgangAttachedItemEventListenerTest {
 		}
 	}
 
+	@Nested
+	@DisplayName("Delete item")
+	class TestDeleteItem {
+
+		private Command command = CommandTestFactory.createBuilder().relationId(VorgangAttachedItemTestFactory.ID)
+				.relationVersion(VorgangAttachedItemTestFactory.VERSION).build();
+
+		@Nested
+		@DisplayName("by itemId and version")
+		class TestDeleteByIdAndVersion {
+
+			@Test
+			void shouldCallService() {
+				listener.deleteItem(CommandCreatedEventTestFactory.create(command));
+
+				verify(service).markAsDeleteByIdAndVersion(VorgangAttachedItemTestFactory.ID, VorgangAttachedItemTestFactory.VERSION);
+			}
+
+			@Test
+			void shouldPublishCommandExecutedEvent() {
+				listener.deleteItem(CommandCreatedEventTestFactory.create(command));
+
+				verify(publisher).publishEvent(any(VorgangAttachedItemDeletedEvent.class));
+			}
+
+			@Test
+			void shouldCallHandleException() {
+				doThrow(new RuntimeException()).when(service).markAsDeleteByIdAndVersion(anyString(), anyLong());
+
+				listener.deleteItem(CommandCreatedEventTestFactory.create(command));
+
+				verify(listener).handleException(any(), eq(CommandTestFactory.ID));
+			}
+		}
+
+		@Nested
+		@DisplayName("by vorgangId")
+		class TestDeleteByVorgangId {
+
+			@Test
+			void shouldCallService() {
+				listener.onVorgangDeleted(VorgangDeletedEventTestFactory.create());
+
+				verify(service).deleteByVorgangId(VorgangTestFactory.ID);
+			}
+		}
+	}
+
+	@Nested
+	class TestRevokeCommand {
+
+		@Nested
+		class TestDeleteItem {
+
+			@Test
+			void shouldCallService() {
+				listener.onRevokeDeleteItem(new RevokeCommandEvent(CommandTestFactory.createBuilder().build()));
+
+				verify(service).unmarkAsDeleteByIdAndVersion(CommandTestFactory.RELATION_ID, CommandTestFactory.RELATION_VERSION);
+			}
+
+			@Test
+			void shouldCallHandleException() {
+				doThrow(new RuntimeException()).when(service).unmarkAsDeleteByIdAndVersion(anyString(), anyLong());
+
+				listener.onRevokeDeleteItem(new RevokeCommandEvent(CommandTestFactory.createBuilder().build()));
+
+				verify(publisher).publishEvent(any(CommandRevokeFailedEvent.class));
+			}
+		}
+	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemITCase.java
similarity index 74%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemITCase.java
index f15c945e394de91a4a258ed9bf52f8d596c00562..fa3ee8e9efaa8a05d86dc2cc03ffff32472cbb61 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import static org.assertj.core.api.Assertions.*;
+import static org.awaitility.Awaitility.*;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
 import java.util.HashMap;
 import java.util.Optional;
+import java.util.concurrent.TimeUnit;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
@@ -43,20 +45,20 @@ import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.security.access.AccessDeniedException;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEvent;
-import de.itvsh.ozg.pluto.command.CommandCreatedEventTestFactory;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.command.Order;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelleTestFactory;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
-import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemResponse;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemRequest;
+import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItemResponse;
 import io.grpc.stub.StreamObserver;
 
 @DataITCase
@@ -64,6 +66,7 @@ class VorgangAttachedItemITCase {
 
 	@Autowired
 	private GrpcVorgangAttachedItemService service;
+
 	@MockBean
 	private CurrentUserService currentUserService;
 	@Autowired
@@ -87,13 +90,15 @@ class VorgangAttachedItemITCase {
 		@Test
 		void shouldPersistInDatabase() {
 			publisher.publishEvent(event);
-
-			var loaded = mongoOperations.findAll(VorgangAttachedItem.class);
-
-			assertThat(loaded).hasSize(1);
-			assertThat(loaded.get(0)).usingRecursiveComparison().ignoringFields("id", "version").isEqualTo(VorgangAttachedItemTestFactory.create());
-			assertThat(loaded.get(0).getId()).isNotNull();
-			assertThat(loaded.get(0).getVersion()).isEqualTo(1L);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var loadedItems = mongoOperations.findAll(VorgangAttachedItem.class);
+
+				assertThat(loadedItems).hasSize(1).first().satisfies(item -> {
+					assertThat(item).usingRecursiveComparison().ignoringFields("id", "version").isEqualTo(VorgangAttachedItemTestFactory.create());
+					assertThat(item.getId()).isNotNull();
+					assertThat(item.getVersion()).isEqualTo(1L);
+				});
+			});
 		}
 	}
 
@@ -114,9 +119,9 @@ class VorgangAttachedItemITCase {
 
 		@BeforeEach
 		void step2createEvent() {
-			var itemMap = new HashMap<String, Object>(persistedItem.getItem());
+			var itemMap = new HashMap<>(persistedItem.getItem());
 
-			var bodyObjectMap = new HashMap<String, Object>(VorgangAttachedItemTestFactory.asMap());
+			var bodyObjectMap = new HashMap<>(VorgangAttachedItemTestFactory.asMap());
 			bodyObjectMap.put(VorgangAttachedItem.FIELDNAME_ITEM, itemMap);
 			command = CommandTestFactory.createBuilder()
 					.order(Order.UPDATE_ATTACHED_ITEM.name())
@@ -131,11 +136,14 @@ class VorgangAttachedItemITCase {
 		void shouldIncrementVersion() {
 			publisher.publishEvent(event);
 
-			var loaded = mongoOperations.findAll(VorgangAttachedItem.class);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var loaded = mongoOperations.findAll(VorgangAttachedItem.class);
 
-			assertThat(loaded).hasSize(1);
-			assertThat(loaded.get(0)).usingRecursiveComparison().ignoringFields("id", "version").isEqualTo(VorgangAttachedItemTestFactory.create());
-			assertThat(loaded.get(0).getVersion()).isEqualTo(2L);
+				assertThat(loaded).hasSize(1).first().satisfies(item -> {
+					assertThat(item).usingRecursiveComparison().ignoringFields("id", "version").isEqualTo(VorgangAttachedItemTestFactory.create());
+					assertThat(item.getVersion()).isEqualTo(2L);
+				});
+			});
 		}
 	}
 
@@ -173,11 +181,13 @@ class VorgangAttachedItemITCase {
 				assertDoesNotThrow(() -> doFind());
 			}
 
+			// TODO remove this Test. Implement PoicyServiceITCase to test permission check
+			// and verify service call in Unit Test
 			@Test
 			void shouldThrowAccessDeniedException() {
 				var user = CallContextUserTestFactory.createBuilder()
 						.organisationEinheitenIdCheckNecessary(true)
-						.organisatorischeEinheitenId("doesNotMatch")
+						.clearOrganisatorischeEinheitenIds().organisatorischeEinheitenId("doesNotMatch")
 						.build();
 				when(currentUserService.findUser()).thenReturn(Optional.of(user));
 
@@ -233,7 +243,7 @@ class VorgangAttachedItemITCase {
 			@Test
 			void shouldThrowAccessDeniedException() {
 				var user = CallContextUserTestFactory.createBuilder()
-						.organisatorischeEinheitenId("doesNotMatch")
+						.clearOrganisatorischeEinheitenIds().organisatorischeEinheitenId("doesNotMatch")
 						.build();
 				when(currentUserService.findUser()).thenReturn(Optional.of(user));
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemMapperTest.java
similarity index 93%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemMapperTest.java
index 6a6a39be89259dd0ec55a07007e690e5e1ab188a..faec91f538266925e16db25f0991ca0bb1345a62 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemRepositoryITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc9fbe425e570aa1af0090ebacaca1b5c08f82ef
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemRepositoryITCase.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.attached_item;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+@DataITCase
+class VorgangAttachedItemRepositoryITCase {
+
+	@Autowired
+	private VorgangAttachedItemRepository repository;
+	@Autowired
+	private MongoOperations mongoOperations;
+
+	private VorgangAttachedItem persistedItem;
+
+	@BeforeEach
+	void prepareDatabase() {
+		mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
+	}
+
+	@DisplayName("Find by")
+	@Nested
+	class TestFindBy {
+
+		@BeforeEach
+		void init() {
+			persistedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).build());
+		}
+
+		@Nested
+		class VorgangIdAndClientAndItemName {
+
+			@Test
+			void shouldReturnResult() {
+				var loadedItems = repository.findByVorgangIdAndClientAndItemNameAndDeleted(VorgangTestFactory.ID,
+						VorgangAttachedItemTestFactory.CLIENT,
+						VorgangAttachedItemTestFactory.ITEM_NAME, VorgangAttachedItemService.NOT_DELETED);
+
+				assertThat(loadedItems).hasSize(1);
+			}
+
+			@Test
+			void shouldReturnEmptyResult() {
+				var loadedItems = repository.findByVorgangIdAndClientAndItemNameAndDeleted(VorgangTestFactory.ID,
+						VorgangAttachedItemTestFactory.CLIENT,
+						VorgangAttachedItemTestFactory.ITEM_NAME, VorgangAttachedItemTestFactory.DELETED);
+
+				assertThat(loadedItems).isEmpty();
+			}
+		}
+
+		@Nested
+		class VorgangIdAndClient {
+
+			@Test
+			void shouldReturnResult() {
+				var loadedItems = repository.findByVorgangIdAndClientAndDeleted(VorgangTestFactory.ID, VorgangAttachedItemTestFactory.CLIENT,
+						VorgangAttachedItemService.NOT_DELETED);
+
+				assertThat(loadedItems).hasSize(1);
+			}
+
+			@Test
+			void shouldReturnEmptyResult() {
+				var loadedItems = repository.findByVorgangIdAndClientAndDeleted(VorgangTestFactory.ID, VorgangAttachedItemTestFactory.CLIENT,
+						VorgangAttachedItemTestFactory.DELETED);
+
+				assertThat(loadedItems).isEmpty();
+			}
+		}
+
+		@Nested
+		class VorgangIdAndItemName {
+
+			@Test
+			void shouldReturnResult() {
+				var loadedItems = repository.findByVorgangIdAndItemNameAndDeleted(VorgangTestFactory.ID, VorgangAttachedItemTestFactory.ITEM_NAME,
+						VorgangAttachedItemService.NOT_DELETED);
+
+				assertThat(loadedItems).hasSize(1);
+			}
+
+			@Test
+			void shouldReturnEmptyResult() {
+				var loadedItems = repository.findByVorgangIdAndItemNameAndDeleted(VorgangTestFactory.ID, VorgangAttachedItemTestFactory.ITEM_NAME,
+						VorgangAttachedItemTestFactory.DELETED);
+
+				assertThat(loadedItems).isEmpty();
+			}
+		}
+
+		@Nested
+		class VorgangId {
+
+			@Test
+			void shouldReturnResult() {
+				var loadedItems = repository.findByVorgangIdAndDeleted(VorgangTestFactory.ID, VorgangAttachedItemService.NOT_DELETED);
+
+				assertThat(loadedItems).hasSize(1);
+			}
+
+			@Test
+			void shouldReturnEmptyResult() {
+				var loadedItems = repository.findByVorgangIdAndDeleted(VorgangTestFactory.ID, VorgangAttachedItemTestFactory.DELETED);
+
+				assertThat(loadedItems).isEmpty();
+			}
+		}
+	}
+
+	@Nested
+	class TestPatch {
+
+		@BeforeEach
+		void prepareDatabase() {
+			mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
+
+			persistedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).build());
+		}
+
+		@Test
+		void shouldUpdateFieldValue() {
+			repository.patch(persistedItem.getId(), persistedItem.getVersion(), buildPatchMap());
+
+			var loaded = findVorgangAttachedItem();
+			assertThat(loaded).isNotNull();
+			assertThat(loaded.getItem()).containsOnly(
+					entry("dontTouch", 600),
+					entry(VorgangAttachedItemTestFactory.ITEM_FIELD_NAME, VorgangAttachedItemTestFactory.ITEM_FIELD_STRING_VALUE));
+		}
+
+		@Test
+		void shouldUpdateWithNullValue() {
+			Map<String, Object> sourceMap = Collections.singletonMap(VorgangAttachedItemTestFactory.ITEM_FIELD_NAME, null);
+
+			repository.patch(persistedItem.getId(), persistedItem.getVersion(), sourceMap);
+
+			var loaded = findVorgangAttachedItem();
+			assertThat(loaded.getItem()).containsOnly(entry(VorgangAttachedItemTestFactory.ITEM_FIELD_NAME, null));
+		}
+
+		@Test
+		void shouldIncreaseVersion() {
+			repository.patch(persistedItem.getId(), persistedItem.getVersion(), buildPatchMap());
+
+			var loaded = findVorgangAttachedItem();
+			assertThat(loaded).isNotNull();
+			assertThat(loaded.getVersion()).isEqualTo(persistedItem.getVersion() + 1);
+		}
+
+		@Test
+		void shouldNotUpdateOnWrongVersion() {
+			repository.patch(persistedItem.getId(), 42, buildPatchMap());
+
+			var loaded = findVorgangAttachedItem();
+
+			assertThat(loaded).usingRecursiveComparison().isEqualTo(persistedItem);
+		}
+
+		@Test
+		void shouldNotPatchDeletedItem() {
+			var deletedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).deleted(true).build());
+
+			repository.patch(deletedItem.getId(), deletedItem.getVersion(), buildPatchMap());
+
+			var loaded = mongoOperations.findById(deletedItem.getId(), VorgangAttachedItem.class);
+			assertThat(loaded).usingRecursiveComparison().isEqualTo(deletedItem);
+		}
+
+		private Map<String, Object> buildPatchMap() {
+			return Map.of("dontTouch", 600);
+		}
+	}
+
+	@Nested
+	class TestForceUpdate {
+
+		@Test
+		void shouldNotPatchDeletedItem() {
+			var deletedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).deleted(true).build());
+
+			repository.forcePatch(deletedItem.getId(), buildPatchMap());
+
+			var loaded = mongoOperations.findById(deletedItem.getId(), VorgangAttachedItem.class);
+			assertThat(loaded).usingRecursiveComparison().isEqualTo(deletedItem);
+		}
+
+		private Map<String, Object> buildPatchMap() {
+			return Map.of("dontTouch", 600);
+		}
+	}
+
+	@Nested
+	class TestDelete {
+
+		@BeforeEach
+		void setup() {
+			mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
+			persistedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).build());
+			mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).build());
+		}
+
+		@Test
+		void shouldDeleteByVorgangId() {
+			repository.deleteByVorgangId(VorgangTestFactory.ID);
+
+			assertThat(mongoOperations.findAll(VorgangAttachedItem.class)).isEmpty();
+		}
+
+		@Test
+		void shouldDeleteByIdAndVersion() {
+			repository.delete(persistedItem.getId(), persistedItem.getVersion());
+
+			assertThat(repository.findById(persistedItem.getId())).isEmpty();
+		}
+
+		@Test
+		void shouldThrowExceptionWhenVersionMismatch() {
+			var expectedId = persistedItem.getId();
+			var expectedVersion = persistedItem.getVersion();
+			mongoOperations.save(persistedItem);
+
+			assertThrows(ConcurrentModificationException.class, () -> repository.delete(expectedId, expectedVersion));
+		}
+	}
+
+	@Nested
+	class TestMarkAsDeleted {
+
+		private static final boolean IS_DELETED = true;
+
+		@BeforeEach
+		void setup() {
+			mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
+			persistedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).build());
+			mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder().id(null).version(0).build());
+		}
+
+		@Test
+		void shouldMarkAsDeleted() {
+			repository.updateDeleted(IS_DELETED, persistedItem.getId(), persistedItem.getVersion());
+
+			var loaded = findVorgangAttachedItem();
+			assertThat(loaded.isDeleted()).isTrue();
+		}
+
+		@Test
+		void shouldThrowExceptionWhenVersionMismatch() {
+			var expectedId = persistedItem.getId();
+			var expectedVersion = persistedItem.getVersion();
+			mongoOperations.save(persistedItem);
+
+			assertThrows(ConcurrentModificationException.class, () -> repository.delete(expectedId, expectedVersion));
+		}
+	}
+
+	private VorgangAttachedItem findVorgangAttachedItem() {
+		return mongoOperations.findById(persistedItem.getId(), VorgangAttachedItem.class);
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8b6b7df25c55781b98c3d3560dddb1bd1ceb2b2
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceITCase.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.attached_item;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import jakarta.validation.ConstraintViolationException;
+
+@ITCase
+class VorgangAttachedItemServiceITCase {
+
+	@Autowired
+	private VorgangAttachedItemService service;
+
+	@MockBean
+	private VorgangAttachedItemRepository repository;
+	@MockBean
+	private ApplicationEventPublisher eventPublisher;
+
+	@Nested
+	class TestCreate {
+		@Test
+		void shouldDenyMissingClientName() {
+			var item = VorgangAttachedItemTestFactory.createBuilder().client(StringUtils.EMPTY).build();
+
+			assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item))
+					.isInstanceOf(ConstraintViolationException.class);
+		}
+
+		@Test
+		void shouldDenyMissingVorgangId() {
+			var item = VorgangAttachedItemTestFactory.createBuilder().vorgangId(StringUtils.EMPTY).build();
+
+			assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item))
+					.isInstanceOf(ConstraintViolationException.class);
+		}
+
+		@Test
+		void shouldDenyMissingItemName() {
+			var item = VorgangAttachedItemTestFactory.createBuilder().itemName(StringUtils.EMPTY).build();
+
+			assertThatThrownBy(() -> service.create(CommandTestFactory.ID, item))
+					.isInstanceOf(ConstraintViolationException.class);
+		}
+	}
+
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java
similarity index 55%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java
index 73c9773d0ded6f1ca98d974bfd96e6cca24374bf..126d872284154d990daa7e429e7d866ca4988fae 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
-import static de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemTestFactory.*;
+import static de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -38,17 +38,19 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 import org.springframework.context.ApplicationEventPublisher;
 
-import de.itvsh.ozg.mail.postfach.PostfachMailTestFactory;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class VorgangAttachedItemServiceTest {
 
 	@InjectMocks
+	@Spy
 	private VorgangAttachedItemService service;
 	@Mock
 	private VorgangAttachedItemRepository repository;
@@ -60,6 +62,8 @@ class VorgangAttachedItemServiceTest {
 
 		@Test
 		void shouldCallRepository() {
+			when(repository.save(any())).thenReturn(VorgangAttachedItemTestFactory.create());
+
 			service.create(CommandTestFactory.ID, VorgangAttachedItemTestFactory.create());
 
 			verify(repository).save(any());
@@ -67,6 +71,8 @@ class VorgangAttachedItemServiceTest {
 
 		@Test
 		void shouldPublishEvent() {
+			when(repository.save(any())).thenReturn(VorgangAttachedItemTestFactory.create());
+
 			service.create(CommandTestFactory.ID, VorgangAttachedItemTestFactory.create());
 
 			verify(publisher).publishEvent(any(VorgangAttachedItemCreatedEvent.class));
@@ -94,6 +100,13 @@ class VorgangAttachedItemServiceTest {
 
 				assertThat(prepared.getItem()).doesNotContainKey(VorgangAttachedItem.FIELDNAME_ID);
 			}
+
+			@Test
+			void shouldSetIsDeletedToFalse() {
+				var prepared = service.prepareForCreation(VorgangAttachedItemTestFactory.create());
+
+				assertThat(prepared.isDeleted()).isFalse();
+			}
 		}
 
 	}
@@ -116,46 +129,66 @@ class VorgangAttachedItemServiceTest {
 		}
 	}
 
+	@Nested
+	class TestForceUpdateItem {
+
+		@Test
+		void shouldCallRepository() {
+			service.forceUpdate(CommandTestFactory.ID, VorgangAttachedItemTestFactory.create());
+
+			verify(repository).forcePatch(eq(VorgangAttachedItemTestFactory.ID), any());
+		}
+
+		@Test
+		void shouldPublishEvent() {
+			service.forceUpdate(CommandTestFactory.ID, VorgangAttachedItemTestFactory.create());
+
+			verify(publisher).publishEvent(any(VorgangAttachedItemUpdatedEvent.class));
+		}
+	}
+
 	@Nested
 	class TestFindBy {
 
 		@Test
-		void shouldCallFindById() {
-			service.findById(PostfachMailTestFactory.ID);
+		void shouldCallFindByIdAndDeleted() {
+			service.findById(PostfachNachrichtTestFactory.ID);
 
-			verify(repository).findById(PostfachMailTestFactory.ID);
+			verify(repository).findByIdAndDeleted(PostfachNachrichtTestFactory.ID, VorgangAttachedItemService.NOT_DELETED);
 		}
 
 	}
 
 	@Nested
 	class TestFind {
+
 		@Test
-		void shouldCallFindByClientAndItemNameAndVorgangId() {
+		void shouldCallFindByClientAndItemNameAndVorgangIdAndDeleted() {
 			service.find(VorgangTestFactory.ID, Optional.of(CLIENT), Optional.of(ITEM_NAME));
 
-			verify(repository).findByVorgangIdAndClientAndItemName(VorgangTestFactory.ID, CLIENT, ITEM_NAME);
+			verify(repository).findByVorgangIdAndClientAndItemNameAndDeleted(VorgangTestFactory.ID, CLIENT, ITEM_NAME,
+					VorgangAttachedItemService.NOT_DELETED);
 		}
 
 		@Test
-		void shouldCallFindByClientAndVorgangId() {
+		void shouldCallFindByClientAndVorgangIdAndDeleted() {
 			service.find(VorgangTestFactory.ID, Optional.of(CLIENT), Optional.empty());
 
-			verify(repository).findByVorgangIdAndClient(VorgangTestFactory.ID, CLIENT);
+			verify(repository).findByVorgangIdAndClientAndDeleted(VorgangTestFactory.ID, CLIENT, VorgangAttachedItemService.NOT_DELETED);
 		}
 
 		@Test
-		void shouldCallFindByItemNameAndVorgangId() {
+		void shouldCallFindByItemNameAndVorgangIdAndDeleted() {
 			service.find(VorgangTestFactory.ID, Optional.empty(), Optional.of(ITEM_NAME));
 
-			verify(repository).findByVorgangIdAndItemName(VorgangTestFactory.ID, ITEM_NAME);
+			verify(repository).findByVorgangIdAndItemNameAndDeleted(VorgangTestFactory.ID, ITEM_NAME, VorgangAttachedItemService.NOT_DELETED);
 		}
 
 		@Test
-		void shouldCallFindByVorgangId() {
+		void shouldCallFindByVorgangIdAndDeleted() {
 			service.find(VorgangTestFactory.ID, Optional.empty(), Optional.empty());
 
-			verify(repository).findByVorgangId(VorgangTestFactory.ID);
+			verify(repository).findByVorgangIdAndDeleted(VorgangTestFactory.ID, VorgangAttachedItemService.NOT_DELETED);
 		}
 	}
 
@@ -175,8 +208,10 @@ class VorgangAttachedItemServiceTest {
 		}
 
 		private Command buildCommand(Map<String, Object> bodyMap) {
-			return CommandTestFactory.createBuilder().relationId(VorgangAttachedItemTestFactory.ID)
-					.relationVersion(VorgangAttachedItemTestFactory.VERSION).bodyObject(bodyMap).build();
+			return CommandTestFactory.createBuilder()
+					.relationId(VorgangAttachedItemTestFactory.ID)
+					.relationVersion(VorgangAttachedItemTestFactory.VERSION)
+					.bodyObject(bodyMap).build();
 		}
 	}
 
@@ -195,11 +230,12 @@ class VorgangAttachedItemServiceTest {
 	}
 
 	@Nested
+
 	class TestGetById {
 		@Test
 		void shouldReturnAttachedItem() {
 			var item = VorgangAttachedItemTestFactory.create();
-			when(repository.findById(any())).thenReturn(Optional.of(item));
+			when(repository.findByIdAndDeleted(any(), anyBoolean())).thenReturn(Optional.of(item));
 
 			var attachedItem = service.getById(VorgangAttachedItemTestFactory.ID);
 
@@ -209,10 +245,20 @@ class VorgangAttachedItemServiceTest {
 		@DisplayName("should throw an exception if no attachedItem was found")
 		@Test
 		void shouldThrowException() {
-			when(repository.findById(any())).thenReturn(Optional.empty());
+			when(repository.findByIdAndDeleted(any(), anyBoolean())).thenReturn(Optional.empty());
 
 			assertThrows(NotFoundException.class, () -> service.getById(VorgangAttachedItemTestFactory.ID));
 		}
+
+		@Test
+		void shouldCallFindByIdAndDeleted() {
+			var item = VorgangAttachedItemTestFactory.create();
+			when(repository.findByIdAndDeleted(any(), anyBoolean())).thenReturn(Optional.of(item));
+
+			service.getById(VorgangAttachedItemTestFactory.ID);
+
+			verify(repository).findByIdAndDeleted(VorgangAttachedItemTestFactory.ID, VorgangAttachedItemService.NOT_DELETED);
+		}
 	}
 
 	@Test
@@ -223,4 +269,42 @@ class VorgangAttachedItemServiceTest {
 
 		assertThat(enrichedItem.getItem()).containsEntry(VorgangAttachedItem.FIELDNAME_ID, id);
 	}
+
+	@Nested
+	@DisplayName("Set deleted by ID and version")
+	class TestMarkDeletedByIdAndVersion {
+
+		@Test
+		@DisplayName("should call updateDeletedByIdAndVersion to mark item as deleted")
+		void shouldCallUpdateIsDeletedMethod() {
+			var deletedFlag = true;
+
+			service.markAsDeleteByIdAndVersion(VorgangAttachedItemTestFactory.ID, VorgangAttachedItemTestFactory.VERSION);
+
+			verify(repository).updateDeleted(deletedFlag, VorgangAttachedItemTestFactory.ID, VorgangAttachedItemTestFactory.VERSION);
+		}
+
+		@Test
+		@DisplayName("should call updateDeletedByIdAndVersion to mark item as not deleted")
+		void shouldCallUpdateIsDeletedMethod1() {
+			var deletedFlag = false;
+
+			service.unmarkAsDeleteByIdAndVersion(VorgangAttachedItemTestFactory.ID, VorgangAttachedItemTestFactory.VERSION);
+
+			verify(repository).updateDeleted(deletedFlag, VorgangAttachedItemTestFactory.ID, VorgangAttachedItemTestFactory.VERSION);
+		}
+	}
+
+	@Nested
+	@DisplayName("Delete item by vorgangId")
+	class TestDelete {
+
+		@Test
+		void shouldCallDeleteMethod() {
+			service.deleteByVorgangId(VorgangAttachedItemTestFactory.ID);
+
+			verify(repository).deleteByVorgangId(VorgangAttachedItemTestFactory.ID);
+		}
+
+	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemTestFactory.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemTestFactory.java
index be7f4a5ff6f2372c818f079dfc9678d5bca3a6fd..ead2acb3b43700063ae725b56b65e02707cf538d 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/attached_item/VorgangAttachedItemTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/attached_item/VorgangAttachedItemTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,21 +21,25 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.attached_item;
+package de.ozgcloud.vorgang.attached_item;
 
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
-import de.itvsh.kop.common.binaryfile.FileId;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.common.binaryfile.FileId;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class VorgangAttachedItemTestFactory {
 
+	public static final boolean DELETED = true;
+
 	public static final String ID = UUID.randomUUID().toString();
 	public static final long VERSION = 1L;
 
-	public static final String CLIENT = "Goofy";
+	public static final String CLIENT = LoremIpsum.getInstance().getFirstName() + "Client";
 	public static final String ITEM_NAME = "test";
 
 	public static final String ITEM_FIELD_NAME = "number";
@@ -67,6 +71,7 @@ public class VorgangAttachedItemTestFactory {
 				.version(VERSION)
 				.client(CLIENT)
 				.itemName(ITEM_NAME)
+				.deleted(false)
 				.item(STRING_MAP);
 	}
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeHasValueValidatorTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeHasValueValidatorTest.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeHasValueValidatorTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeHasValueValidatorTest.java
index 9fb1e9b85b483e878d1a010c9f5e56a8e3233d68..8e14b3faca68e2444ceb9887b1f5e1e69f65c85f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeHasValueValidatorTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeHasValueValidatorTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,21 +21,21 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
-import static de.itvsh.ozg.pluto.clientattribute.ClientAttributeTestFactory.*;
+import static de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 
 import java.util.Optional;
 
-import javax.validation.ConstraintValidatorContext;
-
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
+import jakarta.validation.ConstraintValidatorContext;
+
 class ClientAttributeHasValueValidatorTest {
 
 	@InjectMocks
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeITCase.java
similarity index 86%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeITCase.java
index e99a518b0af3f6de6fbdfecdebdbbfd3ed217dca..3daae6387fde92af1ac30a6acb9669f9d9181e2a 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -34,14 +34,14 @@ import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.test.annotation.DirtiesContext;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.common.callcontext.TestCallContextAttachingInterceptor;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
-import de.itvsh.ozg.pluto.vorgang.GrpcFindVorgangRequestTestFactory;
-import de.itvsh.ozg.pluto.vorgang.GrpcFindVorgangWithEingangRequest;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.callcontext.TestCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequestTestFactory;
+import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangRequest;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
 @SpringBootTest(properties = {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeIdentificatorTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeIdentificatorTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeIdentificatorTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeIdentificatorTestFactory.java
index 0486379438a77239a59d6c2a7bb38f5220580e1b..78b0095a4360b356e43c32281afc9922080087f2 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeIdentificatorTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeIdentificatorTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class ClientAttributeIdentificatorTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMapperTest.java
similarity index 94%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMapperTest.java
index 1982cf833c001b414f39375f5c7b1c45dff5c539..615daf879dedbc10fd6fa1ba2ed05a3176657533 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
-import static de.itvsh.ozg.pluto.clientattribute.ClientAttributeTestFactory.*;
+import static de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 
 import java.util.Optional;
@@ -34,9 +34,9 @@ import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttributeValue;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttributeValue;
 
 class ClientAttributeMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeReadPermittedTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeReadPermittedTest.java
similarity index 90%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeReadPermittedTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeReadPermittedTest.java
index 24c2a82ddcc6574b12b3d883b289f8772f25d876..84280fce7787ec38684044a13d9c2996669b5222 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeReadPermittedTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeReadPermittedTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
@@ -35,9 +35,9 @@ import org.junit.jupiter.params.provider.EnumSource.Mode;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttribute.AccessPermission;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute.AccessPermission;
 
 class ClientAttributeReadPermittedTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeRepositoryITCase.java
similarity index 90%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeRepositoryITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeRepositoryITCase.java
index 6dfb9bcc6958dc740eb488f4f35438d349c95015..463bd31a8b62f034edfe02507ad4d7c3087309ec 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeRepositoryITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
-import static de.itvsh.ozg.pluto.clientattribute.ClientAttributeTestFactory.*;
+import static de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 
 import java.util.Map;
@@ -40,12 +40,12 @@ import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.security.access.AccessDeniedException;
 import org.springframework.security.test.context.support.WithMockUser;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttribute.AccessPermission;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute.AccessPermission;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 @DataITCase
 class ClientAttributeRepositoryITCase {
@@ -75,9 +75,9 @@ class ClientAttributeRepositoryITCase {
 		void withIntValue() {
 			repository.set(vorgang.getId(), ClientAttributeTestFactory.create());
 
-			Map<String, ClientAttribute> goofyAttributes = loadTestClientAttributes();
+			Map<String, ClientAttribute> attributes = loadTestClientAttributes();
 
-			assertThat(goofyAttributes.get(ATTRIBUTE_NAME))
+			assertThat(attributes.get(ATTRIBUTE_NAME))
 					.usingRecursiveComparison().ignoringFields(ClientAttribute.FIELD_CLIENTNAME, ClientAttribute.FIELD_ATTRIBUTENAME)
 					.isEqualTo(ClientAttributeTestFactory.create());
 		}
@@ -89,8 +89,8 @@ class ClientAttributeRepositoryITCase {
 
 			repository.set(vorgang.getId(), attribute);
 
-			Map<String, ClientAttribute> goofyAttributes = loadTestClientAttributes();
-			assertThat(goofyAttributes.get(ATTRIBUTE_NAME))
+			Map<String, ClientAttribute> attributes = loadTestClientAttributes();
+			assertThat(attributes.get(ATTRIBUTE_NAME))
 					.usingRecursiveComparison().ignoringFields(ClientAttribute.FIELD_CLIENTNAME, ClientAttribute.FIELD_ATTRIBUTENAME)
 					.isEqualTo(attribute);
 		}
@@ -102,8 +102,8 @@ class ClientAttributeRepositoryITCase {
 
 			repository.set(vorgang.getId(), attribute);
 
-			Map<String, ClientAttribute> goofyAttributes = loadTestClientAttributes();
-			assertThat(goofyAttributes.get(ATTRIBUTE_NAME))
+			Map<String, ClientAttribute> attributes = loadTestClientAttributes();
+			assertThat(attributes.get(ATTRIBUTE_NAME))
 					.usingRecursiveComparison().ignoringFields(ClientAttribute.FIELD_CLIENTNAME, ClientAttribute.FIELD_ATTRIBUTENAME)
 					.isEqualTo(attribute);
 		}
@@ -115,8 +115,8 @@ class ClientAttributeRepositoryITCase {
 
 			repository.set(vorgang.getId(), attribute);
 
-			Map<String, ClientAttribute> goofyAttributes = loadTestClientAttributes();
-			assertThat(goofyAttributes.get(ATTRIBUTE_NAME))
+			Map<String, ClientAttribute> attributes = loadTestClientAttributes();
+			assertThat(attributes.get(ATTRIBUTE_NAME))
 					.usingRecursiveComparison().ignoringFields(ClientAttribute.FIELD_CLIENTNAME, ClientAttribute.FIELD_ATTRIBUTENAME)
 					.isEqualTo(attribute);
 		}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeServiceITCase.java
similarity index 89%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeServiceITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeServiceITCase.java
index ed315ad69a9af10c5904d8d165b67e3be823f42c..f3650bd1b10518363f7f22ca1314d4f0e612cc3f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeServiceITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,21 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import static org.assertj.core.api.Assertions.*;
 
 import java.util.Optional;
 
-import javax.validation.ConstraintViolationException;
-
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.mock.mockito.MockBean;
 
-import de.itvsh.kop.common.test.ITCase;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import jakarta.validation.ConstraintViolationException;
 
 @ITCase
 class ClientAttributeServiceITCase {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeServiceTest.java
similarity index 94%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeServiceTest.java
index a0b581004966dcd0a6d288c578d108fafde05fa8..8c1aa5c64e30ffd374b8a8e9d71814297cb62d19 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -33,7 +33,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class ClientAttributeServiceTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeTestFactory.java
index bfc237f02863ff0219d70f5bf46420e0cde855ad..d3075e99bd82829f3efadbaf3b140a5a50fa4c99 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributeTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributeTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import java.util.Optional;
 
 import com.thedeanda.lorem.LoremIpsum;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttribute.AccessPermission;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute.AccessPermission;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class ClientAttributeTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributesMapTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributesMapTestFactory.java
similarity index 89%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributesMapTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributesMapTestFactory.java
index fe99faa91943074579aede907cc146a931d3ad5b..4711148538105414ef22ee08e43a786513490488 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/ClientAttributesMapTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/ClientAttributesMapTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 public class ClientAttributesMapTestFactory {
 
 	public static final ClientAttributesMap create() {
-		return createWithAttribute(ClientAttributeTestFactory.createBuilder().build());
+		return createWithAttribute(ClientAttributeTestFactory.create());
 	}
 
 	public static final ClientAttributesMap createWithAttribute(ClientAttribute clientAttribute) {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeServiceITCase.java
similarity index 88%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeServiceITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeServiceITCase.java
index 9942dfaa7df207bf20a765503fae9a08cb9c7a6f..d24c63cdff057eea295f75ba73aaa6e46e7feec8 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeServiceITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,8 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
+import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
@@ -37,14 +38,11 @@ import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.ActiveProfiles;
 
-import static org.assertj.core.api.Assertions.*;
-
-import de.itvsh.ozg.pluto.common.callcontext.TestCallContextAttachingInterceptor;
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
+import de.ozgcloud.vorgang.callcontext.TestCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub;
 import net.devh.boot.grpc.client.inject.GrpcClient;
 
-@Disabled
 @SpringBootTest(properties = {
 		"grpc.server.inProcessName=test",
 		"grpc.server.port=-1",
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeServiceTest.java
similarity index 89%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeServiceTest.java
index 53804a845af85be532584acd28d5d96573b849cc..da4865fdfa01bba6bf2c6e40a173c0d307bd2183 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -38,14 +38,14 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAcknowledgeResponse;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcDeleteClientAttributeRequest;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcSetClientAttributeRequest;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcUpdateClientAttributeRequest;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcAcknowledgeResponse;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcDeleteClientAttributeRequest;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcSetClientAttributeRequest;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcUpdateClientAttributeRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.stub.StreamObserver;
 
 class GrpcClientAttributeServiceTest {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeTestFactory.java
similarity index 76%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeTestFactory.java
index 10e098b8d642984c50bac71cd62d8c5705a02222..845fb08b0398afe9b310460ef103bf2a788485e3 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcClientAttributeTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcClientAttributeTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
-import static de.itvsh.ozg.pluto.clientattribute.ClientAttributeTestFactory.*;
+import static de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory.*;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttributeValue;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcAccessPermission;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttribute;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttributeValue;
 
 public class GrpcClientAttributeTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcDeleteClientAttributeRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcDeleteClientAttributeRequestTestFactory.java
similarity index 81%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcDeleteClientAttributeRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcDeleteClientAttributeRequestTestFactory.java
index 422defb5b74920e884bbc6f0b84ac698578be6bb..b1ebcd9f0e64b25f6766518421baf0a05836c9c4 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcDeleteClientAttributeRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcDeleteClientAttributeRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcDeleteClientAttributeRequest;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcDeleteClientAttributeRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class GrpcDeleteClientAttributeRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcSetClientAttributeRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcSetClientAttributeRequestTestFactory.java
similarity index 76%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcSetClientAttributeRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcSetClientAttributeRequestTestFactory.java
index 6538937ffd18802a30f09cd1de4844067c71d7f0..356699cf01ce882ada48c4c7dc63a2b9fc99df8c 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcSetClientAttributeRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcSetClientAttributeRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
-import static de.itvsh.ozg.pluto.clientattribute.ClientAttributeTestFactory.*;
+import static de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory.*;
 
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttributeValue;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcSetClientAttributeRequest;
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcSetClientAttributeRequest.Builder;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcClientAttributeValue;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcSetClientAttributeRequest;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcSetClientAttributeRequest.Builder;
 
 public class GrpcSetClientAttributeRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcUpdateClientAttributeRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcUpdateClientAttributeRequestTestFactory.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcUpdateClientAttributeRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcUpdateClientAttributeRequestTestFactory.java
index e7d455e6b9b3270add120eaeef154a47ff8bf17d..b89efc31656d81184619d93d67bea1c4bb4931f4 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/clientattribute/GrpcUpdateClientAttributeRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/clientattribute/GrpcUpdateClientAttributeRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.clientattribute;
+package de.ozgcloud.vorgang.clientattribute;
 
-import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcUpdateClientAttributeRequest;
+import de.ozgcloud.vorgang.grpc.clientAttribute.GrpcUpdateClientAttributeRequest;
 
 public class GrpcUpdateClientAttributeRequestTestFactory {
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/AttachmentFileTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/AttachmentFileTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..37d5e6aaea61c3be1e9458e6890886be15952e30
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/AttachmentFileTestFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.function.Supplier;
+
+import org.apache.commons.io.IOUtils;
+
+import de.ozgcloud.nachrichten.postfach.AttachmentFile;
+import de.ozgcloud.nachrichten.postfach.AttachmentFile.AttachmentFileBuilder;
+
+public class AttachmentFileTestFactory {
+
+	public static final String ATTACHMENT_NAME = "test.txt";
+	public static final String CONTENT_TYPE = "text/plain";
+
+	public static final String BASE64_CONTENT = "dGVzdA==";
+	public static final String CONTENT = "test";
+	public static final long SIZE = 4L;
+	public static final Supplier<InputStream> CONTENT_SUPPLIER = () -> IOUtils.toInputStream(CONTENT, Charset.defaultCharset());
+	public static final Supplier<InputStream> BASE64_CONTENT_SUPPLIER = () -> IOUtils.toInputStream(BASE64_CONTENT, Charset.defaultCharset());
+
+	public static AttachmentFile create() {
+		return createBuilder().build();
+	}
+
+	public static AttachmentFileBuilder createBuilder() {
+		return AttachmentFile.builder()
+				.name(ATTACHMENT_NAME)
+				.contentType(CONTENT_TYPE)
+				.content(CONTENT_SUPPLIER);
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandCreatedEventTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandCreatedEventTestFactory.java
similarity index 78%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandCreatedEventTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandCreatedEventTestFactory.java
index ab11c354091c27f6cf1987cfb9a8e7e94782362e..6daf777691cea37053e5be6cb88b67cdc298522c 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandCreatedEventTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandCreatedEventTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
 
 public class CommandCreatedEventTestFactory {
 
+	public static CommandCreatedEvent create() {
+		return create(CommandTestFactory.create());
+	}
+
 	public static CommandCreatedEvent create(Command command) {
 		return new CommandCreatedEvent(command);
 	}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandDeletionSchedulerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandDeletionSchedulerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b39dcb35bce2961f071036367441095d1edb54e4
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandDeletionSchedulerTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.time.ZonedDateTime;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+class CommandDeletionSchedulerTest {
+
+	@InjectMocks
+	@Spy
+	private CommandDeletionScheduler scheduler;
+	@Mock
+	private CommandService commandService;
+
+	private ZonedDateTime cleanupThreshold = ZonedDateTime.now().minusMinutes(CommandDeletionScheduler.CLEANUP_THRESHOLD_MINUTES);
+
+	@Test
+	void shouldCallGetCleanupThreshold() {
+		scheduler.deleteCommands();
+
+		verify(scheduler).getCleanupThreshold();
+	}
+
+	@Test
+	void shouldFindFinishedCommands() {
+		doReturn(cleanupThreshold).when(scheduler).getCleanupThreshold();
+
+		scheduler.deleteCommands();
+
+		verify(commandService).findFinishedVorgangLoeschenCommandsOlderThen(cleanupThreshold);
+	}
+
+	@Test
+	void shouldCallCommandService() {
+		Stream<Command> commands = Stream.of(CommandTestFactory.create(), CommandTestFactory.create());
+		when(commandService.findFinishedVorgangLoeschenCommandsOlderThen(any())).thenReturn(commands);
+
+		scheduler.deleteCommands();
+
+		verify(commandService).deleteAllByVorgang(VorgangTestFactory.ID);
+	}
+
+	@Test
+	void shouldCatchExceptionWhenFindMethodCalled() {
+		doThrow(new RuntimeException()).when(commandService).findFinishedVorgangLoeschenCommandsOlderThen(any());
+
+		scheduler.deleteCommands();
+
+		verify(commandService, never()).deleteAllByVorgang(any());
+	}
+
+	@Test
+	void shouldCatchExceptionWhenDeleteMethodCalled() {
+		when(commandService.findFinishedVorgangLoeschenCommandsOlderThen(any())).thenReturn(Stream.of(CommandTestFactory.create()));
+		doThrow(new RuntimeException()).when(commandService).deleteAllByVorgang(any());
+
+		assertThatNoException().isThrownBy(scheduler::deleteCommands);
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandEventListenerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..23d1885a2b1ba8615ab1501f57dbbae684cf9c0d
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandEventListenerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandRevokeFailedEvent;
+import de.ozgcloud.command.CommandRevokedEvent;
+
+class CommandEventListenerTest {
+
+	@InjectMocks // NOSONAR
+	private CommandEventListener listener;
+
+	@Mock
+	private CommandService commandService;
+
+	@Nested
+	class TestCommandExecutedEventListener {
+
+		@Test
+		void shouldSetStatusFinished() {
+			listener.setStatusFinished(
+					CommandExecutedEventTestFactory.createFor(CommandTestFactory.create(), CommandTestFactory.CREATED_RESOURCE));
+
+			verify(commandService).setCommandFinished(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
+		}
+
+	}
+
+	@Nested
+	class TestCommandRevokeFailedEventListener {
+
+		@Test
+		void shouldSetStatusFinished() {
+			listener.setStatusFinished(new CommandRevokeFailedEvent(CommandTestFactory.ID, "test Error"));
+
+			verify(commandService).setCommandFinished(CommandTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestCommandFailedEventListener {
+		private static final String ERROR_MESSAGE = "test Error";
+
+		@Test
+		void shouldSetStatusError() {
+			listener.setStatusError(new CommandFailedEvent(CommandTestFactory.ID, ERROR_MESSAGE));
+
+			verify(commandService).setCommandError(CommandTestFactory.ID, ERROR_MESSAGE);
+		}
+	}
+
+	@Nested
+	class TestCommandRevokedEventListener {
+		@Test
+		void shouldSetStatusRevoked() {
+			listener.setCommandRevoked(new CommandRevokedEvent(CommandTestFactory.create()));
+
+			verify(commandService).setCommandRevoked(CommandTestFactory.ID);
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandExecutedEventTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandExecutedEventTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..de5a85f2ff5418477a26d0b2e2b362676acc4748
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandExecutedEventTestFactory.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
+
+public class CommandExecutedEventTestFactory {
+
+	public static CommandExecutedEvent createFor(Command command, String createdResource) {
+		return new CommandExecutedEvent(command, createdResource);
+	}
+
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandITCase.java
similarity index 67%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandITCase.java
index f4e694ca1ec40cc9657a0028f0c2aeb335939836..e55a4e0d9357b4c42b315f2027bdfbdff2a299cf 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.*;
+import static org.awaitility.Awaitility.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.assertj.core.api.InstanceOfAssertFactories;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -37,23 +42,22 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.security.test.context.support.WithMockUser;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemTestFactory;
-import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandBodyField;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse.GrpcResponseCode;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
-import de.itvsh.ozg.pluto.grpc.command.GrpcRevokeCommandRequest;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommand;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandBodyField;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetPendingCommandsRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetPendingCommandsResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.grpc.command.GrpcRevokeCommandRequest;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.stub.StreamObserver;
 
 /**
@@ -67,7 +71,6 @@ import io.grpc.stub.StreamObserver;
  * einige wenige Testfälle in eine E2E-ITCase (CommandITCase) ziehen, dabei aber
  * reaktionen von Umsystemen (NAchrichtenMAnager, NotificationManager)
  * berúcksichtigen / ausschalten
- *
  */
 
 @WithMockUser
@@ -114,44 +117,56 @@ class CommandITCase {
 
 			var response = responseCaptor.getValue();
 
-			assertThat(response.getResponseCode()).isEqualTo(GrpcResponseCode.OK);
+			assertThat(response.getResponseCode()).isEqualTo(GrpcCommandResponse.GrpcResponseCode.OK);
 			assertThat(response.getCommand()).isNotNull();
+		}
 
-			var command = response.getCommand();
+		@Test
+		void shouldCreateCommand() {
+			callServiceCreateCommand();
+			var response = responseCaptor.getValue();
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var command = commandService.findCommand(response.getCommand().getId());
+
+				assertThat(command).isPresent().get().satisfies(cmd -> {
+					assertThat(cmd.getId()).isNotNull();
+					assertThat(cmd.getCreatedAt()).isNotNull();
+					assertThat(cmd.getStatus()).isEqualTo(CommandStatus.FINISHED);
+					assertThat(cmd.getRelationId()).isEqualTo(persistedVorgang.getId());
+				});
+			});
 
-			assertThat(command.getId()).isNotNull();
-			assertThat(command.getCreatedAt()).isNotNull();
-			// assertThat(command.getCreatedBy()).isEqualTo(UserTestFactory.ID);
-			assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED.name());
-			assertThat(command.getRelationId()).isEqualTo(persistedVorgang.getId());
-			assertThat(command.getOrder()).isEqualTo(GrpcOrder.VORGANG_ANNEHMEN);
 		}
 
 		@Test
 		void validateUpdatedVorgang() {
 			callServiceCreateCommand();
 
-			var vorgang = mongoOperations.findById(persistedVorgang.getId(), Vorgang.class);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var vorgang = mongoOperations.findById(persistedVorgang.getId(), Vorgang.class);
+
+				assertThat(vorgang).isNotNull();
+				assertThat(vorgang.getVersion()).isEqualTo(VorgangTestFactory.VERSION + 1);
+			});
 
-			assertThat(vorgang).isNotNull();
-			assertThat(vorgang.getVersion()).isEqualTo(VorgangTestFactory.VERSION + 1);
 		}
 
 		@Test
 		void validateCreatedCommand() {
 			callServiceCreateCommand();
 
-			var commands = mongoOperations.findAll(Command.class);
-
-			assertThat(commands).hasSize(1);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var commands = mongoOperations.findAll(Command.class);
 
-			var command = commands.get(0);
-			assertThat(command.getId()).hasSize(36);
-			assertThat(command.getCreatedAt()).isNotNull();
-			// assertThat(command.getCreatedBy()).isNotNull();
-			assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED);
-			assertThat(command.getRelationId()).isEqualTo(persistedVorgang.getId());
-			assertThat(command.getRelationVersion()).isEqualTo(VorgangTestFactory.VERSION);
+				assertThat(commands).hasSize(1).first().satisfies(command -> {
+					assertThat(command.getId()).hasSize(36);
+					assertThat(command.getCreatedAt()).isNotNull();
+					assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED);
+					assertThat(command.getRelationId()).isEqualTo(persistedVorgang.getId());
+					assertThat(command.getRelationVersion()).isEqualTo(VorgangTestFactory.VERSION);
+				});
+			});
 		}
 
 		@DisplayName("with Order SEND_POSTFACH_MAIL")
@@ -295,31 +310,39 @@ class CommandITCase {
 				mongoOperations.save(VorgangTestFactory.createBuilder().status(Status.ANGENOMMEN).build());
 
 				mongoOperations.save(CommandTestFactory.createBuilder()
-						.relationId(VorgangTestFactory.ID).relationVersion(VorgangTestFactory.VERSION - 1).build());
+						.relationId(VorgangTestFactory.ID).relationVersion(VorgangTestFactory.VERSION - 1)
+						.previousState(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Status.NEU)).build());
 			}
 
 			@Test
 			void shouldSetRevokeStatus() {
 				callServiceRevokeCommand();
 
-				var response = responseCaptor.getValue();
-				assertThat(response.getCommand().getStatus()).isEqualTo(CommandStatus.REVOKED.toString());
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+					var command = findCommand(responseCaptor.getValue().getCommand().getId());
+
+					assertThat(command).isNotNull().extracting(Command::getStatus).isEqualTo(CommandStatus.REVOKED);
+				});
 			}
 
 			@Test
 			void shouldUpdateVorgang() {
 				callServiceRevokeCommand();
 
-				var vorgang = mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
-				assertThat(vorgang).isNotNull().extracting(Vorgang::getStatus).isEqualTo(Status.NEU);
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+					var vorgang = mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
+					assertThat(vorgang).isNotNull().extracting(Vorgang::getStatus).isEqualTo(Status.NEU);
+				});
 			}
 
 			@Test
 			void shouldUpdateCommand() {
 				callServiceRevokeCommand();
 
-				var command = findCommand();
-				assertThat(command).isNotNull().extracting(Command::getStatus).isEqualTo(CommandStatus.REVOKED);
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+					var command = findCommand();
+					assertThat(command).isNotNull().extracting(Command::getStatus).isEqualTo(CommandStatus.REVOKED);
+				});
 			}
 
 			@Test
@@ -331,7 +354,11 @@ class CommandITCase {
 			}
 
 			private Command findCommand() {
-				return mongoOperations.findById(CommandTestFactory.ID, Command.class);
+				return findCommand(CommandTestFactory.ID);
+			}
+
+			private Command findCommand(String id) {
+				return mongoOperations.findById(id, Command.class);
 			}
 		}
 
@@ -343,15 +370,20 @@ class CommandITCase {
 				mongoOperations.save(VorgangTestFactory.createBuilder().status(Status.VERWORFEN).build());
 
 				mongoOperations.save(CommandTestFactory.createBuilder().relationId(VorgangTestFactory.ID)
-						.relationVersion(VorgangTestFactory.VERSION - 1).order(Order.VORGANG_VERWERFEN.toString()).build());
+						.relationVersion(VorgangTestFactory.VERSION - 1).order(Order.VORGANG_VERWERFEN.toString())
+						.previousState(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Status.IN_BEARBEITUNG))
+						.build());
 			}
 
 			@Test
 			void shouldSetRevokeStatus() {
 				callServiceRevokeCommand();
 
-				var response = responseCaptor.getValue();
-				assertThat(response.getCommand().getStatus()).isEqualTo(CommandStatus.REVOKED.toString());
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+					var command = commandService.findCommand(responseCaptor.getValue().getCommand().getId());
+
+					assertThat(command).isPresent().get().extracting(Command::getStatus).isEqualTo(CommandStatus.REVOKED);
+				});
 			}
 
 			@Test
@@ -359,15 +391,17 @@ class CommandITCase {
 				callServiceRevokeCommand();
 
 				var vorgang = mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
-				assertThat(vorgang).isNotNull().extracting(Vorgang::getStatus).isEqualTo(Status.NEU);
+				assertThat(vorgang).isNotNull().extracting(Vorgang::getStatus).isEqualTo(Status.IN_BEARBEITUNG);
 			}
 
 			@Test
 			void shouldUpdateCommand() {
 				callServiceRevokeCommand();
 
-				var command = mongoOperations.findById(CommandTestFactory.ID, Command.class);
-				assertThat(command).isNotNull().extracting(Command::getStatus).isEqualTo(CommandStatus.REVOKED);
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+					var command = mongoOperations.findById(CommandTestFactory.ID, Command.class);
+					assertThat(command).isNotNull().extracting(Command::getStatus).isEqualTo(CommandStatus.REVOKED);
+				});
 			}
 		}
 
@@ -385,6 +419,11 @@ class CommandITCase {
 			assertThat(command.getStatus()).isEqualTo(CommandStatus.REVOKED);
 			assertThat(command.getRelationId()).isEqualTo(VorgangTestFactory.ID);
 			assertThat(command.getRelationVersion()).isEqualTo(VorgangTestFactory.VERSION);
+
+			assertThat(command).isInstanceOf(PersistedCommand.class)
+					.extracting("previousState")
+					.asInstanceOf(InstanceOfAssertFactories.map(String.class, Object.class))
+					.containsKey(Vorgang.MONGODB_FIELDNAME_STATUS).isEqualTo(Status.NEU);
 		}
 
 		private void callServiceRevokeCommand() {
@@ -394,44 +433,4 @@ class CommandITCase {
 		}
 	}
 
-	@Nested
-	class TestCreateAttachedItem {
-
-		private CreateCommandRequest request;
-
-		@BeforeEach
-		void prepareDatabase() {
-			mongoOperations.dropCollection(Vorgang.COLLECTION_NAME);
-			mongoOperations.dropCollection(Command.COLLECTION_NAME);
-			mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
-
-			var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).build());
-
-			request = CreateCommandRequestTestFactory.createBuilder()
-					.vorgangId(vorgang.getId()).relationId(vorgang.getId())
-					.order(Order.CREATE_ATTACHED_ITEM.toString()).bodyObject(VorgangAttachedItemTestFactory.asMap()).build();
-		}
-
-		@Test
-		void shouldPersistCommand() {
-			// TODO use grpc-service
-			commandService.createCommand(request);
-
-			var commands = mongoOperations.findAll(Command.class);
-			assertThat(commands).hasSize(1);
-			assertThat(commands.get(0).getBodyObject()).isNotNull();
-			assertThat(commands.get(0).getBodyObject()).containsEntry("itemName",
-					VorgangAttachedItemTestFactory.ITEM_NAME);
-		}
-
-		@Test
-		void shouldExecuteCommand() {
-			// TODO use grpc-service
-			commandService.createCommand(request);
-
-			var commands = mongoOperations.findAll(Command.class);
-			assertThat(commands).hasSize(1);
-			assertThat(commands.get(0).getStatus()).isEqualTo(CommandStatus.FINISHED);
-		}
-	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..99293b0d512d818fee63f2e33e6548163cda893b
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRepositoryITCase.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.springframework.data.mongodb.core.query.Query.*;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+
+import org.assertj.core.api.InstanceOfAssertFactories;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+@DataITCase
+class CommandRepositoryITCase {
+
+	@Autowired
+	private CommandRepository repository;
+	@Autowired
+	private MongoOperations mongoOperations;
+
+	@BeforeEach
+	void clearDB() {
+		mongoOperations.dropCollection(Command.class);
+	}
+
+	@Nested
+	class TestSave {
+
+		@Test
+		void shouldSave() {
+			repository.save(CommandTestFactory.create());
+
+			verifyCommandExists(CommandTestFactory.ID);
+		}
+
+		@Test
+		void shouldGenerateIdOnSave() {
+			Command command = repository.save(CommandTestFactory.createBuilder().id(null).build());
+
+			verifyCommandExists(command.getId());
+		}
+
+		private void verifyCommandExists(String id) {
+			Command command = mongoOperations.findById(id, Command.class);
+
+			assertThat(command).isNotNull();
+			assertThat(command.getId()).isEqualTo(id);
+		}
+	}
+
+	@Nested
+	class TestFinishCommand {
+
+		@Test
+		void shouldUpdateStatusToFinished() {
+			var command = mongoOperations.save(CommandTestFactory.create());
+
+			repository.finishCommand(command.getId());
+
+			var result = repository.getById(command.getId()).get();
+			assertThat(result.getStatus()).isEqualTo(CommandStatus.FINISHED);
+		}
+
+		@Test
+		void shouldSetFinishedAt() {
+			var command = mongoOperations.save(CommandTestFactory.createBuilder().createdAt(null).build());
+
+			repository.finishCommand(command.getId());
+
+			var result = repository.getById(command.getId()).get();
+			assertThat(result.getFinishedAt()).isNotNull();
+		}
+
+		@Test
+		void shouldUpdateStatusToFinishedWithCreatedResource() {
+			var command = mongoOperations.save(CommandTestFactory.create());
+
+			repository.finishCommand(command.getId(), CommandTestFactory.CREATED_RESOURCE);
+
+			var result = repository.getById(command.getId()).get();
+			assertThat(result.getStatus()).isEqualTo(CommandStatus.FINISHED);
+		}
+
+		@Test
+		void shouldSetFinishedAtWithCreatedResource() {
+			var command = mongoOperations.save(CommandTestFactory.createBuilder().createdAt(null).build());
+
+			repository.finishCommand(command.getId(), CommandTestFactory.CREATED_RESOURCE);
+
+			var result = repository.getById(command.getId()).get();
+			assertThat(result.getFinishedAt()).isNotNull();
+		}
+
+		@Test
+		void shouldSetCreatedResource() {
+			var command = CommandTestFactory.createBuilder().id(null).build();
+			var savedCommand = repository.save(command);
+			assertThat(savedCommand.getCreatedResource()).isNull();
+
+			repository.finishCommand(savedCommand.getId(), CommandTestFactory.CREATED_RESOURCE);
+
+			var result = repository.getById(savedCommand.getId()).get();
+			assertThat(result.getCreatedResource()).isEqualTo(CommandTestFactory.CREATED_RESOURCE);
+		}
+
+		@Test
+		void shouldNotOverrideCreatedResource() {
+			var command = CommandTestFactory.createBuilder().id(null).createdResource(CommandTestFactory.CREATED_RESOURCE).build();
+			var savedCommand = repository.save(command);
+
+			repository.finishCommand(savedCommand.getId(), CommandTestFactory.CREATED_RESOURCE);
+
+			var result = repository.getById(savedCommand.getId()).get();
+			assertThat(result.getCreatedResource()).isEqualTo(CommandTestFactory.CREATED_RESOURCE);
+		}
+	}
+
+	@Nested
+	class TestGetById {
+
+		private final String ADDITIONAL_COMMAND_ID = UUID.randomUUID().toString();
+
+		@BeforeEach
+		void persistAdditionalCommandToVorgang() {
+			mongoOperations.save(CommandTestFactory.create());
+		}
+
+		@Test
+		void shouldFindCommand() {
+			verifyCommandExists(CommandTestFactory.ID);
+		}
+
+		@Test
+		void shouldFindAdditionalCommand() {
+			mongoOperations.save(CommandTestFactory.createBuilder().id(ADDITIONAL_COMMAND_ID).build());
+
+			verifyCommandExists(ADDITIONAL_COMMAND_ID);
+		}
+
+		private void verifyCommandExists(String id) {
+			Optional<Command> command = repository.getById(id);
+
+			assertThat(command).isPresent();
+			assertThat(command.get().getId()).isEqualTo(id);
+		}
+	}
+
+	@Nested
+	class TestUpdateCommandStatus {
+
+		@BeforeEach
+		void persistVorgangWithCommand() {
+			repository.save(CommandTestFactory.create());
+		}
+
+		@ParameterizedTest
+		@EnumSource(CommandStatus.class)
+		void shouldUpdateCommandStatus(CommandStatus status) {
+			repository.updateCommandStatus(CommandTestFactory.ID, status);
+
+			Optional<Command> command = repository.getById(CommandTestFactory.ID);
+
+			assertThat(command).isPresent();
+			assertThat(command.get().getStatus()).isEqualTo(status);
+		}
+	}
+
+	@Nested
+	class TestUpdateCommandStatusAndVersion {
+
+		@BeforeEach
+		void persistVorgangWithCommand() {
+			repository.save(CommandTestFactory.create());
+		}
+
+		@ParameterizedTest
+		@EnumSource(CommandStatus.class)
+		void shouldUpdateCommandStatus(CommandStatus status) {
+			repository.updateCommandStatusAndVersion(CommandTestFactory.ID, status, 78L);
+
+			Optional<Command> command = repository.getById(CommandTestFactory.ID);
+
+			assertThat(command).isPresent();
+			assertThat(command.get().getRelationVersion()).isEqualTo(78L);
+			assertThat(command.get().getStatus()).isEqualTo(status);
+		}
+	}
+
+	@Nested
+	class TestGetPendingCommands {
+
+		@BeforeEach
+		void persistCommand() {
+			repository.save(CommandTestFactory.create());
+			repository.save(CommandTestFactory.createBuilder().id(null).vorgangId(VorgangTestFactory.ID).status(CommandStatus.FINISHED).build());
+		}
+
+		@Test
+		void shouldReturnPendingCommand() {
+			var result = repository.getPendingCommands(VorgangTestFactory.ID);
+
+			assertThat(result).hasSize(1);
+			assertThat(result.get(0).getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
+			assertThat(result.get(0).getStatus()).isEqualTo(CommandStatus.PENDING);
+		}
+	}
+
+	@Nested
+	class TestFindCommands {
+
+		@Test
+		void shouldReturnCommandByVorgang() {
+			repository.save(CommandTestFactory.create());
+
+			var commands = repository.findCommands(VorgangTestFactory.ID, Collections.emptyList(), Optional.empty());
+
+			assertThat(commands).hasSize(1);
+		}
+
+		@Nested
+		@DisplayName("by order, status and createdBy")
+		class TestByOrderStatusTime {
+
+			@BeforeEach
+			void setup() {
+				repository.save(createCommandBuilder().build());
+				repository.save(createCommandBuilder().status(CommandStatus.FINISHED).build());
+				repository.save(createCommandBuilder().status(CommandStatus.FINISHED).order(Order.VORGANG_LOESCHEN.name()).build());
+			}
+
+			private PersistedCommand.PersistedCommandBuilder createCommandBuilder() {
+				return CommandTestFactory.createBuilder().id(null).createdAt(getNow());
+			}
+
+			private ZonedDateTime getNow() {
+				return ZonedDateTime.now(ZoneOffset.UTC).withNano(0);
+			}
+
+			@Test
+				// TODO schreibe ein Testcase für Order, Status und Zeit
+			void shouldFindCommand() {
+				var command = repository.save(createCommandBuilder()
+						.status(CommandStatus.FINISHED)
+						.order(Order.VORGANG_LOESCHEN.name())
+						.createdAt(getNow().minusMinutes(2)).build());
+
+				var commands = repository.findCommands(Order.VORGANG_LOESCHEN, CommandStatus.FINISHED, getNow().minusSeconds(1));
+
+				assertThat(commands).hasSize(1).first().usingRecursiveComparison().isEqualTo(command);
+
+			}
+		}
+
+	}
+
+	@DisplayName("Test adding and updating previous state data")
+	@Nested
+	class TestHandlingPreviousState {
+		private static final String PREVIOUS_STATE_STATUS_VALUE = "NEU";
+		private static final String PREVIOUS_STATE_STATUS_FIELD_KEY = Vorgang.MONGODB_FIELDNAME_STATUS;
+
+		private Command command = CommandTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			command = mongoOperations.save(command);
+		}
+
+		@Test
+		void shouldSavePreviousStateValue() {
+			repository.patch(command.getId(), Map.of(PREVIOUS_STATE_STATUS_FIELD_KEY, PREVIOUS_STATE_STATUS_VALUE));
+
+			var persitedCommand = repository.getById(command.getId());
+
+			assertThat(persitedCommand).isPresent().get()
+					.extracting(command -> ((PersistedCommand) command).getPreviousState(), as(InstanceOfAssertFactories.MAP))
+					.containsEntry(PREVIOUS_STATE_STATUS_FIELD_KEY,
+							PREVIOUS_STATE_STATUS_VALUE);
+		}
+	}
+
+	@Nested
+	class TestDeleteAllByVorgang {
+		@Test
+		void shouldDeleteCommand() {
+			mongoOperations.save(CommandTestFactory.create());
+
+			repository.deleteAllByVorgang(VorgangTestFactory.ID);
+
+			assertThat(mongoOperations.count(query(new Criteria()), Command.COLLECTION_NAME)).isZero();
+		}
+
+		@Test
+		void shouldNotDeleteOther() {
+			mongoOperations.save(CommandTestFactory.create());
+
+			repository.deleteAllByVorgang("other");
+
+			assertThat(mongoOperations.count(query(new Criteria()), Command.COLLECTION_NAME)).isOne();
+		}
+	}
+
+	@Nested
+	class TestExistsCommandWithUserId {
+
+		@BeforeEach
+		void setup() {
+			mongoOperations.save(CommandTestFactory.create());
+		}
+
+		@Test
+		void shouldFindInCreatedBy() {
+			var isExists = repository.existsCommandWithUserId(CommandTestFactory.CREATED_BY);
+
+			assertThat(isExists).isTrue();
+		}
+
+		@Test
+		void shouldFindInAssignedTo() {
+			var userId = "userId";
+			var command = CommandTestFactory.createBuilder().createdBy(null).body(Map.of("assignedTo", userId)).build();
+			mongoOperations.save(command);
+
+			var isExists = repository.existsCommandWithUserId(userId);
+
+			assertThat(isExists).isTrue();
+		}
+
+		@Test
+		void shouldReturnFalse() {
+			var esExists = repository.existsCommandWithUserId("userId");
+
+			assertThat(esExists).isFalse();
+		}
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandResponseMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandResponseMapperTest.java
similarity index 93%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandResponseMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandResponseMapperTest.java
index db3d6dab99accf714ffbf1d05ab012a172a0a17b..15509a79823c43ed0a9e7dc12087842d33cdd695 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandResponseMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandResponseMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -29,9 +29,9 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse.GrpcResponseCode;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandResponse.GrpcResponseCode;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
 
 class CommandResponseMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandResponseTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandResponseTestFactory.java
similarity index 83%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandResponseTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandResponseTestFactory.java
index ca4e0210eb38ee39108ccc22feb3398176dd8036..40fa14aaeee33aab891e4bb94bba3ab5c96c7abd 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandResponseTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandResponseTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,16 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.util.List;
 
-import de.itvsh.ozg.pluto.command.CommandResponse.ResponseCode;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.command.CommandResponse.ResponseCode;
 
 public class CommandResponseTestFactory {
 
 	static final ResponseCode RESPONSE_CODE = ResponseCode.PENDING;
-	static final String MESSAGE_CODE = "de.itvsh.ozg.pluto.vorgang.command.error.invalid-document-version";
+	static final String MESSAGE_CODE = "de.ozgcloud.vorgang.vorgang.command.error.invalid-document-version";
 	static final String MESSAGE_PARAM1 = "MessageParam1";
 	static final String MESSAGE_PARAM2 = "MessageParam2";
 	static final Command COMMAND = CommandTestFactory.create();
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRevokedEventTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRevokedEventTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b2b1a5b4dbc24ac2150744501a2f90b865ad7d7
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandRevokedEventTestFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandRevokedEvent;
+
+public class CommandRevokedEventTestFactory {
+	public static CommandRevokedEvent create(Command command) {
+		return new CommandRevokedEvent(command);
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
similarity index 76%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandServiceITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
index c6ae12a889a8f48a50558a5f0d0e9ab87bd01da7..6916ba994de84816f8c511ccadffc58c17103b54 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
 
 import java.util.Optional;
 import java.util.UUID;
@@ -32,29 +33,63 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.boot.test.mock.mockito.SpyBean;
 import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.security.test.context.support.WithMockUser;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 @DataITCase
+@WithMockUser
 class CommandServiceITCase {
 
-	@Autowired
+	@SpyBean
 	private CommandService commandService;
 
 	@Autowired
 	private MongoOperations mongoOperations;
 
+	@MockBean
+	private CurrentUserService currentUserService;
+
 	@Nested
 	class TestVorgangCommandPersist {
 
+		@BeforeEach
+		void initCurrentUserService() {
+			when(currentUserService.findUser()).thenReturn(Optional.of(CallContextUserTestFactory.create()));
+			when(currentUserService.getUser()).thenReturn(CallContextUserTestFactory.create());
+		}
+
 		@BeforeEach
 		void persistVorgang() {
 			mongoOperations.save(VorgangTestFactory.create());
 		}
 
+		@Test
+		void persistCommand() {
+			Command persistedCommand = commandService.saveCommand(
+					CommandTestFactory.createBuilder()
+							.relationId(CommandTestFactory.RELATION_ID)
+							.relationVersion(CommandTestFactory.RELATION_VERSION).build());
+
+			Optional<Command> commandOpt = commandService.findCommand(persistedCommand.getId());
+			assertThat(commandOpt).isPresent();
+
+			Command command = commandOpt.get();
+			assertThat(command.getId()).hasSize(36);
+			assertThat(command.getCreatedAt()).isNotNull();
+			assertThat(command.getStatus()).isEqualTo(CommandStatus.PENDING);
+			assertThat(command.getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
+		}
+
 		@Test
 		void persistCommandHappyPath() {
 			CreateCommandRequest request = CreateCommandRequestTestFactory
@@ -63,7 +98,8 @@ class CommandServiceITCase {
 					.relationVersion(CommandTestFactory.RELATION_VERSION)
 					.build();
 
-			Command persistedCommand = commandService.createCommand(request, Optional.of(VorgangTestFactory.STATUS));
+			Command persistedCommand = commandService.createCommand(request);
+			verify(commandService, timeout(500)).setCommandFinished(eq(persistedCommand.getId()), any());
 
 			Optional<Command> commandOpt = commandService.findCommand(persistedCommand.getId());
 			assertThat(commandOpt).isPresent();
@@ -72,7 +108,7 @@ class CommandServiceITCase {
 			assertThat(command.getId()).hasSize(36);
 			assertThat(command.getCreatedAt()).isNotNull();
 			assertThat(command.getCreatedBy()).isEqualTo(request.getCallContext().getUser().getId());
-			assertThat(command.getStatus()).isEqualTo(CommandStatus.PENDING);
+			assertThat(command.getStatus()).isEqualTo(CommandStatus.FINISHED);
 			assertThat(command.getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
 		}
 	}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
similarity index 62%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
index 74c21e8ba120fe25c7014adc14fd41a110ae1b16..4f40c42572987c2d9b03ce8a24070ecb17e85783 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.time.ZonedDateTime;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -42,11 +43,15 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.springframework.context.ApplicationEventPublisher;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class CommandServiceTest {
 
@@ -71,14 +76,14 @@ class CommandServiceTest {
 
 		@Test
 		void shouldCallOperationRepository() {
-			service.createCommand(request, Optional.of(VorgangTestFactory.STATUS));
+			service.createCommand(request);
 
 			verify(repository).save(any());
 		}
 
 		@Test
 		void shouldReturnCommand() {
-			var command = (PersistedCommand) service.createCommand(request, Optional.of(Status.ANGENOMMEN));
+			var command = (PersistedCommand) service.createCommand(request);
 
 			assertThat(command.getOrder()).isEqualTo(Order.VORGANG_ANNEHMEN.name());
 			assertThat(command.getId()).isNotNull();
@@ -87,14 +92,13 @@ class CommandServiceTest {
 			assertThat(command.getCreatedBy()).isEqualTo(UserTestFactory.ID);
 			assertThat(command.getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID);
 			assertThat(command.getRelationVersion()).isEqualTo(CreateCommandRequestTestFactory.RELATION_VERSION);
-			assertThat(command.getPreviousStatus()).isEqualTo(Status.ANGENOMMEN);
 		}
 
 		@Test
 		void shouldHandleMissingCallContext() {
 			var request = CreateCommandRequestTestFactory.createBuilder().callContext(null).build();
 
-			var command = service.createCommand(request, Optional.of(Status.ANGENOMMEN));
+			var command = service.createCommand(request);
 
 			assertThat(command).isNotNull();
 		}
@@ -106,7 +110,7 @@ class CommandServiceTest {
 			void fromCallContext() {
 				when(currentUserService.findUser()).thenReturn(Optional.empty());
 
-				var command = service.createCommand(request, Optional.of(Status.ANGENOMMEN));
+				var command = service.createCommand(request);
 
 				assertThat(command.getCreatedBy()).isEqualTo(UserTestFactory.ID);
 			}
@@ -116,7 +120,7 @@ class CommandServiceTest {
 				var request = CreateCommandRequestTestFactory.createBuilder().callContext(null).build();
 				when(currentUserService.findUser()).thenReturn(Optional.of(CallContextUserTestFactory.create()));
 
-				var command = service.createCommand(request, Optional.of(Status.ANGENOMMEN));
+				var command = service.createCommand(request);
 
 				assertThat(command.getCreatedBy()).isEqualTo(UserTestFactory.ID);
 			}
@@ -126,7 +130,7 @@ class CommandServiceTest {
 				when(currentUserService.findUser())
 						.thenReturn(Optional.of(CallContextUserTestFactory.createBuilder().userId(Optional.of("other")).build()));
 
-				var command = service.createCommand(request, Optional.of(Status.ANGENOMMEN));
+				var command = service.createCommand(request);
 
 				assertThat(command.getCreatedBy()).isEqualTo("other");
 			}
@@ -138,7 +142,7 @@ class CommandServiceTest {
 			var request = CreateCommandRequestTestFactory.createBuilder().callContext(CallContextTestFactory.createBuilder().user(null).build())
 					.build();
 
-			service.createCommand(request, Optional.empty());
+			service.createCommand(request);
 
 			verify(repository).save(commandCaptor.capture());
 			assertThat(commandCaptor.getValue().getCreatedBy()).isNull();
@@ -176,6 +180,19 @@ class CommandServiceTest {
 		}
 	}
 
+	@Nested
+	class TestFindCommands {
+
+		@Test
+		void shouldCallRepository() {
+			var createdAfter = ZonedDateTime.now();
+
+			service.findFinishedVorgangLoeschenCommandsOlderThen(createdAfter);
+
+			verify(repository).findCommands(Order.VORGANG_LOESCHEN, CommandStatus.FINISHED, createdAfter);
+		}
+	}
+
 	@Nested
 	class TestSetCommandFinished {
 
@@ -185,6 +202,20 @@ class CommandServiceTest {
 
 			verify(repository).updateCommandStatusAndVersion(CommandTestFactory.ID, CommandStatus.FINISHED, 17L);
 		}
+
+		@Test
+		void shouldCallRepositoryFinishCommand() {
+			service.setCommandFinished(CommandTestFactory.ID);
+
+			verify(repository).finishCommand(CommandTestFactory.ID);
+		}
+
+		@Test
+		void shouldCallRepositoryFinishCommandWithCreatedResource() {
+			service.setCommandFinished(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
+
+			verify(repository).finishCommand(CommandTestFactory.ID, CommandTestFactory.CREATED_RESOURCE);
+		}
 	}
 
 	@Nested
@@ -199,18 +230,64 @@ class CommandServiceTest {
 	}
 
 	@Nested
-	class TestRevokeCommand {
+	class TestRevokeCommandPending {
 
 		final String commandId = CommandTestFactory.ID;
 
+		@Test
+		void shouldThrowException() {
+			assertThatExceptionOfType(TechnicalException.class).isThrownBy(() -> service.setCommandRevokePending(commandId));
+		}
+
 		@Test
 		void shouldUpdateCommandStatus() {
+			when(repository.getById(commandId)).thenReturn(Optional.of(CommandTestFactory.create()));
+
+			service.setCommandRevokePending(commandId);
+
+			verify(repository).updateCommandStatus(anyString(), any(CommandStatus.class));
+		}
+
+		@Test
+		void shouldCallPublishRevokeCommandEvent() {
+			when(repository.getById(commandId)).thenReturn(Optional.of(CommandTestFactory.create()));
+
 			service.setCommandRevokePending(commandId);
 
-			verify(service).updateCommandStatus(commandId, CommandStatus.REVOKE_PENDING);
+			verify(service).publishRevokeCommandEvent(any(String.class));
 		}
 	}
 
+	@Nested
+	class TestFiringRevokeCommand {
+
+		final String commandId = CommandTestFactory.ID;
+
+		@Test
+		void shoudlFireEvent() {
+			when(repository.getById(commandId)).thenReturn(Optional.of(CommandTestFactory.create()));
+
+			service.publishRevokeCommandEvent(commandId);
+
+			verify(publisher).publishEvent(any(RevokeCommandEvent.class));
+		}
+
+		@Test
+		void shoudlThrowTechnicalExceptionBecauseCommandNotFound() {
+			when(repository.getById(commandId)).thenReturn(Optional.empty());
+
+			assertThatExceptionOfType(TechnicalException.class).isThrownBy(() -> service.publishRevokeCommandEvent(commandId));
+		}
+
+		@Test
+		void shoudlThrowTechnicalExceptionBecauseNoPreviousState() {
+			when(repository.getById(commandId)).thenReturn(Optional.of(CommandTestFactory.createBuilder().previousState(null).build()));
+
+			assertThatExceptionOfType(TechnicalException.class).isThrownBy(() -> service.publishRevokeCommandEvent(commandId));
+		}
+
+	}
+
 	@Nested
 	class TestExistsPendingCommands {
 
@@ -251,4 +328,39 @@ class CommandServiceTest {
 			assertThat(result).isEqualTo(pendingCommands);
 		}
 	}
+
+	@Nested
+	class TestCommandSetPreviousState {
+
+		final String commandId = CommandTestFactory.ID;
+
+		@Test
+		void shouldSetPreviousState() {
+			service.setPreviousState(commandId, CommandTestFactory.PREVIOUS_STATE);
+
+			verify(repository).patch(anyString(), any());
+		}
+	}
+
+	@Nested
+	class TestDeleteAllByVorgang {
+		@Test
+		void shouldCallRepository() {
+			service.deleteAllByVorgang(VorgangTestFactory.ID);
+
+			verify(repository).deleteAllByVorgang(VorgangTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestFilterUserIdsWithoutCommands {
+
+		@Test
+		void shouldCallRepository() {
+			service.existsCommandWithUserId(UserTestFactory.ID);
+
+			verify(repository).existsCommandWithUserId(UserTestFactory.ID);
+		}
+
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandTestFactory.java
similarity index 79%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandTestFactory.java
index 3fde54908b37cc82fb82e32df3501645a3fe8df5..881cb3fa07e1972f402ccc40d7a35d2406bf52fa 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.time.ZonedDateTime;
+import java.util.Map;
 import java.util.UUID;
 
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class CommandTestFactory {
 
@@ -43,7 +45,8 @@ public class CommandTestFactory {
 	public static final long RELATION_VERSION = VorgangTestFactory.VERSION;
 
 	public static final Order ORDER = Order.VORGANG_ANNEHMEN;
-	public static final Status PREV_STATUS = Status.NEU;
+	public static final Map<String, Object> PREVIOUS_STATE = Map.of("test", "value");
+	public static final String CREATED_RESOURCE = "createdResource";
 
 	public static PersistedCommand create() {
 		return createBuilder().build();
@@ -59,7 +62,7 @@ public class CommandTestFactory {
 				.status(STATUS)
 				.relationId(RELATION_ID)
 				.relationVersion(RELATION_VERSION)
-				.previousStatus(PREV_STATUS)
+				.previousState(PREVIOUS_STATE)
 				.order(ORDER.name());
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CreateCommandRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CreateCommandRequestTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CreateCommandRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CreateCommandRequestTestFactory.java
index ef097e9cf9395b423593eacbc36cd710bbad589d..021e5cdaff9927193d4b189c106841ce23e62263 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CreateCommandRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CreateCommandRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContext;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class CreateCommandRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCallContextTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCallContextTestFactory.java
similarity index 78%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCallContextTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCallContextTestFactory.java
index f35988f8fc81b67a0cd70ef7be975dea8a3e9df8..7b474c2a4f5f8eee3189e87cbd3394444fb70470 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCallContextTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCallContextTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcCallContext;
-import de.itvsh.ozg.pluto.grpc.command.GrpcUser;
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.vorgang.grpc.command.GrpcCallContext;
+import de.ozgcloud.vorgang.grpc.command.GrpcUser;
 
 public class GrpcCallContextTestFactory {
 
 	private static final GrpcUser USER = GrpcUserTestFactory.create();
-	public static final String CLIENT = "testGoofyClient";
+	public static final String CLIENT = LoremIpsum.getInstance().getFirstName() + "Client";
 
 	public static GrpcCallContext create() {
 		return createBuilder().build();
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCommandMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandMapperTest.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCommandMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandMapperTest.java
index 1ace4f856671a3ffd6d3a2acdef130fd3222f3c1..5346247647d9698047e836c7b1d153f308eab11d 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCommandMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -29,8 +29,8 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommand;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
 
 class GrpcCommandMapperTest {
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..1692eb465876e0d2786998cd245051bca6a5a93a
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceITCase.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.command;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.awaitility.Awaitility.*;
+import static org.mockito.Mockito.*;
+
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.annotation.DirtiesContext;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.grpc.command.CommandServiceGrpc.CommandServiceBlockingStub;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@SpringBootTest(properties = {
+		"grpc.server.inProcessName=test",
+		"grpc.client.inProcess.address=in-process:test"
+})
+@DirtiesContext
+@DataITCase
+@WithMockUser
+class GrpcCommandServiceITCase {
+
+	@GrpcClient("inProcess")
+	private CommandServiceBlockingStub serviceBlockingStub;
+
+	@Autowired
+	private MongoOperations mongoOperations;
+
+	@MockBean
+	private ClientAttributeReadPermitted readIsPermitted;
+
+	private GrpcObjectMapper grpcObjectMapper = Mappers.getMapper(GrpcObjectMapper.class);
+
+	@Nested
+	class TestCreateCommand {
+
+		private GrpcCreateCommandRequest request;
+
+		@BeforeEach
+		void prepareDatabase() {
+			mongoOperations.dropCollection(Vorgang.COLLECTION_NAME);
+			mongoOperations.dropCollection(Command.COLLECTION_NAME);
+			mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
+
+			var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).build());
+
+			request = GrpcCreateCommandRequestTestFactory.createBuilder()
+					.setVorgangId(vorgang.getId()).setRelationId(vorgang.getId())
+					.setOrder(GrpcOrder.CREATE_ATTACHED_ITEM)
+					.setBodyObj(grpcObjectMapper.fromMap(VorgangAttachedItemTestFactory.asMap())).build();
+
+			when(readIsPermitted.test(any())).thenReturn(true);
+		}
+
+		@Test
+		void shouldPersistCommand() {
+			serviceBlockingStub.createCommand(request);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var commands = mongoOperations.findAll(Command.class);
+
+				assertThat(commands).hasSize(1).first().satisfies(command -> {
+					assertThat(command.getBodyObject()).isNotNull();
+					assertThat(command.getBodyObject()).containsEntry("itemName", VorgangAttachedItemTestFactory.ITEM_NAME);
+				});
+			});
+		}
+
+		@Test
+		void shouldExecuteCommand() {
+			serviceBlockingStub.createCommand(request);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var commands = mongoOperations.findAll(Command.class);
+
+				assertThat(commands).hasSize(1).first().extracting(Command::getStatus).isEqualTo(CommandStatus.FINISHED);
+			});
+		}
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCommandServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceTest.java
similarity index 79%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCommandServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceTest.java
index 7a0b2dae80b03cf2e122f7e80b0c14b524bf3529..e73d1ec93ceca8197405b072ff3ea2502e6b0452 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCommandServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCommandServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -44,23 +44,29 @@ import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
-
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommand;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandsResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcExistsPendingCommandsRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcExistsPendingCommandsResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcFindCommandsRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcGetPendingCommandsResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
-import de.itvsh.ozg.pluto.grpc.command.GrpcRevokeCommandRequest;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommand;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandsResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcEmpty;
+import de.ozgcloud.vorgang.grpc.command.GrpcExistsPendingCommandsRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcExistsPendingCommandsResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcFindCommandsRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetPendingCommandsRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcGetPendingCommandsResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.grpc.command.GrpcRevokeCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcSetCommandExecutedRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.stub.StreamObserver;
+import lombok.SneakyThrows;
 
 class GrpcCommandServiceTest {
 
@@ -68,17 +74,19 @@ class GrpcCommandServiceTest {
 	@InjectMocks
 	private GrpcCommandService service;
 	@Mock
-	private VorgangService vorgangService;
-	@Mock
 	private GrpcCreateCommandRequestMapper createCommandRequestMapper;
 	@Mock
 	private CommandService commandService;
+
 	@Mock
 	private GrpcCommandResponseMapper commandResponseMapper;
 	@Mock
 	private GrpcCommandMapper commandMapper;
+
 	@Mock
 	private PolicyService policyService;
+	@Mock
+	private ApplicationEventPublisher eventPublisher;
 
 	@Nested
 	class TestCreateCommand {
@@ -95,12 +103,9 @@ class GrpcCommandServiceTest {
 		@BeforeEach
 		void mockMapper() {
 			when(createCommandRequestMapper.fromGrpc(any(GrpcCreateCommandRequest.class))).thenReturn(createComandRequest);
-			when(vorgangService.getById(any())).thenReturn(VorgangTestFactory.create());
-			when(commandService.createCommand(any(CreateCommandRequest.class), any())).thenReturn(persistedCommand);
+			when(commandService.createCommand(any(CreateCommandRequest.class))).thenReturn(persistedCommand);
 			when(commandService.findCommand(anyString())).thenReturn(Optional.of(CommandTestFactory.create()));
 			when(commandResponseMapper.toGrpc(any(CommandResponse.class))).thenReturn(response);
-
-			doNothing().when(service).executeOrder(any());
 		}
 
 		@Test
@@ -117,18 +122,11 @@ class GrpcCommandServiceTest {
 			verify(createCommandRequestMapper).fromGrpc(request);
 		}
 
-		@Test
-		void shouldCallVorgangService() throws Exception {
-			callCreateCommand();
-
-			verify(vorgangService).getById(CommandTestFactory.RELATION_ID);
-		}
-
 		@Test
 		void shouldCallCommandService() throws Exception {
 			callCreateCommand();
 
-			verify(commandService).createCommand(createComandRequest, Optional.of(VorgangTestFactory.STATUS));
+			verify(commandService).createCommand(createComandRequest);
 		}
 
 		@Test
@@ -161,7 +159,8 @@ class GrpcCommandServiceTest {
 
 		@ParameterizedTest
 		@EnumSource(mode = Mode.EXCLUDE, names = { "VORGANG_ANNEHMEN", "VORGANG_VERWERFEN", "VORGANG_ZURUECKHOLEN", "VORGANG_BEARBEITEN",
-				"VORGANG_BESCHEIDEN", "VORGANG_ZURUECKSTELLEN", "VORGANG_ABSCHLIESSEN", "VORGANG_WIEDEREROEFFNEN" })
+				"VORGANG_BESCHEIDEN", "VORGANG_ZURUECKSTELLEN", "VORGANG_ABSCHLIESSEN", "VORGANG_WIEDEREROEFFNEN", "VORGANG_ZUM_LOESCHEN_MARKIEREN",
+				"VORGANG_LOESCHEN" })
 		void shouldReturnFalse(Order order) {
 			var result = service.isStatusChangeOrder(order.name());
 
@@ -257,20 +256,6 @@ class GrpcCommandServiceTest {
 			verify(commandResponseMapper).toGrpc(any());
 		}
 
-		@Test
-		void shouldCallServiceSetCommandRevoked() throws Exception {
-			callRevokeCommand();
-
-			verify(commandService).setCommandRevoked(any());
-		}
-
-		@Test
-		void shouldCallProceed() throws Exception {
-			callRevokeCommand();
-
-			verify(service).proceedRevokeCommand(CommandTestFactory.ID);
-		}
-
 		@Nested
 		class TestProceedRevokeCommand {
 
@@ -282,25 +267,12 @@ class GrpcCommandServiceTest {
 			}
 
 			@Test
+			@SneakyThrows
 			void shouldLoadCommand() {
-				service.proceedRevokeCommand(CommandTestFactory.ID);
+				callRevokeCommand();
 
 				verify(service).getCommand(CommandTestFactory.ID);
 			}
-
-			@Test
-			void shouldRevokeCommand() {
-				service.proceedRevokeCommand(CommandTestFactory.ID);
-
-				verify(vorgangService).revokeStatusChange(command);
-			}
-
-			@Test
-			void shouldSetCommandRevoked() {
-				service.proceedRevokeCommand(CommandTestFactory.ID);
-
-				verify(commandService).setCommandRevoked(CommandTestFactory.ID);
-			}
 		}
 
 		private void callRevokeCommand() throws Exception {
@@ -428,4 +400,59 @@ class GrpcCommandServiceTest {
 			service.findCommands(request, responseObserver);
 		}
 	}
+
+	@Nested
+	class TestSetCommandExecuted {
+
+		@Mock
+		private StreamObserver<GrpcEmpty> responseObserver;
+
+		@BeforeEach
+		void init() {
+			when(commandService.findCommand(any())).thenReturn(Optional.of(CommandTestFactory.create()));
+		}
+
+		@Test
+		void shouldLoadCommand() {
+			service.setCommandExecuted(buildRequest(), responseObserver);
+
+			verify(commandService).findCommand(CommandTestFactory.ID);
+		}
+
+		@Test
+		void shouldPublishEvent() {
+			service.setCommandExecuted(buildRequest(), responseObserver);
+
+			verify(eventPublisher).publishEvent(any(CommandExecutedEvent.class));
+		}
+
+		@Test
+		void shouldHandleMissingCommand() {
+			when(commandService.findCommand(any())).thenReturn(Optional.empty());
+
+			service.setCommandExecuted(buildRequest(), responseObserver);
+
+			verifyNoInteractions(eventPublisher);
+		}
+
+		@Test
+		void shouldCallOnNext() {
+			service.setCommandExecuted(buildRequest(), responseObserver);
+
+			verify(responseObserver).onNext(GrpcEmpty.newBuilder().build());
+		}
+
+		@Test
+		void shouldCallOnCompleted() {
+			service.setCommandExecuted(buildRequest(), responseObserver);
+
+			verify(responseObserver).onCompleted();
+		}
+
+		private GrpcSetCommandExecutedRequest buildRequest() {
+			return GrpcSetCommandExecutedRequest.newBuilder()
+					.setCommandId(CommandTestFactory.ID)
+					.build();
+		}
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestMapperTest.java
similarity index 90%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestMapperTest.java
index d6ab033eb1fa3ac484b3d992685203136ff24205..edfa651607505853a5470af74864ba2a701a719f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -32,9 +32,11 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.files.FileIdMapper;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.vorgang.callcontext.CallContext;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.callcontext.User;
+import de.ozgcloud.vorgang.files.FileIdMapper;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
 
 class GrpcCreateCommandRequestMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestTestFactory.java
similarity index 83%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestTestFactory.java
index 9b328d265419708a1ce831195d1ba33853080bfb..08e25ddcbfbe472eb1993b9880e29a38be96e3ed 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcCreateCommandRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcCreateCommandRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcCallContext;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.grpc.command.GrpcCallContext;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class GrpcCreateCommandRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcUserTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcUserTestFactory.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcUserTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcUserTestFactory.java
index 3aec033e05bc378e2321e1b51b601b27be58bbf9..ae7c36d432d81f9dbeacd0ec9de530ff3f6588ea 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/GrpcUserTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/GrpcUserTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import java.util.List;
 
-import de.itvsh.ozg.pluto.grpc.command.GrpcUser;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.grpc.command.GrpcUser;
 
 public class GrpcUserTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/PersistPostfachMailByCommandServiceITCase.java
similarity index 80%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandServiceITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/PersistPostfachMailByCommandServiceITCase.java
index 5b8e1ba2b9590d0d574ef826d88ec603e83e8356..066ad750bd38e397cb933b8eaa8ccca59a2c5925 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/PersistPostfachMailByCommandServiceITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -36,19 +36,21 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.security.test.context.support.WithMockUser;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.mail.postfach.PostfachMailTestFactory;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 @WithMockUser
 @DataITCase
 class PersistPostfachMailByCommandServiceITCase {
 
 	@Autowired
-	private PersistPostfachMailByCommandService service;
+	private PersistPostfachNachrichtByCommandService service;
 
 	@Autowired
 	private MongoOperations mongoOperations;
@@ -72,7 +74,8 @@ class PersistPostfachMailByCommandServiceITCase {
 
 		@Test
 		void shouldCreateCommand() {
-			service.persistMail(Optional.of(UserTestFactory.ID), PostfachMailTestFactory.createBuilder().vorgangId(persistedVorgang.getId()).build());
+			service.persistNachricht(Optional.of(UserTestFactory.ID),
+					PostfachNachrichtTestFactory.createBuilder().vorgangId(persistedVorgang.getId()).build());
 
 			var commands = mongoOperations.findAll(Command.class);
 			assertThat(commands).hasSize(1);
@@ -90,8 +93,8 @@ class PersistPostfachMailByCommandServiceITCase {
 			mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
 			persistedItem = mongoOperations.save(VorgangAttachedItemTestFactory.createBuilder()
 					.id(null).version(0).vorgangId(persistedVorgang.getId())
-					.client(PersistPostfachMailByCommandService.CLIENT)
-					.itemName(PersistPostfachMailByCommandService.ITEM_NAME).build());
+					.client(PersistPostfachNachrichtByCommandService.CLIENT)
+					.itemName(PersistPostfachNachrichtByCommandService.ITEM_NAME).build());
 		}
 
 		@DisplayName("find by vorgang")
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/PersistPostfachMailByCommandServiceTest.java
similarity index 64%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/PersistPostfachMailByCommandServiceTest.java
index df36deeb74a0d6264796ad8512c5f0a3a0fb9f16..d13b312e4673206fafdcb9affd3328a8d760aefa 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/PersistPostfachMailByCommandServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/PersistPostfachMailByCommandServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.command;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
-import java.io.IOException;
 import java.io.InputStream;
 import java.util.Map;
 import java.util.Optional;
@@ -45,22 +44,23 @@ import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.ozg.mail.postfach.MessageAttachmentTestFactory;
-import de.itvsh.ozg.mail.postfach.MessageTestFactory;
-import de.itvsh.ozg.mail.postfach.PostfachMailTestFactory;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemMapper;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemService;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemTestFactory;
-import de.itvsh.ozg.pluto.files.FileId;
-import de.itvsh.ozg.pluto.files.FileService;
-import de.itvsh.ozg.pluto.files.OzgFile;
-import de.itvsh.ozg.pluto.files.UploadedFilesReference;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory;
+import de.ozgcloud.nachrichten.postfach.osi.MessageAttachmentTestFactory;
+import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemMapper;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemService;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.files.FileId;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.files.OzgFile;
+import de.ozgcloud.vorgang.files.UploadedFilesReference;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class PersistPostfachMailByCommandServiceTest {
 
 	@InjectMocks
-	private PersistPostfachMailByCommandService service;
+	private PersistPostfachNachrichtByCommandService service;
 	@Mock
 	private CommandService commandService;
 	@Mock
@@ -68,6 +68,7 @@ class PersistPostfachMailByCommandServiceTest {
 	@Mock
 	private FileService fileService;
 
+	@DisplayName("Persist mail")
 	@Nested
 	class TestPersistMail {
 
@@ -93,7 +94,7 @@ class PersistPostfachMailByCommandServiceTest {
 			var request = callService();
 
 			assertThat(request.getRelationId()).isEqualTo(MessageTestFactory.VORGANG_ID);
-			assertThat(request.getRelationVersion()).isEqualTo(-1);
+			assertThat(request.getRelationVersion()).isNull();
 		}
 
 		@Test
@@ -117,34 +118,35 @@ class PersistPostfachMailByCommandServiceTest {
 
 			assertThat(request.getBodyObject())
 					.containsEntry(VorgangAttachedItemMapper.PROPERTY_VORGANG_ID, MessageTestFactory.VORGANG_ID)
-					.containsEntry(VorgangAttachedItemMapper.PROPERTY_CLIENT, "MailService")
+					.containsEntry(VorgangAttachedItemMapper.PROPERTY_CLIENT, "OzgCloud_NachrichtenManager")
 					.containsEntry(VorgangAttachedItemMapper.PROPERTY_ITEM_NAME, "PostfachMail")
 					.containsKey(VorgangAttachedItemMapper.PROPERTY_ITEM);
 		}
 
 		@Test
 		void shouldNotAddUser() {
-			service.persistMail(Optional.empty(), PostfachMailTestFactory.create());
+			service.persistNachricht(Optional.empty(), PostfachNachrichtTestFactory.create());
 			verify(commandService).createCommand(requestCaptor.capture());
 
 			assertThat(requestCaptor.getValue().getCallContext().getUser()).isNull();
 		}
 
 		private CreateCommandRequest callService() {
-			service.persistMail(Optional.of(UserTestFactory.ID), PostfachMailTestFactory.create());
+			service.persistNachricht(Optional.of(UserTestFactory.ID), PostfachNachrichtTestFactory.createBuilder().id(null).build());
 			verify(commandService).createCommand(requestCaptor.capture());
 
 			return requestCaptor.getValue();
 		}
 
+		@DisplayName("build mail map")
 		@Nested
 		class TestBuildMailMap {
 
 			@Test
 			void shouldContainAllFieldsIgnoringId() {
-				var map = service.buildMailMap(PostfachMailTestFactory.createBuilder().id(null).build());
+				var map = service.buildNachrichtMap(PostfachNachrichtTestFactory.createBuilder().id(null).build());
 
-				var mapWithoutId = PostfachMailTestFactory.asMap();
+				var mapWithoutId = PostfachNachrichtTestFactory.asMap();
 				mapWithoutId.remove("id");
 
 				assertThat(map).containsAllEntriesOf(mapWithoutId);
@@ -152,12 +154,26 @@ class PersistPostfachMailByCommandServiceTest {
 
 			@Test
 			void shouldIgnoreEmptyMessageId() {
-				assertDoesNotThrow(() -> service.buildMailMap(PostfachMailTestFactory.createBuilder().messageId(null).build()));
+				assertDoesNotThrow(() -> service.buildNachrichtMap(PostfachNachrichtTestFactory.createBuilder().messageId(null).build()));
 			}
 
 			@Test
 			void shouldIgnoreEmptyCreatedBy() {
-				assertDoesNotThrow(() -> service.buildMailMap(PostfachMailTestFactory.createBuilder().createdBy(null).build()));
+				assertDoesNotThrow(() -> service.buildNachrichtMap(PostfachNachrichtTestFactory.createBuilder().createdBy(null).build()));
+			}
+
+			@Test
+			void shouldHandleNullAsPostfachId() {
+				var postfachMail = PostfachNachrichtTestFactory.createBuilder().postfachId(null).build();
+
+				assertDoesNotThrow(() -> service.buildNachrichtMap(postfachMail));
+			}
+
+			@Test
+			void shouldProceedWithEmptyPostfachAddress() {
+				var postfachMail = PostfachNachrichtTestFactory.createBuilder().postfachAddress(null).build();
+
+				assertDoesNotThrow(() -> service.buildNachrichtMap(postfachMail));
 			}
 		}
 	}
@@ -168,21 +184,21 @@ class PersistPostfachMailByCommandServiceTest {
 		@BeforeEach
 		void init() {
 			when(attachedItemService.findById(anyString()))
-					.thenReturn(Optional.of(VorgangAttachedItemTestFactory.createBuilder().item(PostfachMailTestFactory.asMap()).build()));
+					.thenReturn(Optional.of(VorgangAttachedItemTestFactory.createBuilder().item(PostfachNachrichtTestFactory.asMap()).build()));
 		}
 
 		@Test
 		void shouldCallItemService() {
-			service.findById(PostfachMailTestFactory.ID);
+			service.findById(PostfachNachrichtTestFactory.ID);
 
-			verify(attachedItemService).findById(PostfachMailTestFactory.ID);
+			verify(attachedItemService).findById(PostfachNachrichtTestFactory.ID);
 		}
 
 		@Test
 		void shouldReturnNachrichtAsMap() {
-			var found = service.findById(PostfachMailTestFactory.ID);
+			var found = service.findById(PostfachNachrichtTestFactory.ID);
 
-			assertThat(found).isPresent().get().usingRecursiveComparison().isEqualTo(PostfachMailTestFactory.asMap());
+			assertThat(found).isPresent().get().usingRecursiveComparison().isEqualTo(PostfachNachrichtTestFactory.asMap());
 		}
 	}
 
@@ -192,22 +208,22 @@ class PersistPostfachMailByCommandServiceTest {
 		@BeforeEach
 		void init() {
 			when(attachedItemService.find(anyString(), any(), any()))
-					.thenReturn(Stream.of(VorgangAttachedItemTestFactory.createBuilder().item(PostfachMailTestFactory.asMap()).build()));
+					.thenReturn(Stream.of(VorgangAttachedItemTestFactory.createBuilder().item(PostfachNachrichtTestFactory.asMap()).build()));
 		}
 
 		@Test
 		void shouldCallItemService() {
 			service.findByVorgangAsMap(VorgangTestFactory.ID);
 
-			verify(attachedItemService).find(VorgangTestFactory.ID, Optional.of(PersistPostfachMailByCommandService.CLIENT),
-					Optional.of(PersistPostfachMailByCommandService.ITEM_NAME));
+			verify(attachedItemService).find(VorgangTestFactory.ID, Optional.of(PersistPostfachNachrichtByCommandService.CLIENT),
+					Optional.of(PersistPostfachNachrichtByCommandService.ITEM_NAME));
 		}
 
 		@Test
 		void shouldReturnNachrichtenAsMap() {
 			var found = service.findByVorgangAsMap(VorgangTestFactory.ID);
 
-			assertThat(found).first().usingRecursiveComparison().isEqualTo(PostfachMailTestFactory.asMap());
+			assertThat(found).first().usingRecursiveComparison().isEqualTo(PostfachNachrichtTestFactory.asMap());
 		}
 	}
 
@@ -231,21 +247,21 @@ class PersistPostfachMailByCommandServiceTest {
 		@BeforeEach
 		void mockService() {
 			when(attachedItemService.getById(anyString()))
-					.thenReturn(VorgangAttachedItemTestFactory.createBuilder().item(PostfachMailTestFactory.asMap()).build());
+					.thenReturn(VorgangAttachedItemTestFactory.createBuilder().item(PostfachNachrichtTestFactory.asMap()).build());
 		}
 
 		@Test
 		void shouldCallService() {
-			service.getById(PostfachMailTestFactory.ID);
+			service.getById(PostfachNachrichtTestFactory.ID);
 
-			verify(attachedItemService).getById(PostfachMailTestFactory.ID);
+			verify(attachedItemService).getById(PostfachNachrichtTestFactory.ID);
 		}
 
 		@Test
 		void shouldReturnItem() {
-			Map<String, Object> item = service.getById(PostfachMailTestFactory.ID);
+			Map<String, Object> item = service.getById(PostfachNachrichtTestFactory.ID);
 
-			assertThat(item).isEqualTo(PostfachMailTestFactory.asMap());
+			assertThat(item).isEqualTo(PostfachNachrichtTestFactory.asMap());
 		}
 	}
 
@@ -256,8 +272,8 @@ class PersistPostfachMailByCommandServiceTest {
 			UploadedFilesReference ref = service.createUploadedFilesReference(MessageTestFactory.VORGANG_ID);
 
 			assertThat(ref.getVorgangId()).isEqualTo(MessageTestFactory.VORGANG_ID);
-			assertThat(ref.getClient()).isEqualTo(PersistPostfachMailByCommandService.CLIENT);
-			assertThat(ref.getName()).isEqualTo(PersistPostfachMailByCommandService.ATTACHMENT_NAME);
+			assertThat(ref.getClient()).isEqualTo(PersistPostfachNachrichtByCommandService.CLIENT);
+			assertThat(ref.getName()).isEqualTo(PersistPostfachNachrichtByCommandService.ATTACHMENT_NAME);
 		}
 	}
 
@@ -265,7 +281,7 @@ class PersistPostfachMailByCommandServiceTest {
 	class TestOzgFileCreation {
 		@Test
 		void shouldCreateOzgFile() {
-			OzgFile file = service.createOzgFile(MessageAttachmentTestFactory.create(), ContentType.APPLICATION_OCTET_STREAM.toString(),
+			OzgFile file = service.createOzgFile(MessageAttachmentTestFactory.FILENAME, ContentType.APPLICATION_OCTET_STREAM.toString(),
 					MessageAttachmentTestFactory.SIZE);
 
 			assertThat(file.getContentType()).isEqualTo(ContentType.APPLICATION_OCTET_STREAM.toString());
@@ -293,14 +309,14 @@ class PersistPostfachMailByCommandServiceTest {
 			void shouldHaveClientName() {
 				var ref = callService();
 
-				assertThat(ref.getClient()).isEqualTo(PersistPostfachMailByCommandService.CLIENT);
+				assertThat(ref.getClient()).isEqualTo(PersistPostfachNachrichtByCommandService.CLIENT);
 			}
 
 			@Test
 			void shouldHaveName() {
 				var ref = callService();
 
-				assertThat(ref.getName()).isEqualTo(PersistPostfachMailByCommandService.ATTACHMENT_NAME);
+				assertThat(ref.getName()).isEqualTo(PersistPostfachNachrichtByCommandService.ATTACHMENT_NAME);
 			}
 
 			@Test
@@ -311,7 +327,7 @@ class PersistPostfachMailByCommandServiceTest {
 			}
 
 			private UploadedFilesReference callService() {
-				service.persistAttachment(VorgangTestFactory.ID, MessageAttachmentTestFactory.create());
+				service.persistAttachment(VorgangTestFactory.ID, AttachmentFileTestFactory.create());
 
 				verify(fileService).uploadFileStream(refCaptor.capture(), any(), any(), any());
 
@@ -347,7 +363,9 @@ class PersistPostfachMailByCommandServiceTest {
 			}
 
 			private OzgFile callService() {
-				service.persistAttachment(VorgangTestFactory.ID, MessageAttachmentTestFactory.create());
+				var attachmentFile = AttachmentFileTestFactory.createBuilder().content(AttachmentFileTestFactory.BASE64_CONTENT_SUPPLIER).build();
+
+				service.persistAttachment(VorgangTestFactory.ID, attachmentFile);
 
 				verify(fileService).uploadFileStream(any(), ozgFileCaptor.capture(), any(), any());
 
@@ -356,18 +374,19 @@ class PersistPostfachMailByCommandServiceTest {
 		}
 
 		@Test
-		void shouldHaveContent() throws IOException {
+		void shouldHaveContent() {
 			ArgumentCaptor<InputStream> contentCaptor = ArgumentCaptor.forClass(InputStream.class);
+			var attachment = AttachmentFileTestFactory.createBuilder().content(AttachmentFileTestFactory.BASE64_CONTENT_SUPPLIER).build();
 
-			service.persistAttachment(VorgangTestFactory.ID, MessageAttachmentTestFactory.create());
+			service.persistAttachment(VorgangTestFactory.ID, attachment);
 
 			verify(fileService).uploadFileStream(any(), any(), any(), contentCaptor.capture());
-			assertThat(contentCaptor.getValue().readAllBytes()).isEqualTo(MessageAttachmentTestFactory.DECODED_CONTENT.getBytes());
+			assertThat(contentCaptor.getValue()).hasContent(AttachmentFileTestFactory.CONTENT);
 		}
 
 		@Test
 		void shouldReturnFileId() {
-			var id = service.persistAttachment(VorgangTestFactory.ID, MessageAttachmentTestFactory.create());
+			var id = service.persistAttachment(VorgangTestFactory.ID, AttachmentFileTestFactory.create());
 
 			assertThat(id).isEqualTo("42");
 		}
@@ -377,21 +396,27 @@ class PersistPostfachMailByCommandServiceTest {
 	class TestGetTypeByFileName {
 		@Test
 		void shouldReturnDocxType() {
-			var type = service.getTypeByFile("file.docx", "word-file");
+			var attachmentFile = AttachmentFileTestFactory.createBuilder().name("file.docx").contentType("word-file").build();
+
+			var type = service.getTypeByFile(attachmentFile);
 
 			assertThat(type).isEqualTo("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
 		}
 
 		@Test
 		void shouldReturnOctedStreamAsUnkown() {
-			var type = service.getTypeByFile("file.qtsch", "lalal");
+			var attachmentFile = AttachmentFileTestFactory.createBuilder().name("file.qtsch").contentType("lalal").build();
+
+			var type = service.getTypeByFile(attachmentFile);
 
 			assertThat(type).isEqualTo(ContentType.APPLICATION_OCTET_STREAM.toString());
 		}
 
 		@Test
 		void shouldReturnOdtType() {
-			var type = service.getTypeByFile("file.odt", "opendoc file");
+			var attachmentFile = AttachmentFileTestFactory.createBuilder().name("file.odt").contentType("opendoc file").build();
+
+			var type = service.getTypeByFile(attachmentFile);
 
 			assertThat(type).isEqualTo("application/vnd.oasis.opendocument.text");
 		}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeReadConverterTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeReadConverterTest.java
similarity index 93%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeReadConverterTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeReadConverterTest.java
index f940866579237f7b4d42f4f322717a675a47121c..0059677c55377e920bc6441e8a81e046f7c890dd 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeReadConverterTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeReadConverterTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.converter;
+package de.ozgcloud.vorgang.common.converter;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeWriteConverterTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeWriteConverterTest.java
similarity index 93%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeWriteConverterTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeWriteConverterTest.java
index b3f3f82fabeaff651f71adab575d69d015073953..26e55de972cf29bc715536aa13fc16d29427c5de 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/converter/ZonedDateTimeWriteConverterTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/converter/ZonedDateTimeWriteConverterTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.converter;
+package de.ozgcloud.vorgang.common.converter;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/db/CollisionVerifierTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/db/CollisionVerifierTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..05ccc5bd735c78856fc8c53c38c7acbb78908458
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/db/CollisionVerifierTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.db;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ConcurrentModificationException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+
+import com.mongodb.Function;
+import com.mongodb.client.result.DeleteResult;
+import com.mongodb.client.result.UpdateResult;
+
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+class CollisionVerifierTest {
+
+	private CollisionVerifier verifier;
+
+	@Mock
+	private Function<String, Boolean> doEntryWithIdExist;
+
+	@BeforeEach
+	void setup() {
+		verifier = spy(new CollisionVerifier(doEntryWithIdExist));
+	}
+
+	@Nested
+	class VerifyUpdateResult {
+
+		@Mock
+		private UpdateResult result;
+
+		@Test
+		@DisplayName("should detect concurrent modification")
+		void shouldThrowConcurrentModification() {
+			when(result.getMatchedCount()).thenReturn(0L);
+			when(result.getModifiedCount()).thenReturn(0L);
+			when(doEntryWithIdExist.apply(anyString())).thenReturn(true);
+
+			assertThatThrownBy(() -> verifier.verify(result, VorgangTestFactory.ID)).isInstanceOf(ConcurrentModificationException.class);
+		}
+
+		@Nested
+		@DisplayName("should NOT throw concurrent modification exception")
+		class NotThrowingException {
+			@Test
+			void onSuccessfullUpdate() {
+				when(result.getModifiedCount()).thenReturn(1L);
+
+				assertThatCode(() -> verifier.verify(result, VorgangTestFactory.ID)).doesNotThrowAnyException();
+			}
+
+			@Test
+			@DisplayName("if Vorgang does not exists.")
+			void onMissingVorgang() {
+				when(result.getMatchedCount()).thenReturn(0L);
+				when(result.getModifiedCount()).thenReturn(0L);
+				when(doEntryWithIdExist.apply(anyString())).thenReturn(false);
+
+				assertThatCode(() -> verifier.verify(result, VorgangTestFactory.ID)).doesNotThrowAnyException();
+			}
+
+			@Test
+			@DisplayName("on unchanged")
+			void onOnchangedVorgang() {
+				when(result.getMatchedCount()).thenReturn(1L);
+				when(result.getModifiedCount()).thenReturn(0L);
+
+				assertThatCode(() -> verifier.verify(result, VorgangTestFactory.ID)).doesNotThrowAnyException();
+			}
+		}
+
+	}
+
+	@Nested
+	class VerifyDeleteResult {
+
+		@Mock
+		private DeleteResult result;
+
+		@BeforeEach
+		void setup() {
+			when(result.wasAcknowledged()).thenReturn(true);
+		}
+
+		@Test
+		@DisplayName("should detect concurrent modification")
+		void shouldThrowConcurrentModification() {
+			when(doEntryWithIdExist.apply(anyString())).thenReturn(true);
+			when(result.getDeletedCount()).thenReturn(0L);
+
+			assertThatThrownBy(() -> verifier.verify(result, VorgangTestFactory.ID)).isInstanceOf(ConcurrentModificationException.class);
+		}
+
+		@Nested
+		@DisplayName("should NOT throw concurrent modification exception")
+		class TestNotThrowingException {
+
+			@Test
+			void onSuccessfulDelete() {
+				when(result.getDeletedCount()).thenReturn(1L);
+
+				assertThatCode(() -> verifier.verify(result, VorgangTestFactory.ID)).doesNotThrowAnyException();
+			}
+
+			@Test
+			@DisplayName("if VorgangAttachedItem does not exists.")
+			void onMissingVorgangAttachedItem() {
+				when(doEntryWithIdExist.apply(anyString())).thenReturn(false);
+				when(result.getDeletedCount()).thenReturn(0L);
+
+				assertThatCode(() -> verifier.verify(result, VorgangTestFactory.ID)).doesNotThrowAnyException();
+			}
+
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/CriteriaUtilTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/db/CriteriaUtilTest.java
similarity index 84%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/CriteriaUtilTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/db/CriteriaUtilTest.java
index d781fb8f28552ef0807a6513d7597cfb3d07217a..0b2432f6ca825cf4bbe73b04388b047cf03c77eb 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/CriteriaUtilTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/db/CriteriaUtilTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.common.db;
 
 import static org.assertj.core.api.Assertions.*;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+
 class CriteriaUtilTest {
 
 	@Nested
@@ -35,14 +37,14 @@ class CriteriaUtilTest {
 
 		@Test
 		void shouldContainsKey() {
-			var criteria = CriteriaUtil.vorgangInCreation();
+			var criteria = CriteriaUtil.vorgangNotInCreation();
 
 			assertThat(criteria.getKey()).isEqualTo(Vorgang.MONGODB_FIELDNAME_IN_CREATION);
 		}
 
 		@Test
 		void shouldCreateCriteria() {
-			var criteria = CriteriaUtil.vorgangInCreation();
+			var criteria = CriteriaUtil.vorgangNotInCreation();
 
 			assertThat(criteria.getCriteriaObject()).containsEntry(Vorgang.MONGODB_FIELDNAME_IN_CREATION, false);
 		}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/errorhandling/ExceptionHandlerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/errorhandling/ExceptionHandlerTest.java
similarity index 96%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/errorhandling/ExceptionHandlerTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/errorhandling/ExceptionHandlerTest.java
index 57c21a194eb657e6c05f7234a410d05b320f7025..06f41a2b13f1d5173aa919309a6e5a2a3a534e83 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/errorhandling/ExceptionHandlerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/errorhandling/ExceptionHandlerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,8 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.errorhandling;
+package de.ozgcloud.vorgang.common.errorhandling;
 
+import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Map;
@@ -34,12 +35,10 @@ import org.mockito.InjectMocks;
 import org.mockito.Spy;
 import org.springframework.security.access.AccessDeniedException;
 
-import static org.assertj.core.api.Assertions.*;
-
-import de.itvsh.kop.common.errorhandling.FunctionalErrorCode;
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.errorhandling.FunctionalErrorCode;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.Metadata;
 import io.grpc.Metadata.Key;
 import io.grpc.Status.Code;
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/errorhandling/FunctionalExceptionTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/errorhandling/FunctionalExceptionTest.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/errorhandling/FunctionalExceptionTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/errorhandling/FunctionalExceptionTest.java
index 180a935867323a9371b852994bab22d6205e53d1..64e28ab737b5b63a05893e2313ca5f6b62d82485 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/errorhandling/FunctionalExceptionTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/errorhandling/FunctionalExceptionTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.errorhandling;
+package de.ozgcloud.vorgang.common.errorhandling;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M001_UpdateClientNameInClientAttributesITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M001_UpdateClientNameInClientAttributesITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..50afa9db46f36df73e24085a87c9fa2474a42e5c
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M001_UpdateClientNameInClientAttributesITCase.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M001_UpdateClientNameInClientAttributes.*;
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.Map;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M001_UpdateClientNameInClientAttributesITCase {
+
+	private static final Document OLD_CLIENT_NAME_VORGANG = RenameTestFactory.createVorgangWithClientAttributes(OLD_CLIENT_NAME);
+
+	private final M001_UpdateClientNameInClientAttributes migration = new M001_UpdateClientNameInClientAttributes();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoTemplate template;
+
+	@BeforeEach
+	public void init() {
+		dbTestUtils.dropVorgangCollection();
+	}
+
+	@DisplayName("Do migration")
+	@Nested
+	class TestDoMigration {
+
+		@BeforeEach
+		public void init() {
+			dbTestUtils.saveVorgang(OLD_CLIENT_NAME_VORGANG);
+		}
+
+		@Test
+		void shouldUpdateClientName() {
+			migration.doMigration(template);
+
+			var vorgaenge = dbTestUtils.findVorgang(new Query());
+
+			assertThat(vorgaenge).hasSize(1);
+			var vorgangClientAttributes = (Document) vorgaenge.get(0).get(RenameUtil.CLIENT_ATTRIBUTES_KEY);
+			assertThat(vorgangClientAttributes).hasSize(1).containsKey(NEW_CLIENT_NAME);
+		}
+
+		@Test
+		void shouldKeeptClientAttributesData() {
+			migration.doMigration(template);
+
+			var vorgaenge = dbTestUtils.findVorgang(new Query());
+
+			assertThat(vorgaenge).hasSize(1);
+			var clientAttribute = getClientAttribute(vorgaenge.get(0), RenameTestFactory.DUMMY_ATTRIBUTE_NAME);
+			assertThat(clientAttribute).containsExactly(
+					Map.entry(RenameTestFactory.CLIENT_ATTRIBUTE_ACCESS_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_ACCESS_VALUE),
+					Map.entry(RenameTestFactory.CLIENT_ATTRIBUTE_VALUE_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_VALUE_VALUE),
+					Map.entry(RenameTestFactory.CLIENT_ATTRIBUTE_CLASS_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_CLASS_VALUE));
+		}
+
+		private Document getClientAttribute(Document vorgang, String name) {
+			var vorgangClientAttributes = (Document) vorgang.get(RenameUtil.CLIENT_ATTRIBUTES_KEY);
+			var clientAttributeByClientName = (Document) vorgangClientAttributes.get(NEW_CLIENT_NAME);
+			return (Document) clientAttributeByClientName.get(name);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M002_UpdateClientNameInGridFsITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M002_UpdateClientNameInGridFsITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..557727c18fac06d2121e7ea1b34ac105166ec81e
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M002_UpdateClientNameInGridFsITCase.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M002_UpdateClientNameInGridFs.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M002_UpdateClientNameInGridFsITCase {
+
+	private static final Document OLD_CLIENT_NAME_GRID_FS_FILE = RenameTestFactory.createGridFsFile(OLD_CLIENT_NAME);
+
+	private final M002_UpdateClientNameInGridFs migration = new M002_UpdateClientNameInGridFs();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoOperations db;
+
+	@BeforeEach
+	public void init() {
+		dbTestUtils.dropGridFsFilesCollection();
+	}
+
+	@DisplayName("Do migration")
+	@Nested
+	class TestDoMigration {
+
+		@BeforeEach
+		void init() {
+			dbTestUtils.saveGridFsFile(OLD_CLIENT_NAME_GRID_FS_FILE);
+		}
+
+		@Test
+		void shouldUpdateClientInMetadata() {
+			migration.doMigration(db);
+
+			var metadata = (Document) MapUtils.getObject(getGridFsFile(), RenameUtil.METADATA_KEY);
+			assertThat(metadata).contains(entry(RenameUtil.CLIENT_KEY, NEW_CLIENT_NAME));
+		}
+
+		@Test
+		void shouldUpdateClientInFilename() {
+			migration.doMigration(db);
+
+			var filename = MapUtils.getString(getGridFsFile(), RenameUtil.FILENAME_KEY);
+			var expectedFilename = StringUtils.replace(RenameTestFactory.FILE_NAME_VALUE, OLD_CLIENT_NAME, NEW_CLIENT_NAME);
+			assertThat(filename).isEqualTo(expectedFilename);
+		}
+
+		@Test
+		void shouldKeepBaseData() {
+			migration.doMigration(db);
+
+			var gridFsFile = getGridFsFile();
+			assertThat(gridFsFile).contains(entry(RenameTestFactory.LENGTH_KEY, RenameTestFactory.LENGTH_VALUE))
+					.contains(entry(RenameTestFactory.CHUNK_SIZE_KEY, RenameTestFactory.CHUNK_SIZE_VALUE))
+					.contains(entry(RenameTestFactory.UPLOAD_DATE_KEY, RenameTestFactory.UPLOAD_DATE_VALUE));
+		}
+
+		@Test
+		void shouldKeepMetadata() {
+			migration.doMigration(db);
+
+			var metadata = (Document) MapUtils.getObject(getGridFsFile(), RenameUtil.METADATA_KEY);
+			assertThat(metadata).contains(entry(RenameTestFactory.VORGANG_ID_KEY, RenameTestFactory.VORGANG_ID_VALUE))
+					.contains(entry(RenameTestFactory.FIELD_NAME_KEY, RenameTestFactory.FIELD_NAME_VALUE))
+					.contains(entry(RenameTestFactory.CONTENT_TYPE_KEY, RenameTestFactory.CONTENT_TYPE_VALUE))
+					.contains(entry(RenameTestFactory.NAME_KEY, RenameTestFactory.NAME_VALUE));
+		}
+
+		private Document getGridFsFile() {
+			return dbTestUtils.findGridFsFile(new Query()).get(0);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M003_UpdateClientNameInVorgangAttachedItemITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M003_UpdateClientNameInVorgangAttachedItemITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..df1f69e10ee8b8a7cf8edc036dea81e06ea95bb4
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M003_UpdateClientNameInVorgangAttachedItemITCase.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M003_UpdateClientNameInVorgangAttachedItem.*;
+import static de.ozgcloud.vorgang.common.migration.RenameTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M003_UpdateClientNameInVorgangAttachedItemITCase {
+
+	private static final Document OLD_CLIENT_NAME_VORGANG_ATTACHED_ITEM = RenameTestFactory.createVorgangAttachedItem(OLD_CLIENT_NAME);
+
+	private final M003_UpdateClientNameInVorgangAttachedItem migration = new M003_UpdateClientNameInVorgangAttachedItem();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoTemplate template;
+
+	@BeforeEach
+	public void init() {
+		dbTestUtils.dropVorgangAttachedItemCollection();
+	}
+
+	@DisplayName("Do migration")
+	@Nested
+	class TestDoMigration {
+
+		@BeforeEach
+		void init() {
+			dbTestUtils.saveVorgangAttachedItem(OLD_CLIENT_NAME_VORGANG_ATTACHED_ITEM);
+		}
+
+		@Test
+		void shouldUpdateClientName() {
+			migration.doMigration(template);
+
+			assertThat(getVorgangAttachedItem()).containsEntry(RenameUtil.CLIENT_KEY, NEW_CLIENT_NAME);
+		}
+
+		@Test
+		void shouldKeeptOtherAttributes() {
+			migration.doMigration(template);
+
+			assertThat(getVorgangAttachedItem())
+					.containsEntry(ITEM_NAME_KEY, ITEM_NAME_VALUE)
+					.containsKey(ITEM_KEY);
+		}
+
+		@Test
+		void shouldKeepItemAttributes() {
+			migration.doMigration(template);
+
+			var item = (Document) getVorgangAttachedItem().get(ITEM_KEY);
+			assertThat(item).containsExactly(entry(ITEM_ATTRIBUTE_KEY, ITEM_ATTRIBUTE_VALUE));
+		}
+
+		private Document getVorgangAttachedItem() {
+			return dbTestUtils.findVorgangAttachedItem(new Query()).get(0);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItemITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItemITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc57fbe2505bf636619ffe3d62db7e3ce58f8baa
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItemITCase.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItem.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItemITCase {
+
+	private static final Document OLD_CLIENT_NAME_VORGANG_ATTACHED_ITEM = RenameTestFactory.createVorgangAttachedItem(OLD_CLIENT_NAME);
+
+	private final M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItem migration = new M004_UpdateNachrichtenManagerClientNameInVorgangAttachedItem();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoTemplate template;
+
+	@BeforeEach
+	public void init() {
+		dbTestUtils.dropVorgangAttachedItemCollection();
+	}
+
+	@DisplayName("Do migration")
+	@Nested
+	class TestDoMigration {
+
+		@BeforeEach
+		void init() {
+			dbTestUtils.saveVorgangAttachedItem(OLD_CLIENT_NAME_VORGANG_ATTACHED_ITEM);
+		}
+
+		@Test
+		void shouldUpdateClientName() {
+			migration.doMigration(template);
+
+			assertThat(getVorgangAttachedItem()).containsEntry(RenameUtil.CLIENT_KEY, NEW_CLIENT_NAME);
+		}
+
+		@Test
+		void shouldKeeptOtherAttributes() {
+			migration.doMigration(template);
+
+			assertThat(getVorgangAttachedItem())
+					.containsEntry(RenameTestFactory.ITEM_NAME_KEY, RenameTestFactory.ITEM_NAME_VALUE)
+					.containsKey(RenameTestFactory.ITEM_KEY);
+		}
+
+		@Test
+		void shouldKeepItemAttributes() {
+			migration.doMigration(template);
+
+			var item = (Document) getVorgangAttachedItem().get(RenameTestFactory.ITEM_KEY);
+			assertThat(item).containsExactly(entry(RenameTestFactory.ITEM_ATTRIBUTE_KEY, RenameTestFactory.ITEM_ATTRIBUTE_VALUE));
+		}
+
+		private Document getVorgangAttachedItem() {
+			return dbTestUtils.findVorgangAttachedItem(new Query()).get(0);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M005_UpdateNachrichtenManagerClientNameInClientAttributesITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M005_UpdateNachrichtenManagerClientNameInClientAttributesITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..b27f6447fb0aa40e7ac066cf31cff971ab96b4b9
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M005_UpdateNachrichtenManagerClientNameInClientAttributesITCase.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M005_UpdateNachrichtenManagerClientNameInClientAttributes.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M005_UpdateNachrichtenManagerClientNameInClientAttributesITCase {
+
+	private final static Document OLD_CLIENT_NAME_VORGANG = RenameTestFactory.createVorgangWithClientAttributes(OLD_CLIENT_NAME);
+
+	private final M005_UpdateNachrichtenManagerClientNameInClientAttributes migration = new M005_UpdateNachrichtenManagerClientNameInClientAttributes();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoTemplate template;
+
+	@BeforeEach
+	public void init() {
+		dbTestUtils.dropVorgangCollection();
+	}
+
+	@DisplayName("Do migration")
+	@Nested
+	class TestDoMigration {
+
+		@BeforeEach
+		public void init() {
+			dbTestUtils.saveVorgang(OLD_CLIENT_NAME_VORGANG);
+		}
+
+		@Test
+		void shouldUpdateClientName() {
+			migration.doMigration(template);
+
+			var vorgaenge = dbTestUtils.findVorgang(new Query());
+
+			assertThat(vorgaenge).hasSize(1);
+			var vorgangClientAttributes = (Document) vorgaenge.get(0).get(RenameUtil.CLIENT_ATTRIBUTES_KEY);
+			assertThat(vorgangClientAttributes).hasSize(1).containsKey(NEW_CLIENT_NAME);
+		}
+
+		@Test
+		void shouldKeeptClientAttributesData() {
+			migration.doMigration(template);
+
+			var vorgaenge = dbTestUtils.findVorgang(new Query());
+
+			assertThat(vorgaenge).hasSize(1);
+			var clientAttribute = getClientAttribute(vorgaenge.get(0), RenameTestFactory.DUMMY_ATTRIBUTE_NAME);
+			assertThat(clientAttribute).containsExactly(
+					entry(RenameTestFactory.CLIENT_ATTRIBUTE_ACCESS_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_ACCESS_VALUE),
+					entry(RenameTestFactory.CLIENT_ATTRIBUTE_VALUE_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_VALUE_VALUE),
+					entry(RenameTestFactory.CLIENT_ATTRIBUTE_CLASS_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_CLASS_VALUE));
+		}
+
+		private Document getClientAttribute(Document vorgang, String name) {
+			var vorgangClientAttributes = (Document) vorgang.get(RenameUtil.CLIENT_ATTRIBUTES_KEY);
+			var clientAttributeByClientName = (Document) vorgangClientAttributes.get(NEW_CLIENT_NAME);
+			return (Document) clientAttributeByClientName.get(name);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M006_UpdateMailServiceClientNameInVorgangAttachedItemITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M006_UpdateMailServiceClientNameInVorgangAttachedItemITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..71e4c9874e7582e543d6fbf1e8a3f401c9361f4b
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M006_UpdateMailServiceClientNameInVorgangAttachedItemITCase.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M006_UpdateMailServiceClientNameInVorgangAttachedItem.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M006_UpdateMailServiceClientNameInVorgangAttachedItemITCase {
+
+	private static final Document OLD_CLIENT_NAME_VORGANG_ATTACHED_ITEM = RenameTestFactory.createVorgangAttachedItem(OLD_CLIENT_NAME);
+
+	private final M006_UpdateMailServiceClientNameInVorgangAttachedItem migration = new M006_UpdateMailServiceClientNameInVorgangAttachedItem();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoTemplate template;
+
+	@BeforeEach
+	public void init() {
+		dbTestUtils.dropVorgangAttachedItemCollection();
+	}
+
+	@DisplayName("Do migration")
+	@Nested
+	class TestDoMigration {
+
+		@BeforeEach
+		void init() {
+			dbTestUtils.saveVorgangAttachedItem(OLD_CLIENT_NAME_VORGANG_ATTACHED_ITEM);
+		}
+
+		@Test
+		void shouldUpdateClientName() {
+			migration.doMigration(template);
+
+			assertThat(getVorgangAttachedItem()).containsEntry(RenameUtil.CLIENT_KEY, NEW_CLIENT_NAME);
+		}
+
+		@Test
+		void shouldKeeptOtherAttributes() {
+			migration.doMigration(template);
+
+			assertThat(getVorgangAttachedItem())
+					.containsEntry(RenameTestFactory.ITEM_NAME_KEY, RenameTestFactory.ITEM_NAME_VALUE)
+					.containsKey(RenameTestFactory.ITEM_KEY);
+		}
+
+		@Test
+		void shouldKeepItemAttributes() {
+			migration.doMigration(template);
+
+			var item = (Document) getVorgangAttachedItem().get(RenameTestFactory.ITEM_KEY);
+			assertThat(item).containsExactly(entry(RenameTestFactory.ITEM_ATTRIBUTE_KEY, RenameTestFactory.ITEM_ATTRIBUTE_VALUE));
+		}
+
+		private Document getVorgangAttachedItem() {
+			return dbTestUtils.findVorgangAttachedItem(new Query()).get(0);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M007_UpdateMailServiceClientNameInClientAttributesITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M007_UpdateMailServiceClientNameInClientAttributesITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d4547f1ca635393d2c37c9884b158b3b25570cb
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M007_UpdateMailServiceClientNameInClientAttributesITCase.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M007_UpdateMailServiceClientNameInClientAttributes.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M007_UpdateMailServiceClientNameInClientAttributesITCase {
+
+	private final static Document OLD_CLIENT_NAME_VORGANG = RenameTestFactory.createVorgangWithClientAttributes(OLD_CLIENT_NAME);
+
+	private final M007_UpdateMailServiceClientNameInClientAttributes migration = new M007_UpdateMailServiceClientNameInClientAttributes();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoTemplate template;
+
+	@BeforeEach
+	public void init() {
+		dbTestUtils.dropVorgangCollection();
+	}
+
+	@DisplayName("Do migration")
+	@Nested
+	class TestDoMigration {
+
+		@BeforeEach
+		public void init() {
+			dbTestUtils.saveVorgang(OLD_CLIENT_NAME_VORGANG);
+		}
+
+		@Test
+		void shouldUpdateClientName() {
+			migration.doMigration(template);
+
+			var vorgaenge = dbTestUtils.findVorgang(new Query());
+
+			assertThat(vorgaenge).hasSize(1);
+			var vorgangClientAttributes = (Document) vorgaenge.get(0).get(RenameUtil.CLIENT_ATTRIBUTES_KEY);
+			assertThat(vorgangClientAttributes).hasSize(1).containsKey(NEW_CLIENT_NAME);
+		}
+
+		@Test
+		void shouldKeeptClientAttributesData() {
+			migration.doMigration(template);
+
+			var vorgaenge = dbTestUtils.findVorgang(new Query());
+
+			assertThat(vorgaenge).hasSize(1);
+			var clientAttribute = getClientAttribute(vorgaenge.get(0), RenameTestFactory.DUMMY_ATTRIBUTE_NAME);
+			assertThat(clientAttribute).containsExactly(
+					entry(RenameTestFactory.CLIENT_ATTRIBUTE_ACCESS_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_ACCESS_VALUE),
+					entry(RenameTestFactory.CLIENT_ATTRIBUTE_VALUE_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_VALUE_VALUE),
+					entry(RenameTestFactory.CLIENT_ATTRIBUTE_CLASS_KEY, RenameTestFactory.CLIENT_ATTRIBUTE_CLASS_VALUE));
+		}
+
+		private Document getClientAttribute(Document vorgang, String name) {
+			var vorgangClientAttributes = (Document) vorgang.get(RenameUtil.CLIENT_ATTRIBUTES_KEY);
+			var clientAttributeByClientName = (Document) vorgangClientAttributes.get(NEW_CLIENT_NAME);
+			return (Document) clientAttributeByClientName.get(name);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M008_UpdateMailServiceClientNameInGridFsITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M008_UpdateMailServiceClientNameInGridFsITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..49371bea43d87b6ffac535474ccc15e2572b79f6
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/M008_UpdateMailServiceClientNameInGridFsITCase.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M008_UpdateMailServiceClientNameInGridFs.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class M008_UpdateMailServiceClientNameInGridFsITCase {
+
+	private static final Document OLD_CLIENT_NAME_GRID_FS_FILE = RenameTestFactory.createGridFsFile(OLD_CLIENT_NAME);
+
+	private final M008_UpdateMailServiceClientNameInGridFs migration = new M008_UpdateMailServiceClientNameInGridFs();
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+	@Autowired
+	private MongoOperations db;
+
+	@BeforeEach
+	public void init() {
+		dbTestUtils.dropGridFsFilesCollection();
+	}
+
+	@DisplayName("Do migration")
+	@Nested
+	class TestDoMigration {
+
+		@BeforeEach
+		void init() {
+			dbTestUtils.saveGridFsFile(OLD_CLIENT_NAME_GRID_FS_FILE);
+		}
+
+		@Test
+		void shouldUpdateClientInMetadata() {
+			migration.doMigration(db);
+
+			var metadata = (Document) MapUtils.getObject(getGridFsFile(), RenameUtil.METADATA_KEY);
+			assertThat(metadata).contains(entry(RenameUtil.CLIENT_KEY, NEW_CLIENT_NAME));
+		}
+
+		@Test
+		void shouldUpdateClientInFilename() {
+			migration.doMigration(db);
+
+			var filename = MapUtils.getString(getGridFsFile(), RenameUtil.FILENAME_KEY);
+			var expectedFilename = StringUtils.replace(RenameTestFactory.FILE_NAME_VALUE, OLD_CLIENT_NAME, NEW_CLIENT_NAME);
+			assertThat(filename).isEqualTo(expectedFilename);
+		}
+
+		@Test
+		void shouldKeepBaseData() {
+			migration.doMigration(db);
+
+			var gridFsFile = getGridFsFile();
+			assertThat(gridFsFile).contains(entry(RenameTestFactory.LENGTH_KEY, RenameTestFactory.LENGTH_VALUE))
+					.contains(entry(RenameTestFactory.CHUNK_SIZE_KEY, RenameTestFactory.CHUNK_SIZE_VALUE))
+					.contains(entry(RenameTestFactory.UPLOAD_DATE_KEY, RenameTestFactory.UPLOAD_DATE_VALUE));
+		}
+
+		@Test
+		void shouldKeepMetadata() {
+			migration.doMigration(db);
+
+			var metadata = (Document) MapUtils.getObject(getGridFsFile(), RenameUtil.METADATA_KEY);
+			assertThat(metadata).contains(entry(RenameTestFactory.VORGANG_ID_KEY, RenameTestFactory.VORGANG_ID_VALUE))
+					.contains(entry(RenameTestFactory.FIELD_NAME_KEY, RenameTestFactory.FIELD_NAME_VALUE))
+					.contains(entry(RenameTestFactory.CONTENT_TYPE_KEY, RenameTestFactory.CONTENT_TYPE_VALUE))
+					.contains(entry(RenameTestFactory.NAME_KEY, RenameTestFactory.NAME_VALUE));
+		}
+
+		private Document getGridFsFile() {
+			return dbTestUtils.findGridFsFile(new Query()).get(0);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/MigrationDbTestUtils.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/MigrationDbTestUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc716e76c35f45368a2dfbef0b60d4b02d53c670
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/MigrationDbTestUtils.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import java.util.List;
+
+import org.bson.Document;
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Component;
+
+import com.mongodb.client.FindIterable;
+
+@Component
+class MigrationDbTestUtils {
+
+	public static final String COMMAND_COLLECTION = "command";
+	public static final String GRID_FS_FILE_COLLECTION = "fs.files";
+	public static final String VORGANG_COLLECTION = "vorgang";
+	public static final String VORGANG_ATTACHED_ITEM_COLLECTION = "vorgangAttachedItem";
+
+	@Autowired
+	private MongoTemplate template;
+	@Autowired
+	private MongoOperations operations;
+
+	// Command
+	public Document saveCommand(Document doc) {
+		return template.save(doc, COMMAND_COLLECTION);
+	}
+
+	public Document getCommand(ObjectId id) {
+		return template.findById(id, Document.class, COMMAND_COLLECTION);
+	}
+
+	public void dropCommandCollection() {
+		template.dropCollection(COMMAND_COLLECTION);
+	}
+
+	// GridFs
+	public Document saveGridFsFile(Document doc) {
+		return template.save(doc, GRID_FS_FILE_COLLECTION);
+	}
+
+	public List<Document> findGridFsFile(Query query) {
+		return template.find(query, Document.class, GRID_FS_FILE_COLLECTION);
+	}
+
+	public void dropGridFsFilesCollection() {
+		template.dropCollection(GRID_FS_FILE_COLLECTION);
+	}
+
+	public FindIterable<Document> findGridFsFile(Document doc) {
+		return operations.getCollection(GRID_FS_FILE_COLLECTION).find(doc);
+	}
+
+	// Vorgang
+	public Document saveVorgang(Document doc) {
+		return template.save(doc, VORGANG_COLLECTION);
+	}
+
+	public Document getVorgang(ObjectId id) {
+		return template.findById(id, Document.class, VORGANG_COLLECTION);
+	}
+
+	public List<Document> findVorgang(Query query) {
+		return template.find(query, Document.class, VORGANG_COLLECTION);
+	}
+
+	public void dropVorgangCollection() {
+		template.dropCollection(VORGANG_COLLECTION);
+	}
+
+	// VorgangAttachedItem
+	public Document saveVorgangAttachedItem(Document doc) {
+		return template.save(doc, VORGANG_ATTACHED_ITEM_COLLECTION);
+	}
+
+	public Document getVorgangAttachedItem(ObjectId id) {
+		return template.findById(id, Document.class, VORGANG_ATTACHED_ITEM_COLLECTION);
+	}
+
+	public List<Document> findVorgangAttachedItem(Query query) {
+		return template.find(query, Document.class, VORGANG_ATTACHED_ITEM_COLLECTION);
+	}
+
+	public void dropVorgangAttachedItemCollection() {
+		template.dropCollection(VORGANG_ATTACHED_ITEM_COLLECTION);
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationTestUtils.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/MigrationTestUtils.java
similarity index 93%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationTestUtils.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/MigrationTestUtils.java
index 31906af8d66ffd659115fc6faa3d581ee7fcdbcf..db5fa7f1416cc86f7d481febca8f099c3dad9b24 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/migration/MigrationTestUtils.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/MigrationTestUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.migration;
+package de.ozgcloud.vorgang.common.migration;
 
 import java.io.InputStream;
 import java.util.List;
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/RenameTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/RenameTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ad163f0600e4f649ad4a6a103e530d51f2f595ed
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/RenameTestFactory.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static de.ozgcloud.vorgang.common.migration.M002_UpdateClientNameInGridFs.*;
+
+import java.util.UUID;
+
+import org.apache.http.entity.ContentType;
+import org.bson.Document;
+import org.bson.types.ObjectId;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+public class RenameTestFactory {
+
+	// VorgangAttachedItem
+	public static final String ITEM_NAME_KEY = "itemName";
+	public static final String ITEM_NAME_VALUE = "DummyItemName";
+	public static final String ITEM_KEY = "item";
+	public static final String ITEM_ATTRIBUTE_KEY = "DummyKey";
+	public static final String ITEM_ATTRIBUTE_VALUE = "DummyValue";
+
+	public static Document createVorgangAttachedItem(String clientName) {
+		var vorgangAttachedItem = new Document();
+		vorgangAttachedItem.put(RenameUtil.CLIENT_KEY, clientName);
+		vorgangAttachedItem.put(ITEM_NAME_KEY, ITEM_NAME_VALUE);
+		vorgangAttachedItem.put(ITEM_KEY, createItem());
+
+		return vorgangAttachedItem;
+	}
+
+	private static Document createItem() {
+		var item = new Document();
+		item.put(ITEM_ATTRIBUTE_KEY, ITEM_ATTRIBUTE_VALUE);
+
+		return item;
+	}
+
+	// GridFsFiles
+	public static final String LENGTH_KEY = "length";
+	public static final long LENGTH_VALUE = 2L;
+
+	public static final String CHUNK_SIZE_KEY = "chunkSize";
+	public static final int CHUNK_SIZE_VALUE = 261120;
+
+	public static final String UPLOAD_DATE_KEY = "uploadDate";
+	public static final String UPLOAD_DATE_VALUE = "2023-03-28T07:13:14.821Z";
+
+	public static final String VORGANG_ID_KEY = "vorgangId";
+	public static final String VORGANG_ID_VALUE = UUID.randomUUID().toString();
+
+	public static final String FIELD_NAME_KEY = "fieldName";
+	public static final String FIELD_NAME_VALUE = LoremIpsum.getInstance().getFirstName();
+
+	public static final String CONTENT_TYPE_KEY = "contentType";
+	public static final String CONTENT_TYPE_VALUE = ContentType.APPLICATION_JSON.toString();
+
+	public static final String NAME_KEY = "name";
+	public static final String NAME_VALUE = LoremIpsum.getInstance().getFirstName();
+
+	public static final String FILE_NAME_ID_VALUE = new ObjectId().toHexString();
+	public static final String FILE_NAME_VALUE = String.format("%s/%s/%s/%s", FILE_NAME_ID_VALUE, OLD_CLIENT_NAME,
+			FIELD_NAME_VALUE, NAME_VALUE);
+
+	public static Document createGridFsFile(String clientName) {
+		var file = new Document();
+		file.put(RenameUtil.METADATA_KEY, createGridFsFileMetadata(clientName));
+		file.put(RenameUtil.FILENAME_KEY, FILE_NAME_VALUE);
+		file.put(LENGTH_KEY, LENGTH_VALUE);
+		file.put(CHUNK_SIZE_KEY, CHUNK_SIZE_VALUE);
+		file.put(UPLOAD_DATE_KEY, UPLOAD_DATE_VALUE);
+
+		return file;
+	}
+
+	private static Document createGridFsFileMetadata(String clientName) {
+		var metadata = new Document();
+		metadata.put(VORGANG_ID_KEY, VORGANG_ID_VALUE);
+		metadata.put(RenameUtil.CLIENT_KEY, clientName);
+		metadata.put(FIELD_NAME_KEY, FIELD_NAME_VALUE);
+		metadata.put(CONTENT_TYPE_KEY, CONTENT_TYPE_VALUE);
+		metadata.put(NAME_KEY, NAME_VALUE);
+
+		return metadata;
+	}
+
+	// Vorgang ClientAttributes
+	public final static String DUMMY_ATTRIBUTE_NAME = "dummyAttributeName";
+
+	public final static String CLIENT_ATTRIBUTE_ACCESS_KEY = "access";
+	public final static String CLIENT_ATTRIBUTE_ACCESS_VALUE = "READ_ONLY";
+	public final static String CLIENT_ATTRIBUTE_VALUE_KEY = "value";
+	public final static String CLIENT_ATTRIBUTE_VALUE_VALUE = "2023-11-06";
+	public final static String CLIENT_ATTRIBUTE_CLASS_VALUE = "_class";
+	public final static String CLIENT_ATTRIBUTE_CLASS_KEY = "ClientAttribute";
+
+	public static Document createVorgangWithClientAttributes(String clientName) {
+		var vorgang = new Document();
+		vorgang.put(RenameUtil.CLIENT_ATTRIBUTES_KEY, createClientAttribute(clientName));
+		return vorgang;
+	}
+
+	private static Document createClientAttribute(String clientName) {
+		var clientAttribute = new Document();
+		clientAttribute.put(clientName, createClientAttributeByClient());
+		return clientAttribute;
+	}
+
+	private static Document createClientAttributeByClient() {
+		var attributeValue = new Document();
+		attributeValue.put(CLIENT_ATTRIBUTE_ACCESS_KEY, CLIENT_ATTRIBUTE_ACCESS_VALUE);
+		attributeValue.put(CLIENT_ATTRIBUTE_VALUE_KEY, CLIENT_ATTRIBUTE_VALUE_VALUE);
+		attributeValue.put(CLIENT_ATTRIBUTE_CLASS_KEY, CLIENT_ATTRIBUTE_CLASS_VALUE);
+
+		var clientAttributeByClient = new Document();
+		clientAttributeByClient.put(DUMMY_ATTRIBUTE_NAME, attributeValue);
+		return clientAttributeByClient;
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/RenameUtilITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/RenameUtilITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a80e905a30e1c6c446595888bb7b070d3c90bcc
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/migration/RenameUtilITCase.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.migration;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import de.ozgcloud.common.test.DataITCase;
+
+@DataITCase
+class RenameUtilITCase {
+
+	private static final String OLD_CLIENT_NAME = "OldClientName";
+	private static final String NEW_CLIENT_NAME = "NewClientName";
+
+	@Autowired
+	private MigrationDbTestUtils dbTestUtils;
+
+	@DisplayName("VorgangAttachedItem")
+	@Nested
+	class TestVorgangAttachedItem {
+
+		private static final Document OLD_CLIENT_NAME_VORGANG_ATTACHED_ITEM = RenameTestFactory.createVorgangAttachedItem(OLD_CLIENT_NAME);
+		private static final Document NEW_CLIENT_NAME_VORGANG_ATTACHED_ITEM = RenameTestFactory.createVorgangAttachedItem(NEW_CLIENT_NAME);
+
+		@BeforeEach
+		public void init() {
+			dbTestUtils.dropVorgangAttachedItemCollection();
+		}
+
+		@DisplayName("Create find query")
+		@Nested
+		class TestCreateFindQuery {
+
+			@Test
+			void shouldFindWithOldClientName() {
+				dbTestUtils.saveVorgangAttachedItem(OLD_CLIENT_NAME_VORGANG_ATTACHED_ITEM);
+
+				var vorgang = dbTestUtils.findVorgangAttachedItem(RenameUtil.createFindVorgangAttachedItemQuery(OLD_CLIENT_NAME));
+
+				assertThat(vorgang).hasSize(1);
+			}
+
+			@Test
+			void shouldNOTFindWithOtherClientName() {
+				dbTestUtils.saveVorgangAttachedItem(NEW_CLIENT_NAME_VORGANG_ATTACHED_ITEM);
+
+				var vorgang = dbTestUtils.findVorgangAttachedItem(RenameUtil.createFindVorgangAttachedItemQuery(OLD_CLIENT_NAME));
+
+				assertThat(vorgang).isEmpty();
+			}
+		}
+	}
+
+	@DisplayName("GridFsFiles")
+	@Nested
+	class TestGridFsFiles {
+
+		private static final Document OLD_CLIENT_NAME_GRID_FS_FILE = RenameTestFactory.createGridFsFile(OLD_CLIENT_NAME);
+		private static final Document NEW_CLIENT_NAME_GRID_FS_FILE = RenameTestFactory.createGridFsFile(NEW_CLIENT_NAME);
+
+		@BeforeEach
+		public void init() {
+			dbTestUtils.dropGridFsFilesCollection();
+		}
+
+		@DisplayName("Create find query")
+		@Nested
+		class TestCreateFindQuery {
+
+			@Test
+			void shouldFindWithOldClientName() {
+				dbTestUtils.saveGridFsFile(OLD_CLIENT_NAME_GRID_FS_FILE);
+
+				var gridFsFiles = dbTestUtils.findGridFsFile(RenameUtil.createMetadataClientMatchingDocument(OLD_CLIENT_NAME));
+
+				assertThat(gridFsFiles).hasSize(1);
+			}
+
+			@Test
+			void shouldNOTFindWithOtherClientName() {
+				dbTestUtils.saveGridFsFile(NEW_CLIENT_NAME_GRID_FS_FILE);
+
+				var gridFsFiles = dbTestUtils.findGridFsFile(RenameUtil.createMetadataClientMatchingDocument(OLD_CLIENT_NAME));
+
+				assertThat(gridFsFiles).isEmpty();
+			}
+		}
+	}
+
+	@DisplayName("Vorgang ClientAttributes")
+	@Nested
+	class TestVorgangClientAttributes {
+
+		private static final Document OLD_CLIENT_NAME_VORGANG = RenameTestFactory.createVorgangWithClientAttributes(OLD_CLIENT_NAME);
+		private static final Document NEW_CLIENT_NAME_VORGANG = RenameTestFactory.createVorgangWithClientAttributes(NEW_CLIENT_NAME);
+
+		@BeforeEach
+		public void init() {
+			dbTestUtils.dropVorgangCollection();
+		}
+
+		@DisplayName("Create find query")
+		@Nested
+		class TestCreateFindQuery {
+
+			@Test
+			void shouldFindWithOldClientName() {
+				dbTestUtils.saveVorgang(OLD_CLIENT_NAME_VORGANG);
+
+				var vorgang = dbTestUtils.findVorgang(RenameUtil.createFindVorgangClientAttributesQuery(OLD_CLIENT_NAME));
+
+				assertThat(vorgang).hasSize(1);
+			}
+
+			@Test
+			void shouldNOTFindWithOtherClientName() {
+				dbTestUtils.saveVorgang(NEW_CLIENT_NAME_VORGANG);
+
+				var vorgang = dbTestUtils.findVorgang(RenameUtil.createFindVorgangClientAttributesQuery(OLD_CLIENT_NAME));
+
+				assertThat(vorgang).isEmpty();
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/FieldPathProcessorTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/FieldPathProcessorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb2818d9681bb8ab94222818f72d16626288c5ee
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/FieldPathProcessorTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import de.ozgcloud.vorgang.common.operator.FieldPathProcessor;
+import de.ozgcloud.vorgang.common.operator.UnsupportedEntityException;
+
+class FieldPathProcessorTest {
+
+	@Nested
+	class TestProcessToCriteriaPath {
+
+		private final static String VORGANG_FIELD_PATH = "Vorgang.long.path";
+		private final static String CLIENT_ATTRIBUTE_FIELD_PATH = "ClientAttribute.clientName.frist";
+
+		@Nested
+		class GetCriteriaEntity {
+			@Test
+			void shouldReturnVorgang() {
+				var entity = FieldPathProcessor.getCriteriaEntity(VORGANG_FIELD_PATH);
+
+				assertThat(entity).isEqualTo(FieldPathProcessor.CRITERIA_PATH_VORGANG);
+			}
+
+			@Test
+			void shouldThrowExcptionForUnkownEntity() {
+				assertThatThrownBy(() -> FieldPathProcessor.getCriteriaEntity("stupid.path"))
+						.isInstanceOf(UnsupportedEntityException.class);
+
+			}
+		}
+
+		@Nested
+		class GetPath {
+
+			@Test
+			void shouldReturnPathWithoutEntity() {
+				var path = FieldPathProcessor.getPath(VORGANG_FIELD_PATH);
+
+				assertThat(path).isEqualTo("long.path");
+			}
+
+			@Test
+			void shouldAddValueSuffix() {
+				var path = FieldPathProcessor.getPath(CLIENT_ATTRIBUTE_FIELD_PATH);
+
+				assertThat(path).endsWith(".value");
+			}
+		}
+
+		@Test
+		void shouldReturnCriteriaWithoutEntity() {
+			var criteria = FieldPathProcessor.processToCriteriaPath(VORGANG_FIELD_PATH);
+
+			assertThat(criteria).isEqualTo("long.path");
+		}
+
+		@Test
+		void shouldReturnCriteriaWithEntity() {
+			var criteria = FieldPathProcessor.processToCriteriaPath(CLIENT_ATTRIBUTE_FIELD_PATH);
+
+			assertThat(criteria).isEqualTo("clientAttributes.clientName.frist.value");
+		}
+	}
+
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperandFunctionParserTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperandFunctionParserTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d7e1fbfdddcc1d2b30d2217232ddea6668c1d7a
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperandFunctionParserTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import java.time.LocalDate;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class OperandFunctionParserTest {
+
+	private final OperandFunctionParser operandFunctionParser = new OperandFunctionParser();
+
+	@Test
+	void shouldMapTodayFunction() {
+		var date = operandFunctionParser.parse("today()");
+
+		Assertions.assertThat(date).isEqualTo(LocalDate.now().toString());
+	}
+
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperatorBuilderTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperatorBuilderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6492d0273aca1130c6059fb5ef4c830b7c1c2f7
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperatorBuilderTest.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.common.operator.EqualOperator;
+import de.ozgcloud.vorgang.common.operator.GreaterThenOperator;
+import de.ozgcloud.vorgang.common.operator.GreaterThenOrEqualOperator;
+import de.ozgcloud.vorgang.common.operator.LessThenOperator;
+import de.ozgcloud.vorgang.common.operator.LessThenOrEqualOperator;
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+import de.ozgcloud.vorgang.common.operator.UnequalOperator;
+import de.ozgcloud.vorgang.statistic.VorgangStatisticBadRequestException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+
+class OperatorBuilderTest {
+
+	private static final String QUERY_PATH = "Vorgang.fieldPath";
+	private static final String FIELD_PATH = "fieldPath";
+	private static final String OPERAND = "operand";
+
+	@Test
+	void shouldSetFieldSet() {
+	var builder = OperatorBuilder.from(GrpcQueryOperator.UNEQUAL).fieldPath(QUERY_PATH);
+
+		assertThat(builder).extracting("fieldPath").isEqualTo(FIELD_PATH);
+	}
+
+	@Test
+	void shouldSetOperator() {
+		var builder = OperatorBuilder.from(GrpcQueryOperator.UNEQUAL);
+
+		assertThat(builder).extracting("grpcOperator").isEqualTo(GrpcQueryOperator.UNEQUAL);
+	}
+
+	@Test
+	void shouldSetOperand() {
+		var builder = OperatorBuilder.from(GrpcQueryOperator.UNEQUAL).operand(OPERAND);
+
+		assertThat(builder).extracting("operand").isEqualTo(OPERAND);
+	}
+
+	@Nested
+	@DisplayName("build operator")
+	class TestBuild {
+
+		@Test
+		void shouldBuildEqualOperator() {
+			var operator = buildOperator(GrpcQueryOperator.EQUAL);
+
+			assertThat(operator).isInstanceOf(EqualOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("operand").isEqualTo(OPERAND);
+		}
+
+		@Test
+		void shouldBuildIsEmptyOperator() {
+			var operator = buildOperator(GrpcQueryOperator.IS_EMPTY);
+
+			assertThat(operator).isInstanceOf(EqualOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("operand").isEqualTo(StringUtils.EMPTY);
+		}
+
+		@Test
+		void shouldBuildIsNullOperator() {
+			var operator = buildOperator(GrpcQueryOperator.IS_NULL);
+
+			assertThat(operator).isInstanceOf(EqualOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("operand").isNull();
+		}
+
+		@Test
+		void shouldBuildUnequalOperator() {
+			var operator = buildOperator(GrpcQueryOperator.UNEQUAL);
+
+			assertThat(operator).isInstanceOf(UnequalOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("operand").isEqualTo(OPERAND);
+		}
+
+		@Test
+		void shouldBuildGreaterThenOperator() {
+			var operator = buildOperator(GrpcQueryOperator.GREATER_THEN);
+
+			assertThat(operator).isInstanceOf(GreaterThenOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("operand").isEqualTo(OPERAND);
+		}
+
+		@Test
+		void shouldBuildGreaterThenOrEqualOperator() {
+			var operator = buildOperator(GrpcQueryOperator.GREATER_THEN_OR_EQUAL_TO);
+
+			assertThat(operator).isInstanceOf(GreaterThenOrEqualOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("operand").isEqualTo(OPERAND);
+		}
+
+		@Test
+		void shouldBuildLessThenOperator() {
+			var operator = buildOperator(GrpcQueryOperator.LESS_THEN);
+
+			assertThat(operator).isInstanceOf(LessThenOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("operand").isEqualTo(OPERAND);
+		}
+
+		@Test
+		void shouldBuildLessThenOrEqualOperator() {
+			var operator = buildOperator(GrpcQueryOperator.LESS_THEN_OR_EQUAL_TO);
+
+			assertThat(operator).isInstanceOf(LessThenOrEqualOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("operand").isEqualTo(OPERAND);
+		}
+
+		@Test
+		void shouldThrowExceptionWhenUnrecognized() {
+			assertThrows(VorgangStatisticBadRequestException.class, () -> buildOperator(GrpcQueryOperator.UNRECOGNIZED));
+		}
+
+		@Test
+		void shouldBuildExistsOperator() {
+			var operator = buildOperator(GrpcQueryOperator.EXISTS);
+
+			assertThat(operator).isInstanceOf(ExistsOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+		}
+
+		@Test
+		void shouldBuildNotExistsOperator() {
+			var operator = buildOperator(GrpcQueryOperator.NOT_EXIST);
+
+			assertThat(operator).isInstanceOf(ExistsOperator.class);
+			assertThat(operator).extracting("fieldPath").isEqualTo(FIELD_PATH);
+			assertThat(operator).extracting("negate").isEqualTo(true);
+		}
+
+		private Operator buildOperator(GrpcQueryOperator grpcOperator) {
+			return OperatorBuilder.from(grpcOperator).fieldPath(QUERY_PATH).operand(OPERAND).build();
+		}
+	}
+
+	@Nested
+	class TestParseOperand {
+
+		private OperatorBuilder operatorBuilder = spy(OperatorBuilder.from(GrpcQueryOperator.EQUAL).fieldPath(QUERY_PATH).operand(OPERAND));
+
+		@Test
+		void shouldReturnUnmodified() {
+			doReturn(null).when(operatorBuilder).getFieldClass();
+
+			var parsedOperand = operatorBuilder.getParsedOperand();
+
+			assertThat(parsedOperand).isEqualTo(OPERAND);
+		}
+
+		@Test
+		void shouldCallGetFieldClass() {
+			doReturn(String.class).when(operatorBuilder).getFieldClass();
+
+			operatorBuilder.getParsedOperand();
+
+			verify(operatorBuilder).getFieldClass();
+		}
+
+		@Test
+		void shouldCallParseValue() {
+			doReturn(ZonedDateTime.class).when(operatorBuilder).getFieldClass();
+			doReturn(OPERAND).when(operatorBuilder).parseValue(ZonedDateTime.class);
+
+			operatorBuilder.getParsedOperand();
+
+			verify(operatorBuilder).parseValue(ZonedDateTime.class);
+		}
+	}
+
+	@Nested
+	class TestGetFieldClass {
+
+		private OperatorBuilder operatorBuilder = OperatorBuilder.from(GrpcQueryOperator.EQUAL);
+
+		@Test
+		void shouldReturnNull() {
+			var fieldClass = operatorBuilder.getFieldClass();
+
+			assertThat(fieldClass).isNull();
+		}
+
+		@Test
+		void shouldReturnNullIfFieldPathIsBlank() {
+			operatorBuilder.fieldPath("Vorgang.");
+
+			var fieldClass = operatorBuilder.getFieldClass();
+
+			assertThat(fieldClass).isNull();
+		}
+
+		@Test
+		void shouldReturnRootClass() {
+			var fieldPath = "Vorgang.createdAt";
+			operatorBuilder.fieldPath(fieldPath);
+
+			var fieldClass = operatorBuilder.getFieldClass();
+
+			assertThat(fieldClass).isEqualTo(ZonedDateTime.class);
+		}
+
+		@Test
+		void shouldReturnNestedClass() {
+			operatorBuilder.fieldPath("Vorgang.eingangs.header.serviceKonto.type");
+
+			var fieldClass = operatorBuilder.getFieldClass();
+
+			assertThat(fieldClass).isEqualTo(String.class);
+		}
+
+		@Test
+		void shouldReturnNullWhenFieldNotExists() {
+			operatorBuilder.fieldPath("Vorgang.notExists");
+
+			var fieldClass = operatorBuilder.getFieldClass();
+
+			assertThat(fieldClass).isNull();
+		}
+	}
+
+	@Nested
+	class TestParseValue {
+
+		@Test
+		void shouldReturnZonedDateTime() {
+			var operatorBuilder = OperatorBuilder.from(GrpcQueryOperator.EQUAL).fieldPath(QUERY_PATH).operand("2024-01-01T00:00:00Z");
+
+			var parsedValue = operatorBuilder.parseValue(ZonedDateTime.class);
+
+			assertThat(parsedValue).isInstanceOf(ZonedDateTime.class);
+		}
+
+		@Test
+		void shouldReturnLocalDate() {
+			var operatorBuilder = OperatorBuilder.from(GrpcQueryOperator.EQUAL).fieldPath(QUERY_PATH).operand("2024-01-01");
+
+			var parsedValue = operatorBuilder.parseValue(LocalDate.class);
+
+			assertThat(parsedValue).isInstanceOf(LocalDate.class);
+		}
+
+		@Test
+		void shouldReturnLocalDateTime() {
+			var operatorBuilder = OperatorBuilder.from(GrpcQueryOperator.EQUAL).fieldPath(QUERY_PATH).operand("2024-01-01T00:00:00");
+
+			var parsedValue = operatorBuilder.parseValue(LocalDateTime.class);
+
+			assertThat(parsedValue).isInstanceOf(LocalDateTime.class);
+		}
+
+		@Test
+		void shouldReturnUnmodified() {
+			var operatorBuilder = OperatorBuilder.from(GrpcQueryOperator.EQUAL).fieldPath(QUERY_PATH).operand(1);
+
+			var parsedValue = operatorBuilder.parseValue(String.class);
+
+			assertThat(parsedValue).isInstanceOf(Integer.class);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperatorTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperatorTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0996dbc352219e50372fcbf3018eb71a1c40b0ec
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/operator/OperatorTestFactory.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.operator;
+
+import de.ozgcloud.vorgang.common.operator.EqualOperator.EqualOperatorBuilder;
+import de.ozgcloud.vorgang.common.operator.LessThenOperator.LessThenOperatorBuilder;
+
+public class OperatorTestFactory {
+
+	public static final String PATH = "field";
+	public static final String STRING_VALUE = "value";
+	public static final int INT_VALUE = 1;
+
+	public static Operator createEqualOperator() {
+		return createEqualOperatorBuilder().build();
+	}
+
+	public static EqualOperatorBuilder createEqualOperatorBuilder() {
+		return EqualOperator.builder()
+				.fieldPath(PATH)
+				.operand(STRING_VALUE);
+	}
+
+	public static Operator createLessThenOperator() {
+		return createLessThenOperatorBuilder().build();
+	}
+
+	public static LessThenOperatorBuilder createLessThenOperatorBuilder() {
+		return LessThenOperator.builder()
+				.fieldPath(PATH)
+				.operand(INT_VALUE);
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/IndexedVorgangMapperTest.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/IndexedVorgangMapperTest.java
index 6d97a823c1f103d82921ac7f51b2bbff5388a8ae..428dc8aebf967f076d10b9d50bb5f6b8e6e47e0f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/IndexedVorgangMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,18 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.*;
 
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mapstruct.factory.Mappers;
 
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.vorgang.AntragstellerTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelleTestFactory;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.AntragstellerTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
 
 class IndexedVorgangMapperTest {
 	private IndexedVorgangMapper mapper = Mappers.getMapper(IndexedVorgangMapper.class);
@@ -162,4 +162,5 @@ class IndexedVorgangMapperTest {
 			assertThat(vorgang.getAssignedTo()).isEqualTo(IndexedVorgangTestFactory.ASSIGNED_TO);
 		}
 	}
+
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/IndexedVorgangTestFactory.java
similarity index 80%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/IndexedVorgangTestFactory.java
index facf47264002a2a74387cc503acad7bc9ba66b7b..3abecfca6f7d06c37995828ea7c3e633da441aa1 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/IndexedVorgangTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/IndexedVorgangTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,20 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import java.time.ZonedDateTime;
-import java.util.UUID;
 
-import de.itvsh.ozg.pluto.vorgang.AntragstellerTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelleTestFactory;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.AntragstellerTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
 
 class IndexedVorgangTestFactory {
 	static final String AKTENZEICHEN = VorgangTestFactory.AKTENZEICHEN;
 	static final String ANTRAGSTELLER_NAME = AntragstellerTestFactory.NACHNAME;
 	static final String ANTRAGSTELLER_VORNAME = AntragstellerTestFactory.VORNAME;
-	static final String ASSIGNED_TO = UUID.randomUUID().toString();
+	static final String ASSIGNED_TO = UserTestFactory.ID;
 	static final ZonedDateTime CREATED_AT = VorgangTestFactory.CREATED_AT;
 	static final String NAME = VorgangTestFactory.NAME;
 	static final String VORGANG_NUMMER = VorgangTestFactory.VORGANG_NUMMER;
@@ -59,4 +59,8 @@ class IndexedVorgangTestFactory {
 				.status(STATUS)
 				.vorgangId(ID);
 	}
+
+	public static String createScriptRemoveFields(String field) {
+		return "ctx._source.remove('%s')".formatted(field);
+	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchConfigTest.java
similarity index 51%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangEventListenerTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchConfigTest.java
index 9d2e41897b423b74efb79ea8ae95bc170d9b9268..ab7c656749f33201285c9aebe671016b6623e09c 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangEventListenerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchConfigTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,46 +21,65 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.common.search;
 
 import static org.mockito.Mockito.*;
 
+import javax.net.ssl.SSLContext;
+
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.vorgang.redirect.VorgangForwardFailedEventTestFactory;
-import de.itvsh.ozg.pluto.vorgang.redirect.VorgangRedirectedEventTestFactory;
+import lombok.SneakyThrows;
 
-class VorgangEventListenerTest {
+class SearchConfigTest {
 
+	@Spy
 	@InjectMocks
-	private VorgangEventListener listener;
+	private SearchConfig searchConfig;
 
 	@Mock
-	private VorgangService service;
+	private SearchProperties properties;
 
 	@Nested
-	class OnVorgangRedirectedEvent {
+	class TestClientConfiguration {
 
-		@Test
-		void shouldSetStatus() {
-			listener.updateStatus(VorgangRedirectedEventTestFactory.create());
+		@BeforeEach
+		void setup() {
+			when(properties.getAddress()).thenReturn("address:9200");
+			when(properties.getUsername()).thenReturn("username");
+			when(properties.getPassword()).thenReturn("");
+		}
 
-			verify(service).setStatusToWeitergeleitet(VorgangRedirectedEventTestFactory.SOURCE);
+	 	@Test
+		void shouldCallGetAddress() {
+			searchConfig.clientConfiguration();
+
+			verify(properties).getAddress();
 		}
-	}
 
-	@Nested
-	class TestUpdateStatusOnVorgangForwardFailedEvent {
+		@Test
+		void shouldCallBuildHeaders() {
+			searchConfig.clientConfiguration();
+
+			verify(searchConfig).buildHeaders();
+		}
 
+		@SneakyThrows
 		@Test
-		void shouldSetStatus() {
-			listener.updateStatus(VorgangForwardFailedEventTestFactory.create());
+		void shouldSetSslContext() {
+			doReturn(mock(SSLContext.class)).when(searchConfig).createSslContext();
+			when(properties.isUseSsl()).thenReturn(true);
 
-			verify(service).setStatusToInBearbeitung(VorgangForwardFailedEventTestFactory.SOURCE.getId(),
-					VorgangForwardFailedEventTestFactory.SOURCE.getVorgangId());
+			searchConfig.clientConfiguration();
+
+			verify(searchConfig).createSslContext();
 		}
+
 	}
-}
\ No newline at end of file
+
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java
similarity index 54%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchEventListenerTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java
index 56b56af764651e14e490ac536069f336b06f492b..afdc70f8b74cbe88a3ace2e475117804edebe5ce 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchEventListenerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchEventListenerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
+import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Map;
 import java.util.Optional;
 
 import org.junit.jupiter.api.BeforeEach;
@@ -34,17 +36,18 @@ import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandService;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
-import de.itvsh.ozg.pluto.common.search.SearchEventListener;
-import de.itvsh.ozg.pluto.common.search.SearchService;
-import de.itvsh.ozg.pluto.vorgang.StatusChangedEvent;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangAssignedEvent;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.status.StatusChangedEvent;
+import de.ozgcloud.vorgang.vorgang.SetAktenzeichenCompletedEvent;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangAssignedEvent;
+import de.ozgcloud.vorgang.vorgang.VorgangDeletedEvent;
+import de.ozgcloud.vorgang.vorgang.VorgangDeletedEventTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class SearchEventListenerTest {
 
@@ -52,11 +55,9 @@ class SearchEventListenerTest {
 	private SearchEventListener eventListener;
 
 	@Mock
-	private SearchService elasticsearchService;
-
+	private SearchService service;
 	@Mock
 	private CommandService commandService;
-
 	@Mock
 	private VorgangService vorgangService;
 
@@ -79,7 +80,7 @@ class SearchEventListenerTest {
 
 			eventListener.onNewVorgang(vorgangCreatedEvent);
 
-			verify(elasticsearchService).addVorgang(any());
+			verify(service).addVorgang(any());
 		}
 	}
 
@@ -100,7 +101,7 @@ class SearchEventListenerTest {
 		void shouldUpdateVorgang() {
 			eventListener.onVorgangAssigned(vorgangAssignedEvent);
 
-			verify(elasticsearchService).updateVorgang(any());
+			verify(service).updateVorgang(any());
 		}
 	}
 
@@ -111,18 +112,57 @@ class SearchEventListenerTest {
 
 		@BeforeEach
 		void init() {
-			when(vorgangUpdatedEvent.getSource()).thenReturn("commandId");
-			Command command = CommandTestFactory.create();
-			when(commandService.findCommand(anyString())).thenReturn(Optional.of(command));
-
+			when(commandService.findCommand(any())).thenReturn(Optional.of(CommandTestFactory.create()));
 			when(vorgangService.getById(anyString())).thenReturn(vorgang);
 		}
 
 		@Test
-		void shouldUpdateVorgangInSolr() {
+		void shouldUpdateVorgangInSearchService() {
 			eventListener.onVorgangStatusChanged(vorgangUpdatedEvent);
 
-			verify(elasticsearchService).updateVorgang(any());
+			verify(service).updateVorgang(any());
+		}
+	}
+
+	@Nested
+	class TestOnDeletedVorgang {
+
+		private VorgangDeletedEvent event = VorgangDeletedEventTestFactory.create();
+
+		@Test
+		void shouldCallService() {
+			eventListener.onVorgangDeleted(event);
+
+			verify(service).deleteVorgang(any());
+		}
+
+		@Test
+		void shouldCatchException() {
+			doThrow(RuntimeException.class).when(service).deleteVorgang(any());
+
+			assertThatCode(() -> eventListener.onVorgangDeleted(event)).doesNotThrowAnyException();
+		}
+	}
+
+	@Nested
+	class TestOnSetAktenzeichenCompleted {
+
+		private SetAktenzeichenCompletedEvent event;
+		private Command command;
+
+		@BeforeEach
+		void setup() {
+			command = CommandTestFactory.createBuilder().bodyObject(Map.of(VorgangService.BODY_OBJECT_AKTENZEICHEN, VorgangTestFactory.AKTENZEICHEN))
+					.build();
+			event = new SetAktenzeichenCompletedEvent(command);
 		}
+
+		@Test
+		void shouldCallService() {
+			eventListener.onSetAktenzeichenCompletedEvent(event);
+
+			verify(service).setAktenzeichen(command.getVorgangId(), VorgangTestFactory.AKTENZEICHEN);
+		}
+
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchITCase.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchITCase.java
index dd82437bbf35ab33c52ed5341a9bb7b81512eac5..6e5c53dd848585fb6dc596b576eb712572016f14 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Inherited;
@@ -29,10 +29,9 @@ import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
 
-import de.itvsh.kop.common.test.ITCase;
+import de.ozgcloud.common.test.ITCase;
 
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
@@ -40,7 +39,6 @@ import de.itvsh.kop.common.test.ITCase;
 
 @ITCase
 @ContextConfiguration(initializers = { SearchInitializer.class })
-@ActiveProfiles({ "itcase" })
 public @interface SearchITCase {
 
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchIndexEnabledInitializer.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchIndexEnabledInitializer.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchIndexEnabledInitializer.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchIndexEnabledInitializer.java
index 7b97e36a02764a165f22df20549142ba175e3ec7..340066659d4422af982fbacb1911f84c871e2f8f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchIndexEnabledInitializer.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchIndexEnabledInitializer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import org.springframework.boot.test.util.TestPropertyValues;
 import org.springframework.context.ConfigurableApplicationContext;
@@ -32,6 +32,6 @@ class SearchIndexEnabledInitializer extends SearchInitializer {
 	protected void setProperties(ElasticsearchContainer container, ConfigurableApplicationContext applicationContext) {
 		super.setProperties(container, applicationContext);
 
-		TestPropertyValues.of("kop.elasticsearch.initEnabled=true").applyTo(applicationContext.getEnvironment());
+		TestPropertyValues.of("ozgcloud.elasticsearch.initEnabled=true").applyTo(applicationContext.getEnvironment());
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchIndexInitializerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchIndexInitializerITCase.java
similarity index 83%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchIndexInitializerITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchIndexInitializerITCase.java
index 1d46f9a4a8f6f42b1c56b42a2ebdc64f277fc247..3a358253d600a49c899970d3d238df3404b05473 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchIndexInitializerITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchIndexInitializerITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.after;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.verify;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
 
 import java.io.IOException;
 
@@ -40,13 +38,15 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.DisabledIf;
 
-import de.itvsh.kop.common.test.DbInitializer;
-import de.itvsh.kop.common.test.ITCase;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.test.DbInitializer;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
+@DisabledIf(expression = "${elasticTests.disabled:false}", reason = "Wegen hohem Speicherverbrauch des testcontainers")
 class SearchIndexInitializerITCase {
 	private static final int FOR_500_MS = 500;
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchInitializer.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchInitializer.java
similarity index 82%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchInitializer.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchInitializer.java
index c6b0d330e5b8a877c69af69839bac916af9b1693..32cf32db5e7f9eaaf8ba789dbd0240b5327c49e1 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchInitializer.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchInitializer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import java.time.Duration;
 
@@ -41,7 +41,7 @@ class SearchInitializer implements ApplicationContextInitializer<ConfigurableApp
 
 	private static ElasticsearchContainer elasticsearchContainer;
 
-	private final static String PASSWORD = "sUpers3cret!";
+	private final static String PASSWORD = "";
 	private static final String USERNAME = "elastic";
 
 	@Override
@@ -70,13 +70,14 @@ class SearchInitializer implements ApplicationContextInitializer<ConfigurableApp
 	}
 
 	protected void setProperties(ElasticsearchContainer container, ConfigurableApplicationContext applicationContext) {
-		var uriString = String.format("http://%s:%d", container.getHost(), container.getFirstMappedPort());
-		LOG.info("Uri: {} ", uriString);
+		var elasticAddress = container.getHost() + ":" + container.getFirstMappedPort();
+		LOG.info("address: {} ", elasticAddress);
 
 		TestPropertyValues.of(
-				"spring.elasticsearch.uris= http://" + container.getHost() + ":" + container.getFirstMappedPort(),
-				"spring.elasticsearch.username= " + USERNAME,
-				"spring.elasticsearch.password= " + PASSWORD,
-				"kop.elasticsearch.index=test").applyTo(applicationContext);
+				"ozgcloud.elasticsearch.address=" + elasticAddress,
+				"ozgcloud.elasticsearch.username=" + USERNAME,
+				"ozgcloud.elasticsearch.password=" + PASSWORD,
+				"ozgcloud.elasticsearch.useSsl=false",
+				"ozgcloud.elasticsearch.index=test").applyTo(applicationContext);
 	}
 }
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf61508cbb43f87da32496d714f1677b8bec48ba
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchServiceITCase.java
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.search;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
+import org.springframework.test.context.junit.jupiter.DisabledIf;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.vorgang.AntragstellerTestFactory;
+import de.ozgcloud.vorgang.vorgang.FilterCriteria;
+import de.ozgcloud.vorgang.vorgang.FilterCriteriaTestFactory;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequestTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+@DisabledIf(expression = "${elasticTests.disabled:false}", reason = "Wegen hohem Speicherverbrauch des testcontainers")
+@SearchITCase
+public class SearchServiceITCase {
+
+	@Autowired
+	private SearchService searchService;
+
+	@Autowired
+	private SearchVorgangRepository repository;
+
+	@Autowired
+	private ElasticsearchOperations elasticsearchOperations;
+
+	@MockBean
+	private CommandService commandService;
+
+	@Nested
+	class TestAddVorgang {
+		@BeforeEach
+		void init() {
+			elasticsearchOperations.indexOps(IndexedVorgang.class).delete();
+		}
+
+		@Test
+		void shouldAdd() throws IOException {
+			searchService.addVorgang(VorgangTestFactory.create());
+
+			Iterable<IndexedVorgang> vorgangs = repository.findAll();
+			assertThat(vorgangs).isNotEmpty();
+		}
+	}
+
+	@Nested
+	class TestUpdateVorgang {
+		@BeforeEach
+		void init() {
+			Command cmd = CommandTestFactory.createBuilder().build();
+			when(commandService.findCommand(CommandTestFactory.ID)).thenReturn(Optional.of(cmd));
+
+			elasticsearchOperations.indexOps(IndexedVorgang.class).delete();
+
+			searchService.addVorgang(VorgangTestFactory.create());
+		}
+
+		@Test
+		void shouldUpdate() throws IOException {
+			var vorgang = VorgangTestFactory.createBuilder().status(Status.ABGESCHLOSSEN).build();
+			searchService.updateVorgang(vorgang);
+
+			Iterable<IndexedVorgang> vorgangs = repository.findAll();
+			assertThat(vorgangs).isNotEmpty().hasSize(1);
+			assertThat(vorgangs.iterator().next().getStatus()).isEqualTo(Status.ABGESCHLOSSEN.name());
+		}
+	}
+
+	@DisplayName("Find")
+	@Nested
+	class TestFind {
+
+		@BeforeEach
+		void init() {
+			var indexOperations = elasticsearchOperations.indexOps(IndexedVorgang.class);
+			indexOperations.delete();
+			indexOperations.create();
+			indexOperations.putMapping(IndexedVorgang.class);
+		}
+
+		@DisplayName("with hyphen")
+		@Nested
+		class TestWithHyphen {
+
+			@DisplayName("in vorgangNummer")
+			@Test
+			void shouldFindInVorgangNummer() {
+				var vorgangNummer = "Vorgang-Nummer";
+				elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().vorgangNummer(vorgangNummer).build());
+				elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+				var vorgangHeaders = searchService.find(
+						FindVorgangRequestTestFactory.createBuilder().searchBy(vorgangNummer).build()).getContent();
+
+				assertThat(vorgangHeaders).hasSize(1).first().extracting("nummer").isEqualTo(vorgangNummer);
+			}
+
+			@DisplayName("in vorgangName")
+			@Test
+			void shouldFindInVorgangName() {
+				var vorgangName = "VorgangName";
+				elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().vorgangName(vorgangName).build());
+				elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+				var vorgangHeaders = searchService.find(
+						FindVorgangRequestTestFactory.createBuilder().searchBy(vorgangName).build()).getContent();
+
+				assertThat(vorgangHeaders).hasSize(1).first().extracting("name").isEqualTo(vorgangName);
+
+			}
+
+			@DisplayName("in aktenzeichen")
+			@Test
+			void shouldFindInAktenzeichen() {
+				var aktenzeichen = "Akten-zeichen";
+				elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().aktenzeichen(aktenzeichen).build());
+				elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+				var vorgangHeaders = searchService.find(
+						FindVorgangRequestTestFactory.createBuilder().searchBy("kten").build()).getContent();
+
+				assertThat(vorgangHeaders).hasSize(1).first().extracting("aktenzeichen").isEqualTo(aktenzeichen);
+			}
+
+			@DisplayName("in antragstellerName")
+			@Test
+			void shouldFindInAntragstellerName() {
+				elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().antragstellerName("Antragsteller-Name").build());
+				repository.save(IndexedVorgangTestFactory.createBuilder().vorgangId("123").build());
+				elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+				var vorgangHeaders = searchService.find(FindVorgangRequestTestFactory.createBuilder().searchBy("steller-na").build()).getContent();
+
+				assertThat(vorgangHeaders).hasSize(1);
+			}
+
+			@DisplayName("in antragstellerVorname")
+			@Test
+			void shouldFindInAntragstellerVorname() {
+				elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().antragstellerVorname("Antragsteller-Vorname").build());
+				elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+				var vorgangHeaders = searchService.find(FindVorgangRequestTestFactory.createBuilder().searchBy("name").build())
+						.getContent();
+
+				assertThat(vorgangHeaders).hasSize(1);
+			}
+		}
+
+		@Nested
+		class filteredByOrganisationseinheitenId {
+
+			@BeforeEach
+			void init() {
+				searchService.addVorgang(VorgangTestFactory.create());
+				searchService.addVorgang(
+						VorgangTestFactory.createBuilder().id(null).aktenzeichen("test").assignedTo(UUID.randomUUID().toString()).build());
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).aktenzeichen("vors").build());
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).aktenzeichen("vOrsi").build());
+			}
+
+			@Test
+			void shouldFindByAktenzeichen() {
+				var res = searchService.find(FindVorgangRequestTestFactory.createBuilder()
+						.searchBy("vors")
+						.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().filterByAssignedTo(false).build())
+						.build());
+
+				assertThat(res).hasSize(2);
+			}
+
+			@Test
+			void shouldFindByAntragstellerName() {
+				var res = searchService
+						.find(FindVorgangRequestTestFactory.createBuilder()
+								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME)
+								.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().filterByAssignedTo(false).build())
+								.build());
+
+				assertThat(res).hasSize(4);
+			}
+
+			@Test
+			void shouldFindByAntragstellerNameAndAktenzeichen() {
+				var res = searchService
+						.find(FindVorgangRequestTestFactory.createBuilder()
+								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME + " tes")
+								.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().filterByAssignedTo(false).build())
+								.build());
+
+				assertThat(res).hasSize(1);
+			}
+
+			@Test
+			void shouldFindByAntragstellerNameAndereOrganisationEinheitId() {
+				searchService
+						.addVorgang(
+								VorgangTestFactory.createWithOrganisationEinheitId("12345678").toBuilder().id(UUID.randomUUID().toString()).build());
+
+				var res = searchService.find(FindVorgangRequestTestFactory.createBuilder()
+						.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME).filterBy(
+								FilterCriteriaTestFactory.createBuilder()
+										.clearOrganisationseinheitIds()
+										.organisationseinheitIds(List.of("12345678"))
+										.clearStatus().build())
+						.build());
+
+				assertThat(res).hasSize(1);
+			}
+
+			@Test
+			void shouldDoPageination() {
+				var res = searchService
+						.find(FindVorgangRequestTestFactory.createBuilder()
+								.searchBy(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME)
+								.limit(2)
+								.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().build())
+								.build());
+
+				assertThat(res).hasSize(2);
+				assertThat(res.getTotalPages()).isEqualTo(2);
+			}
+		}
+
+		@DisplayName("filter by status only")
+		@Nested
+		class TestFilterByStatus {
+
+			@BeforeEach
+			void init() {
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).status(Status.ANGENOMMEN).build());
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).build());
+				searchService.addVorgang(VorgangTestFactory.createWithOrganisationEinheitId("12345678").toBuilder().id(null).build());
+			}
+
+			@Test
+			void shouldFindByAntragstellerName() {
+				var request = createRequest(IndexedVorgangTestFactory.ANTRAGSTELLER_NAME,
+						FilterCriteriaTestFactory.createBuilder().filterByOrganisationseinheitenId(false).build());
+
+				var res = searchService.find(request);
+
+				assertThat(res).hasSize(2);
+			}
+		}
+
+		@DisplayName("filter by organisationsEinheitId and status")
+		@Nested
+		class TestFilterByOrganisationsEinheitIdAndStatus {
+
+			@BeforeEach
+			void init() {
+				searchService.addVorgang(VorgangTestFactory.create());
+				searchService.addVorgang(
+						VorgangTestFactory.createBuilder().id(null).aktenzeichen("test").assignedTo(UUID.randomUUID().toString()).build());
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).aktenzeichen("vors").build());
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).aktenzeichen("vOrsi").build());
+				searchService
+						.addVorgang(
+								VorgangTestFactory.createWithOrganisationEinheitId("12345678").toBuilder().id(UUID.randomUUID().toString()).build());
+				searchService
+						.addVorgang(VorgangTestFactory.createBuilder().status(Status.ANGENOMMEN).id(UUID.randomUUID().toString()).build());
+			}
+
+			@Test
+			void shouldFindByAktenzeichen() {
+				var request = createRequest("test", FilterCriteriaTestFactory.createBuilder().filterByAssignedTo(false).build());
+
+				var res = searchService.find(request);
+
+				assertThat(res).hasSize(1);
+			}
+
+			@Test
+			void shouldFindByAntragstellerName() {
+				var request = createRequest(AntragstellerTestFactory.NACHNAME,
+						FilterCriteriaTestFactory.createBuilder().filterByAssignedTo(false).build());
+
+				var res = searchService.find(request);
+
+				assertThat(res).hasSize(4);
+			}
+		}
+
+		private FindVorgangRequest createRequest(String searchBy, FilterCriteria filterCriteria) {
+			return FindVorgangRequestTestFactory.createBuilder().searchBy(searchBy).filterBy(filterCriteria).build();
+		}
+	}
+
+	@DisplayName("Filter")
+	@Nested
+	class TestFilter {
+
+		@BeforeEach
+		void init() {
+			elasticsearchOperations.indexOps(IndexedVorgang.class).delete();
+			elasticsearchOperations.indexOps(IndexedVorgang.class).create();
+		}
+
+		@DisplayName("by organisationsEinheitId")
+		@Nested
+		class TestByOrganisationsEinheitId {
+
+			private static final String NAME = "shouldBeFound";
+
+			@BeforeEach
+			void init() {
+				searchService.addVorgang(VorgangTestFactory.createWithOrganisationEinheitId("132").toBuilder().id(null).build());
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).name(NAME).assignedTo(null).build());
+			}
+
+			@Test
+			void shouldReturnMatchingId() {
+				var request = createRequest(AntragstellerTestFactory.NACHNAME,
+						FilterCriteriaTestFactory.createBuilder().filterByAssignedTo(false).build());
+
+				var result = searchService.find(request);
+				assertThat(result).hasSize(1);
+				assertThat(result.getContent().get(0).getName()).isEqualTo(NAME);
+			}
+
+			@Test
+			void shouldReturnUnfiltered() {
+				var request = createRequest(AntragstellerTestFactory.NACHNAME, FilterCriteriaTestFactory.createBuilder().filterByAssignedTo(false)
+						.filterByOrganisationseinheitenId(false).organisationseinheitIds(List.of("123"))
+						.build());
+
+				var result = searchService.find(request);
+				assertThat(result).hasSize(2);
+			}
+		}
+
+		@DisplayName("by assignedTo")
+		@Nested
+		class TestByAssignedTo {
+
+			private static final String NAME = "shouldBeFound";
+
+			@BeforeEach
+			void init() {
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).build());
+				searchService.addVorgang(VorgangTestFactory.createBuilder().id(null).name(NAME).assignedTo(null).build());
+			}
+
+			@Test
+			void shouldReturnUnassigned() {
+				var request = createRequest(AntragstellerTestFactory.NACHNAME,
+						FilterCriteriaTestFactory.createBuilder().assignedTo(StringUtils.EMPTY).build());
+
+				var result = searchService.find(request);
+
+				assertThat(result).hasSize(1);
+				assertThat(result.getContent().get(0).getName()).isEqualTo(NAME);
+			}
+
+			@Test
+			void shouldReturnMatchingAssigned() {
+				var request = createRequest(AntragstellerTestFactory.NACHNAME, FilterCriteriaTestFactory.createBuilder().build());
+
+				var result = searchService.find(request);
+
+				assertThat(result).hasSize(1);
+				assertThat(result.getContent().get(0).getName()).isEqualTo(VorgangTestFactory.NAME);
+			}
+
+			@Test
+			void shouldReturnUnfiltered() {
+				var request = createRequest(AntragstellerTestFactory.NACHNAME,
+						FilterCriteriaTestFactory.createBuilder().filterByAssignedTo(false).build());
+
+				var result = searchService.find(request);
+
+				assertThat(result).hasSize(2);
+			}
+
+			@Test
+			void shouldFilterByAssignedToOnly() {
+				var request = createRequest(AntragstellerTestFactory.NACHNAME,
+						FilterCriteriaTestFactory.createBuilder().filterByOrganisationseinheitenId(false).build());
+
+				var result = searchService.find(request);
+
+				assertThat(result).hasSize(1);
+			}
+		}
+
+		private FindVorgangRequest createRequest(String searchBy, FilterCriteria filterCriteria) {
+			return FindVorgangRequestTestFactory.createBuilder().searchBy(searchBy).filterBy(filterCriteria).build();
+		}
+	}
+
+	@Nested
+	class TestAktenzeichen {
+
+		@Test
+		void shouldSetAktenzeichenOnly() {
+			var newAktenzeichen = "new-aktenzeichen";
+			var vorgang = elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().vorgangId(null).build());
+			elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+			searchService.setAktenzeichen(vorgang.getVorgangId(), newAktenzeichen);
+
+			var indexedVorgang = elasticsearchOperations.get(vorgang.getVorgangId(), IndexedVorgang.class);
+			assertThat(indexedVorgang).usingRecursiveComparison().ignoringFields("vorgangId").isEqualTo(IndexedVorgangTestFactory.createBuilder().aktenzeichen(newAktenzeichen).build());
+		}
+
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchServiceTest.java
similarity index 72%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchServiceTest.java
index 76a41bd13546459f538c589580a38ac9259b7781..be5441e3f9c675c6e3a84c6f5fdea0cfdbf50b75 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Map;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -35,18 +37,19 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.springframework.dao.DataAccessResourceFailureException;
 
-import de.itvsh.ozg.pluto.common.errorhandling.SearchServiceUnavailableException;
-import de.itvsh.ozg.pluto.vorgang.FindVorgangRequestTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.common.errorhandling.SearchServiceUnavailableException;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequestTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class SearchServiceTest {
 
 	@InjectMocks
 	private SearchService searchService;
 	@Mock
-	private SearchVorgangRepostitory repository;
+	private SearchVorgangRepository repository;
 	@Mock
-	private SearchVorgangCustomRepostitory searchRepository;
+	private SearchVorgangCustomRepository searchRepository;
 
 	@Mock
 	private IndexedVorgangMapper mapper;
@@ -97,7 +100,7 @@ class SearchServiceTest {
 		void shouldCallRepositorySearch() {
 			searchService.find(FindVorgangRequestTestFactory.create());
 
-			verify(searchRepository).searchBy(any(SearchRequest.class));
+			verify(searchRepository).searchBy(any(FindVorgangRequest.class));
 		}
 
 		@DisplayName("on unavailable search service")
@@ -116,4 +119,26 @@ class SearchServiceTest {
 			}
 		}
 	}
-}
+
+	@Nested
+	class TestDeleteVorgang {
+		@Test
+		void shouldDeleteVorgang() {
+			searchService.deleteVorgang(VorgangTestFactory.ID);
+
+			verify(repository).deleteById(VorgangTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestSetAktenzeichen {
+
+		@Test
+		void shouldCallRepository() {
+			searchService.setAktenzeichen(VorgangTestFactory.ID, VorgangTestFactory.AKTENZEICHEN);
+
+			verify(searchRepository).update(VorgangTestFactory.ID, Map.of(IndexedVorgang.FIELD_AKTENZEICHEN, VorgangTestFactory.AKTENZEICHEN));
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..20275fcb2c7be7088b3a87be9815142ff714db07
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryITCase.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.search;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
+import org.springframework.test.context.junit.jupiter.DisabledIf;
+
+import de.ozgcloud.vorgang.vorgang.FilterCriteria;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest;
+
+@DisabledIf(expression = "${elasticTests.disabled:false}", reason = "Wegen hohem Speicherverbrauch des testcontainers")
+@SearchITCase
+public class SearchVorgangCustomRepositoryITCase {
+
+	@Autowired
+	private SearchVorgangCustomRepository repostitory;
+
+	@Autowired
+	private ElasticsearchOperations elasticsearchOperations;
+
+	@Nested
+	class TestSpecialCharacters {
+
+		private static final String VALUE_PATTERN = "AbC%sTest";
+		private static final String SEARCH_BY_PATTERN = "bc%st";
+
+		@BeforeEach
+		void init() {
+			var indexOperations = elasticsearchOperations.indexOps(IndexedVorgang.class);
+			indexOperations.delete();
+			indexOperations.create();
+			indexOperations.putMapping(IndexedVorgang.class);
+		}
+
+		@DisplayName("should find vorgang when vorgangName")
+		@ParameterizedTest(name = "contains {0}")
+		@ValueSource(strings = { "_", "+", "-", "=", "&&", "||", "!", "(", ")", "{", "}", "[", "]", "^", "\"", "~", "*", "?", ":", "\\", "/", "<",
+				">", "$", "%", "&", "#", "@" })
+		void shouldFindInVorgangName(String character) {
+			elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().vorgangName(VALUE_PATTERN.formatted(character)).build());
+			elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+			var vorgangHeaders = repostitory.searchBy(searchRequest(character));
+
+			Assertions.assertThat(vorgangHeaders.getContent()).hasSize(1).first()
+					.extracting("name").isEqualTo(VALUE_PATTERN.formatted(character));
+		}
+
+		@DisplayName("should find vorgang when vorgangNummer")
+		@ParameterizedTest(name = "contains {0}")
+		@ValueSource(strings = { "_", "+", "-", "=", "&&", "||", "!", "(", ")", "{", "}", "[", "]", "^", "\"", "~", "*", "?", ":", "\\", "/", "<",
+				">", "$", "%", "&", "#", "@" })
+		void shouldFindInVorgangNummer(String character) {
+			elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().vorgangNummer(VALUE_PATTERN.formatted(character)).build());
+			elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+			var vorgangHeaders = repostitory.searchBy(searchRequest(character));
+
+			Assertions.assertThat(vorgangHeaders.getContent()).hasSize(1).first()
+					.extracting("nummer").isEqualTo(VALUE_PATTERN.formatted(character));
+		}
+
+		@DisplayName("should find vorgang when antragstellerName")
+		@ParameterizedTest(name = "contains {0}")
+		@ValueSource(strings = { "_", "+", "-", "=", "&&", "||", "!", "(", ")", "{", "}", "[", "]", "^", "\"", "~", "*", "?", ":", "\\", "/", "<",
+				">", "$", "%", "&", "#", "@" })
+		void shouldFindInAntragstellerName(String character) {
+			elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().antragstellerName(VALUE_PATTERN.formatted(character)).build());
+			elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+			var vorgangHeaders = repostitory.searchBy(searchRequest(character));
+
+			Assertions.assertThat(vorgangHeaders.getContent()).hasSize(1);
+		}
+
+		@DisplayName("should find vorgang when antragstellerVorname")
+		@ParameterizedTest(name = "contains {0}")
+		@ValueSource(strings = { "_", "+", "-", "=", "&&", "||", "!", "(", ")", "{", "}", "[", "]", "^", "\"", "~", "*", "?", ":", "\\", "/", "<",
+				">", "$", "%", "&", "#", "@" })
+		void shouldFindInAntragstellerVorname(String character) {
+			elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().antragstellerVorname(VALUE_PATTERN.formatted(character)).build());
+			elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+			var vorgangHeaders = repostitory.searchBy(searchRequest(character));
+
+			Assertions.assertThat(vorgangHeaders.getContent()).hasSize(1);
+		}
+
+		@DisplayName("should find vorgang when aktenzeichen")
+		@ParameterizedTest(name = "contains {0}")
+		@ValueSource(strings = { "_", "+", "-", "=", "&&", "||", "!", "(", ")", "{", "}", "[", "]", "^", "\"", "~", "*", "?", ":", "\\", "/", "<",
+				">", "$", "%", "&", "#", "@" })
+		void shouldFindInAktenzeichen(String character) {
+			elasticsearchOperations.save(IndexedVorgangTestFactory.createBuilder().aktenzeichen(VALUE_PATTERN.formatted(character)).build());
+			elasticsearchOperations.indexOps(IndexedVorgang.class).refresh();
+
+			var vorgangHeaders = repostitory.searchBy(searchRequest(character));
+
+			Assertions.assertThat(vorgangHeaders.getContent()).hasSize(1).first()
+					.extracting("aktenzeichen").isEqualTo(VALUE_PATTERN.formatted(character));
+		}
+
+		private FindVorgangRequest searchRequest(String character) {
+			return FindVorgangRequest.builder().filterBy(FilterCriteria.builder().build()).searchBy(SEARCH_BY_PATTERN.formatted(character)).build();
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryImplTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..03d9fa28eb80f852ff953cae14903fc15de2c028
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangCustomRepositoryImplTest.java
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.search;
+
+import static de.ozgcloud.vorgang.common.search.IndexedVorgangTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.assertj.core.data.MapEntry;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.elasticsearch.client.elc.NativeQuery;
+import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
+import org.springframework.data.elasticsearch.core.IndexOperations;
+import org.springframework.data.elasticsearch.core.ScriptType;
+import org.springframework.data.elasticsearch.core.SearchHit;
+import org.springframework.data.elasticsearch.core.SearchHits;
+import org.springframework.data.elasticsearch.core.document.Document;
+import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
+import org.springframework.data.elasticsearch.core.query.UpdateQuery;
+
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.FilterCriteriaTestFactory;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequestTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.VorgangHeader;
+import de.ozgcloud.vorgang.vorgang.VorgangHeaderTestFactory;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
+
+class SearchVorgangCustomRepositoryImplTest {
+
+	@Spy
+	@InjectMocks
+	private SearchVorgangCustomRepositoryImpl searchRepostitory;
+
+	@Mock
+	private IndexedVorgangMapper mapper;
+
+	@Mock
+	private SearchProperties properties;
+
+	@Mock
+	private ElasticsearchOperations operations;
+
+	@Nested
+	class TestSearch {
+
+		@Mock
+		private SearchHits<IndexedVorgang> searchHits;
+		@Mock
+		private SearchHit<IndexedVorgang> searchHit;
+
+		@BeforeEach
+		void init() {
+			when(searchHit.getContent()).thenReturn(IndexedVorgangTestFactory.create());
+			when(searchHits.get()).thenReturn(List.of(searchHit).stream());
+			when(operations.search(any(NativeQuery.class), eq(IndexedVorgang.class))).thenReturn(searchHits);
+		}
+
+		@Test
+		void shouldCallSearch() {
+			searchRepostitory.searchBy(FindVorgangRequestTestFactory.create());
+
+			verify(mapper, atLeastOnce()).toVorgangHeader(any());
+			verify(operations).search(any(NativeQuery.class), eq(IndexedVorgang.class));
+		}
+
+		@Test
+		void shouldMapResult() {
+			when(mapper.toVorgangHeader(any())).thenReturn(VorgangHeaderTestFactory.create());
+
+			var res = searchRepostitory.searchBy(FindVorgangRequestTestFactory.create());
+
+			assertThat(res).isNotEmpty().hasAtLeastOneElementOfType(VorgangHeader.class);
+		}
+	}
+
+	@Nested
+	class TestQuery {
+
+		@Test
+		void shouldHavePaging() {
+			var pageable = searchRepostitory.buildPageable(FindVorgangRequestTestFactory.create());
+
+			assertThat(pageable).isNotNull();
+			assertThat(pageable.getOffset()).isZero();
+			assertThat(pageable.getPageSize()).isEqualTo(FindVorgangRequestTestFactory.LIMIT);
+			assertThat(pageable.getSort()).isEqualTo(Sort.unsorted());
+		}
+
+		@Test
+		void shouldHaveFirstPageNumber() {
+			var pageable = searchRepostitory.buildPageable(FindVorgangRequestTestFactory.create());
+
+			assertThat(pageable.getPageNumber()).isZero();
+		}
+
+		@Test
+		void shouldHaveSecondPageNumber() {
+			var pageable = searchRepostitory.buildPageable(
+					FindVorgangRequestTestFactory.createBuilder()
+							.offset(FindVorgangRequestTestFactory.LIMIT)
+							.build());
+
+			assertThat(pageable.getPageNumber()).isEqualTo(1);
+		}
+
+		@Test
+		void shouldHaveFieldsWithWights() {
+			var query = searchRepostitory.buildQueryBuilder(FindVorgangRequestTestFactory.create()).build();
+
+			assertThat(query.getQuery()).isNotNull();
+			assertThat(query.getQuery()).asString().contains("aktenzeichen^2.0");
+			assertThat(query.getQuery()).asString().contains("antragstellerName^1.0");
+			assertThat(query.getQuery()).asString().contains("antragstellerVorname^1.0");
+			assertThat(query.getQuery()).asString().contains("vorgangName^0.5");
+			assertThat(query.getQuery()).asString().contains("vorgangNummer^2.0");
+		}
+
+		@Test
+		void shouldHaveSimpleQuery() {
+			var request = FindVorgangRequestTestFactory.createBuilder().searchBy("vors").build();
+			var query = searchRepostitory.buildQueryBuilder(request).build();
+
+			assertThat(query.getQuery()).asString().contains("\"query\":\"(*vors*)\"");
+		}
+
+		@Test
+		void shouldHaveQuery() {
+			var request = FindVorgangRequestTestFactory.createBuilder().searchBy("vors test").build();
+			var query = searchRepostitory.buildQueryBuilder(request).build();
+
+			assertThat(query.getQuery()).asString().contains("\"query\":\"(*vors*) AND (*test*)\"");
+		}
+
+		@Nested
+		class TestBuildSearchByQueryBuilder {
+
+			@Test
+			void shouldCallAdjustSearchTerm() {
+				var request = FindVorgangRequestTestFactory.createBuilder().searchBy("vors test").build();
+
+				searchRepostitory.buildSearchByQueryBuilder(request);
+
+				verify(searchRepostitory, times(2)).adjustSearchTerm(any());
+			}
+		}
+
+		@Nested
+		class TestEscapingCharacters {
+
+			private static final String SEARCH_TERM_PATTERN = "Ab%sT";
+			private static final String ESCAPED_SEARCH_TERM_PATTERN = "(*Ab\\%sT*)";
+
+			@ParameterizedTest(name = "should escape {0}")
+			@ValueSource(strings = { "+", "-", "=", "&&", "||", "!", "(", ")", "{", "}", "[", "]", "^", "\"", "~", "*", "?", ":", "\\", "/" })
+			void shouldFindWithSpecialCharacters(String character) {
+				var result = searchRepostitory.adjustSearchTerm(SEARCH_TERM_PATTERN.formatted(character));
+
+				assertThat(result).isEqualTo(ESCAPED_SEARCH_TERM_PATTERN.formatted(character));
+			}
+
+			@ParameterizedTest(name = "should replace {0}")
+			@ValueSource(strings = { "<", ">" })
+			void shouldRemoveSpecialCharacters(String character) {
+				var result = searchRepostitory.adjustSearchTerm(SEARCH_TERM_PATTERN.formatted(character));
+
+				assertThat(result).isEqualTo("(*" + SEARCH_TERM_PATTERN.formatted("?") + "*)");
+			}
+
+			@Test
+			void shouldReplaceAllCharacters() {
+				var searchTerm = "abc/123+z";
+				var expectedResult = "(*abc\\/123\\+z*)";
+
+				var result = searchRepostitory.adjustSearchTerm(searchTerm);
+
+				assertThat(result).isEqualTo(expectedResult);
+			}
+		}
+
+		@Nested
+		class forRolePoststelle {
+			@Test
+			void shouldHaveStatusFilterOnly() {
+				var request = FindVorgangRequestTestFactory.createBuilder().filterBy(
+						FilterCriteriaTestFactory.createBuilder()
+								.filterByOrganisationseinheitenId(false).clearOrganisationseinheitIds()
+								.clearStatus().singleStatus(Status.ABGESCHLOSSEN)
+								.build())
+						.build();
+				var query = searchRepostitory.buildQueryBuilder(request).build();
+
+				assertThat(query.getFilter()).isNotNull();
+				assertThat(query.getFilter()).asString().contains("status");
+				assertThat(query.getFilter()).asString().contains(Status.ABGESCHLOSSEN.name());
+				assertThat(query.getFilter()).asString().doesNotContain("organisationseinheitenId");
+			}
+
+			@Test
+			void shouldHaveOrganisationseinheitenIdFilterOnly() {
+				var request = FindVorgangRequestTestFactory.create();
+				var query = searchRepostitory.buildQueryBuilder(request).build();
+
+				assertThat(query.getFilter()).isNotNull();
+				assertThat(query.getFilter()).asString().contains("organisationseinheitenId");
+				assertThat(query.getFilter()).asString().contains(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
+			}
+
+			@Test
+			void shouldHaveOrganisationseinheitenAndStatusFilter() {
+				var request = FindVorgangRequestTestFactory.createBuilder().filterBy(
+						FilterCriteriaTestFactory.createBuilder().clearStatus().singleStatus(Status.ABGESCHLOSSEN).build())
+						.build();
+
+				var query = searchRepostitory.buildQueryBuilder(request).build();
+
+				assertThat(query.getFilter()).isNotNull();
+				assertThat(query.getFilter()).asString().contains("organisationseinheitenId");
+				assertThat(query.getFilter()).asString().contains(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
+				assertThat(query.getFilter()).asString().contains("status");
+				assertThat(query.getFilter()).asString().contains(Status.ABGESCHLOSSEN.name());
+			}
+		}
+
+		@Nested
+		class forOtherRoles {
+			@Test
+			void shouldHaveOrganisationseinheitenIdFilter() {
+				var request = FindVorgangRequestTestFactory.create();
+				var query = searchRepostitory.buildQueryBuilder(request).build();
+
+				assertThat(query.getFilter()).isNotNull();
+				assertThat(query.getFilter()).asString().contains("organisationseinheitenId");
+				assertThat(query.getFilter()).asString().contains(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
+			}
+
+			@Test
+			void shouldHaveAssignedToFilter() {
+				var request = FindVorgangRequestTestFactory.create();
+				var query = searchRepostitory.buildQueryBuilder(request).build();
+
+				assertThat(query.getFilter()).isNotNull();
+				assertThat(query.getFilter()).asString().contains("assignedTo");
+				assertThat(query.getFilter()).asString().contains(UserTestFactory.ID);
+			}
+		}
+	}
+
+	@Nested
+	class TestPartialUpdate {
+
+		@Nested
+		class TestUpdate {
+
+			private static final Set<String> FIELDS_TO_REMOVE = Set.of(IndexedVorgang.FIELD_AKTENZEICHEN);
+			private static final Map<String, Object> FIELDS_TO_UPDATE = Map.of(IndexedVorgang.FIELD_AKTENZEICHEN,
+					AKTENZEICHEN);
+
+			@Mock
+			private UpdateQuery updateQuery;
+
+			@Test
+			void shouldCallExecuteUpdate() {
+				doNothing().when(searchRepostitory).executeUpdate(any());
+				doReturn(FIELDS_TO_REMOVE).when(searchRepostitory).getFieldsToRemove(any());
+				doReturn(FIELDS_TO_UPDATE).when(searchRepostitory).getFieldsToUpdate(any());
+
+				searchRepostitory.update(IndexedVorgangTestFactory.ID, Collections.emptyMap());
+
+				verify(searchRepostitory, times(2)).executeUpdate(any());
+			}
+
+			@Test
+			void shouldNotCallExecuteUpdate() {
+				doReturn(Collections.emptySet()).when(searchRepostitory).getFieldsToRemove(any());
+				doReturn(Collections.emptyMap()).when(searchRepostitory).getFieldsToUpdate(any());
+
+				searchRepostitory.update(IndexedVorgangTestFactory.ID, createMap());
+
+				verify(searchRepostitory, never()).executeUpdate(any());
+			}
+
+			Map<String, Object> createMap() {
+				var map = new HashMap<String, Object>();
+				map.put(IndexedVorgang.FIELD_ANTRAGSTELLER_NAME, IndexedVorgangTestFactory.ANTRAGSTELLER_NAME);
+				map.put(IndexedVorgang.FIELD_AKTENZEICHEN, null);
+				return map;
+			}
+
+			@Nested
+			class TestUpdateWithScript {
+
+				@BeforeEach
+				void setup() {
+					doNothing().when(searchRepostitory).executeUpdate(any());
+					doReturn(FIELDS_TO_REMOVE).when(searchRepostitory).getFieldsToRemove(any());
+				}
+
+				@Test
+				void shouldCallBuildRemoveFieldScript() {
+					searchRepostitory.update(IndexedVorgangTestFactory.ID, createMap());
+
+					verify(searchRepostitory).buildRemoveFieldScript(FIELDS_TO_REMOVE);
+				}
+
+				@Test
+				void shouldCallBuildUpdateQueryWithScript() {
+					var createdScript = "script";
+					doReturn(createdScript).when(searchRepostitory).buildRemoveFieldScript(any());
+
+					searchRepostitory.update(IndexedVorgangTestFactory.ID, createMap());
+
+					verify(searchRepostitory).buildUpdateQueryWithScript(IndexedVorgangTestFactory.ID, createdScript);
+				}
+
+				@Test
+				void shouldCallExecuteUpdate() {
+					doReturn(updateQuery).when(searchRepostitory).buildUpdateQueryWithScript(any(), any());
+
+					searchRepostitory.update(IndexedVorgangTestFactory.ID, createMap());
+
+					verify(searchRepostitory).executeUpdate(updateQuery);
+				}
+
+				private Map<String, Object> createMap() {
+					var map = new HashMap<String, Object>();
+					map.put(IndexedVorgang.FIELD_AKTENZEICHEN, null);
+					return map;
+				}
+			}
+
+			@Nested
+			class TestUpdateWithDocument {
+
+				@BeforeEach
+				void setup() {
+					doNothing().when(searchRepostitory).executeUpdate(any());
+					doReturn(FIELDS_TO_UPDATE).when(searchRepostitory).getFieldsToUpdate(any());
+				}
+
+				@Test
+				void shouldCallBuildUpdateQueryWithDocument() {
+					searchRepostitory.update(IndexedVorgangTestFactory.ID, FIELDS_TO_UPDATE);
+
+					verify(searchRepostitory).buildUpdateQueryWithDocument(IndexedVorgangTestFactory.ID, FIELDS_TO_UPDATE);
+				}
+
+				@Test
+				void shouldCallExecuteUpdate() {
+					doReturn(updateQuery).when(searchRepostitory).buildUpdateQueryWithDocument(any(), any());
+
+					searchRepostitory.update(IndexedVorgangTestFactory.ID, FIELDS_TO_UPDATE);
+
+					verify(searchRepostitory).executeUpdate(updateQuery);
+				}
+			}
+
+		}
+
+		@Nested
+		class TestGetFieldsToRemove {
+
+			@Test
+			void shouldReturnFieldsToRemove() {
+				var fieldsToRemove = searchRepostitory.getFieldsToRemove(createMap(null));
+
+				assertThat(fieldsToRemove).containsOnly(IndexedVorgang.FIELD_AKTENZEICHEN);
+			}
+
+			@Test
+			void shouldReturnEmptyFieldsToRemove() {
+				var fieldsToRemove = searchRepostitory.getFieldsToRemove(createMap(AKTENZEICHEN));
+
+				assertThat(fieldsToRemove).isEmpty();
+			}
+
+			private Map<String, Object> createMap(Object value) {
+				var map = new HashMap<String, Object>();
+				map.put(IndexedVorgang.FIELD_AKTENZEICHEN, value);
+				return map;
+			}
+		}
+
+		@Nested
+		class TestBuildRemoveFieldScript {
+
+			@Test
+			void shouldBuildScript() {
+				var removeAktenzeichenScript = createScriptRemoveFields(IndexedVorgang.FIELD_AKTENZEICHEN);
+				var removeAssignedToScript = createScriptRemoveFields(IndexedVorgang.FIELD_ASSIGNED_TO);
+
+				var script = searchRepostitory.buildRemoveFieldScript(Set.of(IndexedVorgang.FIELD_AKTENZEICHEN, IndexedVorgang.FIELD_ASSIGNED_TO));
+
+				assertThat(script).contains(removeAktenzeichenScript, removeAssignedToScript);
+			}
+		}
+
+		@Nested
+		class TestBuildUpdateQueryWithScript {
+
+			@Mock
+			private UpdateQuery.Builder updateQuery;
+
+			@BeforeEach
+			void setup() {
+				when(updateQuery.withScript(any())).thenReturn(updateQuery);
+				when(updateQuery.withScriptType(any())).thenReturn(updateQuery);
+				doReturn(updateQuery).when(searchRepostitory).createUpdateBuilder(any());
+			}
+
+			@Test
+			void shouldSetScriptType() {
+				searchRepostitory.buildUpdateQueryWithScript(IndexedVorgangTestFactory.ID, "script");
+
+				verify(updateQuery).withScriptType(ScriptType.INLINE);
+			}
+
+			@Test
+			void shouldSetScript() {
+				var script = "script";
+
+				searchRepostitory.buildUpdateQueryWithScript(IndexedVorgangTestFactory.ID, script);
+
+				verify(updateQuery).withScript(script);
+			}
+
+			@Test
+			void shouldCallBuild() {
+				searchRepostitory.buildUpdateQueryWithScript(IndexedVorgangTestFactory.ID, "script");
+
+				verify(updateQuery).build();
+			}
+		}
+
+		@Nested
+		class TestGetFieldsToUpdate {
+
+			@Test
+			void shouldReturnFieldsToUpdate() {
+				var fieldsToUpdate = searchRepostitory.getFieldsToUpdate(createMap(IndexedVorgang.FIELD_AKTENZEICHEN, AKTENZEICHEN));
+
+				assertThat(fieldsToUpdate).containsOnly(MapEntry.entry(IndexedVorgang.FIELD_AKTENZEICHEN, AKTENZEICHEN));
+			}
+
+			@Test
+			void shouldReturnEmptyFieldsToUpdate() {
+				var fieldsToUpdate = searchRepostitory.getFieldsToUpdate(createMap(IndexedVorgang.FIELD_ASSIGNED_TO, null));
+
+				assertThat(fieldsToUpdate).isEmpty();
+			}
+
+			private Map<String, Object> createMap(String key, Object value) {
+				var map = new HashMap<String, Object>();
+				map.put(key, value);
+				return map;
+			}
+		}
+
+		@Nested
+		class TestBuildUpdateQueryWithDocument {
+
+			@Mock
+			private UpdateQuery.Builder updateQuery;
+			@Mock
+			private Document document;
+
+			@BeforeEach
+			void setup() {
+				when(updateQuery.withDocument(any())).thenReturn(updateQuery);
+				doReturn(updateQuery).when(searchRepostitory).createUpdateBuilder(any());
+			}
+
+			@Test
+			void shouldSetDocument() {
+				Map<String, Object> patch = Map.of(IndexedVorgang.FIELD_AKTENZEICHEN, AKTENZEICHEN);
+				try(var fromMock = mockStatic(Document.class)) {
+					fromMock.when(() -> Document.from(any())).thenReturn(document);
+
+					searchRepostitory.buildUpdateQueryWithDocument(IndexedVorgangTestFactory.ID, patch);
+
+					verify(updateQuery).withDocument(document);
+				}
+			}
+
+			@Test
+			void shouldCallBuild() {
+				searchRepostitory.buildUpdateQueryWithDocument(IndexedVorgangTestFactory.ID, Map.of());
+
+				verify(updateQuery).build();
+			}
+		}
+
+		@Nested
+		class TestExecuteUpdate {
+
+			@Mock
+			private UpdateQuery updateQuery;
+			@Mock
+			private IndexOperations indexOperations;
+			@Mock
+			private IndexCoordinates indexCoordinates;
+
+			@BeforeEach
+			void setup() {
+				when(indexOperations.getIndexCoordinates()).thenReturn(indexCoordinates);
+				when(operations.indexOps(any(Class.class))).thenReturn(indexOperations);
+			}
+
+			@Test
+			void shouldCallUpdate() {
+				searchRepostitory.executeUpdate(updateQuery);
+
+				verify(operations).update(updateQuery, indexCoordinates);
+			}
+		}
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchVorgangRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangRepositoryITCase.java
similarity index 74%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchVorgangRepositoryITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangRepositoryITCase.java
index 8d7a034ba38a7b1d5f1b771cb9fad3968cf429fa..b72029c0676b1bc734fda1bf0fa5a5ee2a661efc 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/search/SearchVorgangRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/search/SearchVorgangRepositoryITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,27 +21,25 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.search;
+package de.ozgcloud.vorgang.common.search;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.List;
 
-import org.elasticsearch.core.List;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
-import org.springframework.test.context.ContextConfiguration;
-
-import de.itvsh.kop.common.test.ITCase;
+import org.springframework.test.context.junit.jupiter.DisabledIf;
 
-@ITCase
-@ContextConfiguration(initializers = SearchInitializer.class)
-@Disabled("Wegen hohem Speicherverbrauch des testcontainers")
+@DisabledIf(expression = "${elasticTests.disabled:false}", reason = "Wegen hohem Speicherverbrauch des testcontainers")
+@SearchITCase
 class SearchVorgangRepositoryITCase {
+
 	@Autowired
-	private SearchVorgangRepostitory repostitory;
+	private SearchVorgangRepository repostitory;
 
 	@Autowired
 	private ElasticsearchOperations elasticsearchOperations;
@@ -50,7 +48,7 @@ class SearchVorgangRepositoryITCase {
 	void initDatabase() {
 		elasticsearchOperations.indexOps(IndexedVorgang.class).delete();
 
-		repostitory.saveAll(List.of(IndexedVorgangTestFactory.create()));
+		repostitory.save(IndexedVorgangTestFactory.create());
 	}
 
 	@Nested
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/security/PolicyRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyRepositoryITCase.java
similarity index 77%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/security/PolicyRepositoryITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyRepositoryITCase.java
index fd38e7350e6479ea07eff89b5cd7f01a1ff46107..c3032923d2dca14614a70ae588fe546998afe2fc 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/security/PolicyRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyRepositoryITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.security;
+package de.ozgcloud.vorgang.common.security;
 
 import static org.assertj.core.api.Assertions.*;
 
 import java.util.List;
 
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -34,15 +35,16 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemTestFactory;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.files.GridFsTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelleTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.files.GridFsTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
 
 @DataITCase
 class PolicyRepositoryITCase {
@@ -124,6 +126,19 @@ class PolicyRepositoryITCase {
 
 				assertThat(result).isFalse();
 			}
+
+			@Test
+			void shouldThrowNotFoundIfDeleted() {
+				var vorgangAttachedItem = mongoOperations.save(
+						VorgangAttachedItemTestFactory.createBuilder().id(null).deleted(true).version(0).build());
+				var id = vorgangAttachedItem.getId();
+
+				Assertions.assertThrows(NotFoundException.class, () -> existsByVorgangAttachedItem(id));
+			}
+
+			private void existsByVorgangAttachedItem(String vorgangAttachedItemId) {
+				repository.existsByVorgangAttachedItem(vorgangAttachedItemId, List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+			}
 		}
 
 		@DisplayName("by file id")
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyRepositoryTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyRepositoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a56ccd337e7378f1a7bf186756d1caa8071dc0bc
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyRepositoryTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.security;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.List;
+
+import org.bson.Document;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
+
+class PolicyRepositoryTest {
+
+	@InjectMocks
+	private PolicyRepository repository;
+
+	@Mock
+	private MongoTemplate mongoTemplate;
+
+	@Nested
+	class TestEvaluateOrganisationseinheitId {
+
+		@Nested
+		class TestMatch {
+
+			@Test
+			void shouldEvaluateVorgang() {
+				var document = new Document(PolicyRepository.FIELD_ORGANISATIONSEINHEIT_ID,
+						List.of(List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)));
+
+				var result = repository.evaluateOrganisationseinheitId(document, List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+
+				assertThat(result).isTrue();
+			}
+
+			@Test
+			void shouldEvaluateVorgangStub() {
+				var document = new Document(PolicyRepository.FIELD_ORGANISATIONSEINHEIT_ID,
+						List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+
+				var result = repository.evaluateOrganisationseinheitId(document, List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+
+				assertThat(result).isTrue();
+			}
+		}
+
+		@Test
+		void  shouldReturnFalseIfNoMatch() {
+			var document = new Document(PolicyRepository.FIELD_ORGANISATIONSEINHEIT_ID,
+					List.of(List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)));
+
+			var result = repository.evaluateOrganisationseinheitId(document, List.of("otherId"));
+
+			assertThat(result).isFalse();
+		}
+
+		@Test
+		void shouldReturnFalseIfEmpty() {
+			var document = new Document(PolicyRepository.FIELD_ORGANISATIONSEINHEIT_ID, List.of());
+
+			var result = repository.evaluateOrganisationseinheitId(document, List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+
+			assertThat(result).isFalse();
+		}
+
+		@Test
+		void shouldReturnFalseIfNestedEmpty() {
+			var document = new Document(PolicyRepository.FIELD_ORGANISATIONSEINHEIT_ID, List.of(List.of()));
+
+			var result = repository.evaluateOrganisationseinheitId(document, List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+
+			assertThat(result).isFalse();
+		}
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/security/PolicyServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyServiceTest.java
similarity index 94%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/common/security/PolicyServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyServiceTest.java
index 487aa2992e92138d2c34d993ce2ee66f182646ca..92e1edaccc5cc010663fe184bff1031754ddd874 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/security/PolicyServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/security/PolicyServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.common.security;
+package de.ozgcloud.vorgang.common.security;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
@@ -44,17 +44,17 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.springframework.security.access.AccessDeniedException;
 
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItemTestFactory;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUser;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.files.GridFsTestFactory;
-import de.itvsh.ozg.pluto.files.OzgFileTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextUser;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.files.GridFsTestFactory;
+import de.ozgcloud.vorgang.files.OzgFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class PolicyServiceTest {
 
@@ -160,7 +160,7 @@ class PolicyServiceTest {
 				}
 
 				@Test
-				void shouldThrowAccessDeniedExceptionOnAllNonMatch() {
+				void shouldThrowNotFoundException() {
 					when(repository.existsByVorgangAttachedItem(any(), any())).thenReturn(false);
 
 					assertThrows(AccessDeniedException.class, () -> service.checkPermissionByVorgangAttachedItem(VorgangAttachedItemTestFactory.ID));
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/GrpcGetSupportedOrganisationEinheitenResponseTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/GrpcGetSupportedOrganisationEinheitenResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8913f236501fb3d5e7c350bf8be6e919f66be82
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/GrpcGetSupportedOrganisationEinheitenResponseTestFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.userconfig;
+
+import de.ozgcloud.user.grpc.organisationseinheit.GrpcGetSupportedOrganisationsEinheitenResponse;
+import de.ozgcloud.user.organisationseinheit.GrpcOrganisationsEinheit;
+
+public class GrpcGetSupportedOrganisationEinheitenResponseTestFactory {
+	public static String ORGANISATIONS_EINHEIT_ID = "123456";
+
+	public static GrpcGetSupportedOrganisationsEinheitenResponse create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcGetSupportedOrganisationsEinheitenResponse.Builder createBuilder() {
+		return GrpcGetSupportedOrganisationsEinheitenResponse.newBuilder()
+				.addOrganisationseinheiten(GrpcOrganisationsEinheit.newBuilder().setOrganisationsEinheitId(ORGANISATIONS_EINHEIT_ID).build());
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/UserConfigRemoteServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/UserConfigRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..559d81dbf234b61dff2f79ec4331b74933a87a57
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/UserConfigRemoteServiceTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.userconfig;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.user.grpc.organisationseinheit.OrganisationsEinheitServiceGrpc.OrganisationsEinheitServiceBlockingStub;
+import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor;
+
+class UserConfigRemoteServiceTest {
+	@Spy
+	@InjectMocks
+	private UserConfigRemoteService remoteService;
+
+	@Mock
+	private OrganisationsEinheitServiceBlockingStub stub;
+
+	@DisplayName("Test getting Organsiationseinheiten Ids of the users")
+	@Nested
+	class TestGettingOrganisationsEinheitenIds {
+		@BeforeEach
+		void init() {
+			when(stub.getSupportedOrganisationsEinheiten(any()))
+					.thenReturn(GrpcGetSupportedOrganisationEinheitenResponseTestFactory.create());
+			when(stub.withInterceptors(any())).thenReturn(stub);
+		}
+
+		@Test
+		void shouldGetOrganisationsEinheiten() {
+			var organisationsEinheiten = remoteService.getSupportedOrganisationsEinheiten();
+
+			assertThat(organisationsEinheiten).hasSize(1)
+					.contains(GrpcGetSupportedOrganisationEinheitenResponseTestFactory.ORGANISATIONS_EINHEIT_ID);
+		}
+
+		@Test
+		void shouldUseInterceptor() {
+			remoteService.getSupportedOrganisationsEinheiten();
+
+			verify(stub).withInterceptors(any(VorgangManagerClientCallContextAttachingInterceptor.class));
+		}
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/UserConfigServiceTest.java
similarity index 64%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandEventListenerTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/UserConfigServiceTest.java
index a13e3fb3717038b66c5814a590354e73e9fc96f2..357659d36c4a3976bbbc591b3be80fb51e3821f2 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/command/CommandEventListenerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/common/userconfig/UserConfigServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,32 +21,33 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.command;
+package de.ozgcloud.vorgang.common.userconfig;
 
 import static org.mockito.Mockito.*;
 
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 
-class CommandEventListenerTest {
-
-	@InjectMocks // NOSONAR
-	private CommandEventListener listener;
+class UserConfigServiceTest {
+	@Spy
+	@InjectMocks
+	private UserConfigService userConfigService;
 
 	@Mock
-	private CommandService commandService;
+	private UserConfigRemoteService userConfigRemoteService;
 
+	@DisplayName("Test invocation of user config remote service")
 	@Nested
-	class TestCommandExecutedEventListener {
-
+	class TestUserConfigService {
 		@Test
-		void shouldSetStatusFinished() {
-			listener.setStatusFinished(
-					CommandExecutedEventTestFactory.createFor(CommandTestFactory.create()));
+		void shouldCallUserConfigRemoteService() {
+			userConfigService.getSupportedOrganisationsEinheiten();
 
-			verify(commandService).setCommandFinished(CommandTestFactory.ID);
+			verify(userConfigRemoteService).getSupportedOrganisationsEinheiten();
 		}
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileITCase.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileITCase.java
index 4b2c66fe1c2e2283b8ad32c7116831e23e00b84f..6b624485d403fbbbe3c04a22e62a919a1b3b0082 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
@@ -54,18 +54,18 @@ import org.springframework.test.annotation.DirtiesContext;
 import com.google.protobuf.ByteString;
 import com.mongodb.client.gridfs.model.GridFSFile;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.common.callcontext.TestCallContextAttachingInterceptor;
-import de.itvsh.ozg.pluto.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceBlockingStub;
-import de.itvsh.ozg.pluto.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceStub;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcFindFilesResponse;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileMetaData;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileResponse;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.callcontext.TestCallContextAttachingInterceptor;
+import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceBlockingStub;
+import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc.BinaryFileServiceStub;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcFindFilesResponse;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileMetaData;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileResponse;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.StatusRuntimeException;
 import io.grpc.stub.StreamObserver;
 import lombok.AccessLevel;
@@ -122,9 +122,6 @@ public class BinaryFileITCase {
 
 				assertThat(file.getId()).isEqualTo(fileId.toHexString());
 				assertThat(file.getName()).isEqualTo(OzgFileTestFactory.NAME);
-				// FIXME
-				// assertThat(file.getSize()).isEqualTo(OzgFileTestFactory.SIZE);
-				//
 				assertThat(file.getContentType()).isEqualTo(OzgFileTestFactory.CONTENT_TYPE);
 			}
 		}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileRepositoryITCase.java
similarity index 73%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileRepositoryITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileRepositoryITCase.java
index b81dd7d70ec31308c444b91e8dc71986a346b5ac..94cd6a4ebccf1c349fb59a90f0dc888700dbf20d 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileRepositoryITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -40,19 +40,26 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoTemplate;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 @DataITCase
 class BinaryFileRepositoryITCase {
 
 	@Autowired
-	private BinaryFileRepository gridFsService;
+	private BinaryFileRepository repository;
 
 	@Autowired
 	private MongoTemplate template;
 
+	@BeforeEach
+	void clearDB() {
+		template.dropCollection("fs.files");
+		template.dropCollection("fs.chunks");
+	}
+
 	@Nested
 	class TestUploadFile {
 		private UploadedFilesReference ref;
@@ -60,9 +67,6 @@ class BinaryFileRepositoryITCase {
 
 		@BeforeEach
 		void init() {
-			template.dropCollection("fs.files");
-			template.dropCollection("fs.chunks");
-
 			ref = UploadedFilesReference.builder()
 					.client("client")
 					.name("test.file")
@@ -75,7 +79,7 @@ class BinaryFileRepositoryITCase {
 		void shouldStoreFiles() throws IOException {
 			FileId id = storeFile(45);
 
-			assertThat(gridFsService.getFileContent(id)).isNotEmpty();
+			assertThat(repository.getFileContent(id)).isNotEmpty();
 		}
 
 		@Test
@@ -85,7 +89,7 @@ class BinaryFileRepositoryITCase {
 
 			FileId id = storeFile(savedFileMB);
 
-			InputStream in = gridFsService.getFileContent(id);
+			InputStream in = repository.getFileContent(id);
 			byte[] buffer = in.readAllBytes();
 
 			assertThat(buffer).hasSize(fileSizeInBytes);
@@ -94,7 +98,7 @@ class BinaryFileRepositoryITCase {
 		private FileId storeFile(int sizeInMB) throws IOException {
 			InputStream stream = IncomingFileTestFactory.createContentStreamInMB(sizeInMB);
 
-			FileId id = gridFsService.addContentStream(ref, file, Optional.empty(), stream);
+			FileId id = repository.addContentStream(ref, file, Optional.empty(), stream);
 			stream.close();
 			return id;
 		}
@@ -105,12 +109,6 @@ class BinaryFileRepositoryITCase {
 
 		private FileId fileId;
 
-		@BeforeEach
-		void deleteAll() {
-			template.dropCollection("fs.files");
-			template.dropCollection("fs.chunks");
-		}
-
 		@Nested
 		class TestSingleMetaData {
 
@@ -170,12 +168,42 @@ class BinaryFileRepositoryITCase {
 		}
 
 		private FileId initContentStream(OzgFile ozgFile) {
-			return gridFsService.addContentStream(UploadedFilesReferenceTestFactory.create(), ozgFile, Optional.of(UserTestFactory.ID),
+			return repository.addContentStream(UploadedFilesReferenceTestFactory.create(), ozgFile, Optional.of(UserTestFactory.ID),
 					new ByteArrayInputStream(OzgFileTestFactory.CONTENT));
 		}
 
 		private Stream<OzgFile> callRepository(Collection<String> fileIds) {
-			return gridFsService.getAll(fileIds);
+			return repository.getAll(fileIds);
+		}
+	}
+
+	@Nested
+	class TestDeleteByVorgang {
+		@Test
+		void shouldDeleteFiles() {
+			var fileId = persistFile();
+
+			repository.deleteAllByVorgang(VorgangTestFactory.ID);
+
+			var loaded = repository.getFile(fileId);
+			assertThat(loaded).isNull();
+		}
+
+		@Test
+		void shouldNotDeleteOtherFiles() {
+			var fileId = persistFile();
+
+			repository.deleteAllByVorgang("other");
+
+			var loaded = repository.getFile(fileId);
+			assertThat(loaded).isNotNull();
+		}
+
+		private FileId persistFile() {
+			return repository.addContentStream(UploadedFilesReferenceTestFactory.create(),
+					OzgFileTestFactory.create(),
+					Optional.of(UserTestFactory.ID),
+					new ByteArrayInputStream(OzgFileTestFactory.CONTENT));
 		}
 	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileRepositoryTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileRepositoryTest.java
similarity index 84%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileRepositoryTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileRepositoryTest.java
index 7f60918248b23f03aa7d7dbae10f49723aa31954..021205d647d8858c78ef15b4389bd445a1a6c785 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/BinaryFileRepositoryTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/BinaryFileRepositoryTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Collections;
+import java.util.List;
 
+import org.apache.commons.lang3.StringUtils;
 import org.bson.Document;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
@@ -38,10 +41,10 @@ import org.springframework.data.mongodb.gridfs.GridFsTemplate;
 
 import static org.assertj.core.api.Assertions.*;
 
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class BinaryFileRepositoryTest {
 
@@ -145,6 +148,22 @@ class BinaryFileRepositoryTest {
 			assertThat(files).hasSize(1);
 		}
 
+		@Test
+		@DisplayName("should not map to OZG File when FileId is empty")
+		void shouldNotMapWhenFileIdEmpty() {
+			grisFsService.getAll(List.of(StringUtils.EMPTY)).toList();
+
+			verify(grisFsService, never()).mapToOzgFile(any());
+		}
+
+		@Test
+		@DisplayName("should not map to OZG File when FileId is null")
+		void shouldNotMapWhenFileIdNull() {
+			grisFsService.getAll(Collections.singletonList(null)).toList();
+
+			verify(grisFsService, never()).mapToOzgFile(any());
+		}
+
 		@Nested
 		class TestMapToOzgFile {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/EingangFilesRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/EingangFilesRepositoryITCase.java
similarity index 89%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/EingangFilesRepositoryITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/EingangFilesRepositoryITCase.java
index ac2ca8c3229745d14b0c21201adb394acbe6756b..2361337c22635c373f20092b6d84eb733d2eca7c 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/EingangFilesRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/EingangFilesRepositoryITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -33,13 +33,13 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.vorgang.EingangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFile;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileGroupTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFile;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroupTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 @DataITCase
 class EingangFilesRepositoryITCase {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileITCase.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileITCase.java
index 8382210f944039729e763f136d1cee4942ca4e6f..748a5a65d28a7853af2aa6f2e12170afcb30068a 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
@@ -37,17 +37,17 @@ import org.mockito.Mock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetAttachmentsRequest;
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetAttachmentsResponse;
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetRepresentationsRequest;
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetRepresentationsResponse;
-import de.itvsh.ozg.pluto.vorgang.EingangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFile;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileGroupTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetAttachmentsRequest;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetAttachmentsResponse;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetRepresentationsRequest;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetRepresentationsResponse;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFile;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroupTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.stub.StreamObserver;
 
 @DataITCase
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileServiceTest.java
similarity index 61%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileServiceTest.java
index 1243b2cca0f2e3bb2022c39fe07e39548b413e30..f6e6b71677fabf29c2ba12073acd9e594454ee8c 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/FileServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/FileServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,28 +21,33 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 class FileServiceTest {
 
+	@Spy
 	@InjectMocks
 	private FileService service;
 
@@ -53,10 +58,38 @@ class FileServiceTest {
 	@Mock
 	private FileIdMapper fileIdMapper;
 
+	private final UploadedFilesReference ref = UploadedFilesReferenceTestFactory.create();
+	private final Optional<String> user = Optional.empty();
+	private final OzgFile file = OzgFileTestFactory.create();
+	private final InputStream contentStream = new ByteArrayInputStream(IncomingFileTestFactory.CONTENT);
+
+	@DisplayName("Upload filestream")
+	@Nested
+	class TestUploadFileStream {
+
+		@Test
+		void shouldCallUploadFile() {
+			service.uploadFileStream(ref, file, user, contentStream);
+
+			verify(service).uploadFile(ref, file, user, contentStream);
+		}
+	}
+
+	@DisplayName("upload filestream async")
+	@Nested
+	class TestUploadFileStreamAsync {
+
+		@Test
+		void shouldCallUploadFile() {
+			service.uploadFileStream(ref, file, user, contentStream);
+
+			verify(service).uploadFile(ref, file, user, contentStream);
+		}
+	}
+
+	@DisplayName("Upload file")
 	@Nested
-	class TestUploadFileAsStream {
-		private UploadedFilesReference ref = UploadedFilesReferenceTestFactory.create();
-		private OzgFile file = OzgFileTestFactory.create();
+	class TestUploadFile {
 
 		@BeforeEach
 		void init() {
@@ -65,21 +98,21 @@ class FileServiceTest {
 
 		@Test
 		void shouldCallAddContentSream() {
-			service.uploadFileStream(ref, file, Optional.empty(), new ByteArrayInputStream(IncomingFileTestFactory.CONTENT));
+			service.uploadFileStream(ref, file, user, contentStream);
 
-			verify(binaryFileRepository).addContentStream(any(), any(), any(), any());
+			verify(binaryFileRepository).addContentStream(ref, file, user, contentStream);
 		}
 
 		@Test
 		void shouldAddContent() {
-			service.uploadFileStream(ref, file, Optional.empty(), new ByteArrayInputStream(IncomingFileTestFactory.CONTENT));
+			service.uploadFileStream(ref, file, user, contentStream);
 
-			verify(binaryFileRepository).addContentStream(any(), any(), any(), any());
+			verify(binaryFileRepository).addContentStream(ref, file, user, contentStream);
 		}
 
 		@Test
 		void shouldReturnId() throws Exception {
-			var id = service.uploadFileStream(ref, file, Optional.empty(), new ByteArrayInputStream(IncomingFileTestFactory.CONTENT)).get(5,
+			var id = service.uploadFileStream(ref, file, user, contentStream).get(5,
 					TimeUnit.SECONDS);
 
 			assertThat(id).isEqualTo(IncomingFileTestFactory.ID);
@@ -121,4 +154,14 @@ class FileServiceTest {
 			verify(binaryFileRepository).getAll(Collections.singletonList(OzgFileTestFactory.ID.toString()));
 		}
 	}
+
+	@Nested
+	class TestDeleteAllByVorgang {
+		@Test
+		void shouldCallRepository() {
+			service.deleteAllByVorgang(VorgangTestFactory.ID);
+
+			verify(binaryFileRepository).deleteAllByVorgang(VorgangTestFactory.ID);
+		}
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GridFsTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GridFsTestFactory.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GridFsTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GridFsTestFactory.java
index 813880b01e7be182a5c17d5ca68686276dcbaa85..0285a2d553048f1fd5b1268846de9aba51220948 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GridFsTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GridFsTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.io.ByteArrayInputStream;
 import java.util.Date;
@@ -33,9 +33,9 @@ import org.springframework.data.mongodb.util.BsonUtils;
 
 import com.mongodb.client.gridfs.model.GridFSFile;
 
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class GridFsTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcBinaryFileServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcBinaryFileServiceTest.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcBinaryFileServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcBinaryFileServiceTest.java
index 2deb779af18f097b9c6838d9b38d168c07ddf3ee..294bf00f1aaea68c00e23b91b5dedc22a742cb7c 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcBinaryFileServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcBinaryFileServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -36,6 +36,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
@@ -45,13 +46,13 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcFindFilesResponse;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileMetaData;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileResponse;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcFindFilesResponse;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileMetaData;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileResponse;
 import io.grpc.stub.CallStreamObserver;
 import io.grpc.stub.ServerCallStreamObserver;
 import io.grpc.stub.StreamObserver;
@@ -114,8 +115,10 @@ class GrpcBinaryFileServiceTest {
 		}
 	}
 
+	@DisplayName("Upload filestream async")
 	@Nested
-	class TestUploadFileStream {
+	class TestUploadFileStreamAsync {
+
 		private static final int FILE_SIZE = 5 * 1_000_000;
 
 		@Mock
@@ -129,14 +132,14 @@ class GrpcBinaryFileServiceTest {
 
 		@BeforeEach
 		void init() {
-			when(service.uploadFileStream(any(), any(), any(), any())).thenReturn(CompletableFuture.supplyAsync(() -> FileId.createNew()));
+			when(service.uploadFileStreamAsync(any(), any(), any(), any())).thenReturn(CompletableFuture.supplyAsync(() -> FileId.createNew()));
 		}
 
 		@Test
 		void shouldCallService() throws IOException {
 			uploadFile(FILE_SIZE);
 
-			verify(service, timeout(500)).uploadFileStream(any(), any(), any(), any());
+			verify(service, timeout(500)).uploadFileStreamAsync(any(), any(), any(), any());
 		}
 
 		@Test
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcBinaryFilesRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcBinaryFilesRequestTestFactory.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcBinaryFilesRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcBinaryFilesRequestTestFactory.java
index 2790309a32b8ea5f0d3ea7c29a39aa0851b851b1..278c394b84997fdafbe2b968071161327a200816 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcBinaryFilesRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcBinaryFilesRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcBinaryFilesRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcBinaryFilesRequest;
 
 public class GrpcBinaryFilesRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetAttachmentsRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetAttachmentsRequestTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetAttachmentsRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetAttachmentsRequestTestFactory.java
index b0c40eb8d6463611f8f9576702d22be9dfb0e70a..531b25408d71ad17320c012903a0ec45e6782d25 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetAttachmentsRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetAttachmentsRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetAttachmentsRequest;
-import de.itvsh.ozg.pluto.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetAttachmentsRequest;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
 
 public class GrpcGetAttachmentsRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetBinaryFileDataRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetBinaryFileDataRequestTestFactory.java
similarity index 84%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetBinaryFileDataRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetBinaryFileDataRequestTestFactory.java
index 3f0e881c32cee9e1172175d6d6e41d6703d937e5..21a925c240aca2c18c46fa8005e04d406d504297 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetBinaryFileDataRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetBinaryFileDataRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
-import de.itvsh.ozg.pluto.command.GrpcCallContextTestFactory;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
+import de.ozgcloud.vorgang.command.GrpcCallContextTestFactory;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
 
 class GrpcGetBinaryFileDataRequestTestFactory {
 	static final String FILE_ID = FileId.createNew().toString();
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetRepresentationsRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetRepresentationsRequestTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetRepresentationsRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetRepresentationsRequestTestFactory.java
index 3d04ab0dce61f015234f7897dc8b23d01f4a7011..91a7b56731a6e7ff39ee0379e3c31586ce999097 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcGetRepresentationsRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcGetRepresentationsRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
-import de.itvsh.ozg.pluto.grpc.file.GrpcGetRepresentationsRequest;
-import de.itvsh.ozg.pluto.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.grpc.file.GrpcGetRepresentationsRequest;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
 
 public class GrpcGetRepresentationsRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcOzgFileMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcOzgFileMapperTest.java
similarity index 90%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcOzgFileMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcOzgFileMapperTest.java
index dabe7fff286a39ef1680195c315824694e0212d3..37fc98e7bdc220ad7b0f9aa826969442092d9dd3 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcOzgFileMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcOzgFileMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -32,7 +32,7 @@ import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.grpc.file.GrpcOzgFile;
+import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
 
 class GrpcOzgFileMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadBinaryFileMetaDataTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadBinaryFileMetaDataTestFactory.java
similarity index 83%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadBinaryFileMetaDataTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadBinaryFileMetaDataTestFactory.java
index 4d52585aa659b3b7fd352c0c14c75c311a1ff3c2..08ff40405bc2f9e248b836b2bf03b8a3e8bc23ea 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadBinaryFileMetaDataTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadBinaryFileMetaDataTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
-import de.itvsh.ozg.pluto.command.GrpcCallContextTestFactory;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileMetaData;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.command.GrpcCallContextTestFactory;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileMetaData;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class GrpcUploadBinaryFileMetaDataTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadBinaryFileRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadBinaryFileRequestTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadBinaryFileRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadBinaryFileRequestTestFactory.java
index 4cc88a23faba995faf093aaab25f64432f5a3c7a..29dbb42c3f6c83aefd5778817e80f10e37d8b914 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadBinaryFileRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadBinaryFileRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import com.google.protobuf.ByteString;
 
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
 
 public class GrpcUploadBinaryFileRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadedFilesReferencesTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadedFilesReferencesTestFactory.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadedFilesReferencesTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadedFilesReferencesTestFactory.java
index 43cc82d31bdc8cee02aabc7f740be1634abc4c65..604a2098ddb0993edcec8a36f7a3063b0a085b55 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/GrpcUploadedFilesReferencesTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/GrpcUploadedFilesReferencesTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
 
 public class GrpcUploadedFilesReferencesTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/OzgFileTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/OzgFileTestFactory.java
similarity index 90%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/OzgFileTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/OzgFileTestFactory.java
index 6cda8f7969d34b5229bd48c82f89acc5c6138442..209887e5fe7e66daecdec450e233af94bdc70609 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/OzgFileTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/OzgFileTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.util.Random;
 
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class OzgFileTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/UploadStreamObserverTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/UploadStreamObserverTest.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/UploadStreamObserverTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/UploadStreamObserverTest.java
index 3e961bc375235f055ef2d04dea352f0128bd0dd1..ce727080708fcaf65d3dd2030c10d91b498dc70b 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/UploadStreamObserverTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/UploadStreamObserverTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
@@ -43,12 +43,12 @@ import org.mockito.Mock;
 
 import com.google.protobuf.ByteString;
 
-import de.itvsh.kop.common.errorhandling.TechnicalException;
-import de.itvsh.ozg.pluto.common.security.PolicyService;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileRequest;
-import de.itvsh.ozg.pluto.grpc.binaryFile.GrpcUploadBinaryFileResponse;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.common.security.PolicyService;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcUploadBinaryFileResponse;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.stub.StreamObserver;
 
 class UploadStreamObserverTest {
@@ -153,7 +153,7 @@ class UploadStreamObserverTest {
 
 			@BeforeEach
 			void init() {
-				when(service.uploadFileStream(any(), any(), any(), any())).thenReturn(CompletableFuture.completedFuture(FileId.createNew()));
+				when(service.uploadFileStreamAsync(any(), any(), any(), any())).thenReturn(CompletableFuture.completedFuture(FileId.createNew()));
 			}
 
 			@Test
@@ -176,7 +176,7 @@ class UploadStreamObserverTest {
 				uploadStreamObserver.storeFileMetaData(fileUploadRequest, uploadStreamObserver.getPipedInput(),
 						uploadStreamObserver.getPipedOutput());
 
-				verify(service).uploadFileStream(any(), any(), any(), any());
+				verify(service).uploadFileStreamAsync(any(), any(), any(), any());
 			}
 		}
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/UploadedFilesReferenceTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/UploadedFilesReferenceTestFactory.java
similarity index 86%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/files/UploadedFilesReferenceTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/UploadedFilesReferenceTestFactory.java
index e999d0cf90c056b62a70e90dfa68d5a597cfc7ef..6ba171928a9e09ec720b093884684aa5d06936f0 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/files/UploadedFilesReferenceTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/files/UploadedFilesReferenceTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.files;
+package de.ozgcloud.vorgang.files;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class UploadedFilesReferenceTestFactory {
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..09aa437eaf2c1b6a826e9b02083f78419547123b
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/GrpcRegistrationResponseTestFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.registry;
+
+import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationResponse;
+
+public class GrpcRegistrationResponseTestFactory {
+	public static GrpcVorgangManagerRegistrationResponse create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcVorgangManagerRegistrationResponse.Builder createBuilder() {
+		return GrpcVorgangManagerRegistrationResponse.newBuilder().setSuccess(true);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistrySchedulerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistrySchedulerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5b53cc9dd5abcb3d3ad49a13b51829c74ee67ac1
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistrySchedulerTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.registry;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.vorgang.common.userconfig.UserConfigService;
+import io.grpc.StatusRuntimeException;
+
+class RegistrySchedulerTest {
+	private static final String ORGANISATION_EINHEITEN_ID = "123456";
+	private static final List<String> ORGANISATION_EINHEITEN_IDS = List.of(ORGANISATION_EINHEITEN_ID);
+
+	@Spy
+	@InjectMocks
+	private RegistryScheduler registryScheduler;
+
+	@Mock
+	private RegistryService registryService;
+
+	@Mock
+	private UserConfigService userConfigService;
+
+	@DisplayName("Test the registering the VorgangManager")
+	@Nested
+	class TestScheduler {
+
+		@Test
+		void shouldCallService() {
+			when(userConfigService.getSupportedOrganisationsEinheiten()).thenReturn(ORGANISATION_EINHEITEN_IDS);
+
+			registryScheduler.register();
+
+			verify(registryService).registerVorgangManager(anyList());
+		}
+
+		@Test
+		void shouldHandleExceptionWhenLoadingOrganisationEinheiten() {
+			when(userConfigService.getSupportedOrganisationsEinheiten()).thenThrow(StatusRuntimeException.class);
+
+			registryScheduler.register();
+
+			verify(registryService, never()).registerVorgangManager(anyList());
+		}
+
+		@Test
+		void shouldCallGetOrganisationEinheitenIds() {
+			when(userConfigService.getSupportedOrganisationsEinheiten()).thenReturn(ORGANISATION_EINHEITEN_IDS);
+
+			registryScheduler.register();
+
+			verify(userConfigService).getSupportedOrganisationsEinheiten();
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6404824b3f03cc9199eba477e8986ce9a4aa1dc8
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/RegistryServiceTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.registry;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.test.util.ReflectionTestUtils;
+
+class RegistryServiceTest {
+	private static final String ORGANISATION_EINHEITEN_ID = "123456";
+	private static final List<String> ORGANISATION_EINHEITEN_IDS = List.of(ORGANISATION_EINHEITEN_ID);
+	private static final Optional<String> VORGANG_MANAGER_ADDRESS = Optional.of("address");
+
+	@Spy
+	@InjectMocks
+	private RegistryService registryService;
+
+	@Mock
+	private ZufiRemoteService zufiRemoteService;
+
+	@DisplayName("Test registering the VorgangManager")
+	@Nested
+	class TestRegistryVorgangManager {
+		@BeforeEach
+		void initVorgangManagerAddress() {
+			ReflectionTestUtils.setField(registryService, "vorgangManagerAddress", VORGANG_MANAGER_ADDRESS);
+		}
+
+		@Test
+		void shouldCallZuFiRemoteService() {
+			registryService.registerVorgangManager(ORGANISATION_EINHEITEN_IDS);
+
+			verify(zufiRemoteService).registerVorgangManager(anyList(), any());
+		}
+
+		@Test
+		void shouldNotCallZuFiRemoteServiceOnEmptyOrganisationsEinheitenIds() {
+			registryService.registerVorgangManager(Collections.emptyList());
+
+			verify(zufiRemoteService, never()).registerVorgangManager(anyList(), any());
+		}
+
+		@Test
+		void shouldNotCallServiceStub() {
+			registryService.registerAddress(ORGANISATION_EINHEITEN_IDS, Optional.empty());
+
+			verify(zufiRemoteService, never()).registerVorgangManager(any(), any());
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..094dbeb3cf58b2236561fdd384a150a1bfa4e081
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/registry/ZufiRemoteServiceTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.registry;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.vorgang.callcontext.VorgangManagerClientCallContextAttachingInterceptor;
+import de.ozgcloud.zufi.grpc.registration.GrpcVorgangManagerRegistrationRequest;
+import de.ozgcloud.zufi.grpc.registration.VorgangManagerRegistrationServiceGrpc.VorgangManagerRegistrationServiceBlockingStub;
+
+class ZufiRemoteServiceTest {
+	private static final String ORGANISATIONS_EINHEITEN_ID = "123456";
+	private static final List<String> ORGANISATIONS_EINHEITEN_IDS = List.of(ORGANISATIONS_EINHEITEN_ID);
+	private static final String VORGANG_MANAGER_ADDRESS = "address";
+
+	@Spy
+	@InjectMocks
+	private ZufiRemoteService zufiRemoteService;
+
+	@Mock
+	private VorgangManagerRegistrationServiceBlockingStub serviceStub;
+
+	@DisplayName("Test ZuFiRemoteService when VorgangManager address is configured")
+	@Nested
+	class TestRegisteringVorgangManager {
+		@BeforeEach
+		void init() {
+			when(serviceStub.withInterceptors(any())).thenReturn(serviceStub);
+			when(serviceStub.register(any(GrpcVorgangManagerRegistrationRequest.class))).thenReturn(GrpcRegistrationResponseTestFactory.create());
+		}
+
+		@Test
+		void shouldCallServiceStub() {
+			zufiRemoteService.registerVorgangManager(ORGANISATIONS_EINHEITEN_IDS, VORGANG_MANAGER_ADDRESS);
+
+			verify(serviceStub).register(any(GrpcVorgangManagerRegistrationRequest.class));
+		}
+
+		@Test
+		void shouldUseInterceptor() {
+			zufiRemoteService.registerVorgangManager(ORGANISATIONS_EINHEITEN_IDS, VORGANG_MANAGER_ADDRESS);
+
+			verify(serviceStub).withInterceptors(any(VorgangManagerClientCallContextAttachingInterceptor.class));
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/GrpcPostfachAddressTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/GrpcPostfachAddressTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b21f6ba0149f0cb4788c10a2bdeff75a13d9af4
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/GrpcPostfachAddressTestFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.servicekonto;
+
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.common.GrpcProperty;
+import de.ozgcloud.vorgang.vorgang.GrpcPostfachAddress;
+
+public class GrpcPostfachAddressTestFactory {
+
+	public static GrpcPostfachAddress create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcPostfachAddress.Builder createBuilder() {
+		return GrpcPostfachAddress.newBuilder()
+				.setType(PostfachAddressTestFactory.TYPE)
+				.setIdentifier(createStringBasedIdentifier())
+				.setVersion(PostfachAddressTestFactory.VERSION);
+	}
+
+	private static GrpcObject createStringBasedIdentifier() {
+		return GrpcObject.newBuilder()
+				.addProperty(GrpcProperty.newBuilder()
+						.setName(PostfachAddress.IDENTIFIER_POSTFACH_ID_FIELD)
+						.addValue(PostfachAddressTestFactory.STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE)
+						.build())
+				.build();
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/GrpcServiceKontoTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/GrpcServiceKontoTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a3198d581240b49fbbeef6f0fa2adc20c50dc120
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/GrpcServiceKontoTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.servicekonto;
+
+import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto;
+
+public class GrpcServiceKontoTestFactory {
+
+	public static GrpcServiceKonto create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcServiceKonto.Builder createBuilder() {
+		return GrpcServiceKonto.newBuilder()
+				.setType(ServiceKontoTestFactory.TYPE)
+				.addPostfachAddresses(GrpcPostfachAddressTestFactory.create());
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/PostfachAddressTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/PostfachAddressTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..280f10c81a7f1ab7709ca181e00ead4675b2e05f
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/PostfachAddressTestFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.servicekonto;
+
+import java.util.Map;
+import java.util.UUID;
+
+public class PostfachAddressTestFactory {
+
+	public final static int TYPE = 1;
+	public static final String STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE = UUID.randomUUID().toString();
+	public static final Map<String, Object> IDENTIFIER = Map.of(PostfachAddress.IDENTIFIER_POSTFACH_ID_FIELD,
+			STRING_BASED_IDENTIFIER_POSTFACH_ID_VALUE);
+	public static final String VERSION = "1.0";
+
+	public static PostfachAddress create() {
+		return createBuilder().build();
+	}
+
+	public static PostfachAddress.PostfachAddressBuilder createBuilder() {
+		return PostfachAddress.builder()
+				.type(TYPE)
+				.identifier(IDENTIFIER)
+				.version(VERSION);
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2a6f5fe35137e335ece6deb5c3fb14d17709e68
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoMapperTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.servicekonto;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+import org.mockito.Spy;
+
+import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
+import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto;
+
+class ServiceKontoMapperTest {
+
+	@InjectMocks
+	private ServiceKontoMapper mapper = Mappers.getMapper(ServiceKontoMapper.class);
+	@Spy
+	private GrpcObjectMapper grpcObjectMapper = Mappers.getMapper(GrpcObjectMapper.class);
+
+	@DisplayName("From serviceKonto")
+	@Nested
+	class TestFromServiceKonto {
+
+		@Test
+		void shouldMapFields() {
+			var serviceKonto = fromServiceKonto();
+
+			assertThat(serviceKonto).usingRecursiveComparison().isEqualTo(ServiceKontoTestFactory.create());
+		}
+
+		private ServiceKonto fromServiceKonto() {
+			return mapper.fromServiceKonto(GrpcServiceKontoTestFactory.create());
+		}
+	}
+
+	@DisplayName("to serviceKonto")
+	@Nested
+	class TestToServiceKonto {
+
+		@Test
+		void shouldMapFields() {
+			var serviceKonto = toServiceKonto();
+
+			assertThat(serviceKonto).usingRecursiveComparison().isEqualTo(GrpcServiceKontoTestFactory.create());
+		}
+
+		private GrpcServiceKonto toServiceKonto() {
+			return mapper.toServiceKonto(ServiceKontoTestFactory.create());
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..1235c5ffa50636dce7e2d6e179e91d5db9b02552
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/servicekonto/ServiceKontoTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.servicekonto;
+
+public class ServiceKontoTestFactory {
+
+	public final static String TYPE = "OSI";
+
+	public static ServiceKonto create() {
+		return createBuilder().build();
+	}
+
+	public static ServiceKonto.ServiceKontoBuilder createBuilder() {
+		return ServiceKonto.builder()
+				.type(TYPE)
+				.postfachAddress(PostfachAddressTestFactory.create());
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountByPathTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountByPathTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7cc5fc3f4e496e6d2ea7767063c14fb8b686120
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountByPathTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class CountByPathTest {
+
+	@Test
+	void shouldSetFieldPath() {
+		var countByPath = CountByPath.fromStatisticRequest(VorgangStatisticRequestTestFactory.create());
+
+		assertThat(countByPath.getFieldPath()).isEqualTo(VorgangStatisticRequestTestFactory.REQUEST_FIELD_PATH);
+	}
+
+	@Test
+	void shouldSetAlias() {
+		var countByPath = CountByPath.fromStatisticRequest(VorgangStatisticRequestTestFactory.create());
+
+		assertThat(countByPath.getAlias()).isEqualTo(VorgangStatisticRequestTestFactory.RESULT_NAME);
+	}
+
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountByPathTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountByPathTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..41e9409a0be9aa33ff1926686c27f63e55e5fd0a
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountByPathTestFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import de.ozgcloud.vorgang.statistic.CountByPath.CountByPathBuilder;
+
+public class CountByPathTestFactory {
+	public static final String ALIAS = "attribute";
+	public static final String FIELD_PATH = "Vorgang.name";
+
+	public static final CountByPath create() {
+		return createBuilder().build();
+	}
+
+	public static final CountByPathBuilder createBuilder() {
+		return CountByPath.builder()
+				.alias(ALIAS);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountPathRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountPathRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..58306eb4d6ee11bc3a2e1bef0a4c4f2dfd71b440
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountPathRequestTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import de.ozgcloud.vorgang.statistic.CountByPath.CountByPathBuilder;
+
+public class CountPathRequestTestFactory {
+
+	public static final String FIELD_PATH = "path";
+
+	public static CountByPath create() {
+		return createRequest().build();
+	}
+
+	public static CountByPathBuilder createRequest() {
+		return CountByPath.builder().fieldPath(FIELD_PATH).alias(CountResultTestFactory.NAME);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountResultTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountResultTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..8941a6ee8d54cf18704a4ade9974b02d54bb8eec
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountResultTestFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+public class CountResultTestFactory {
+
+	public static final String NAME = CountByPathTestFactory.ALIAS;
+	public static final int VALUE = 1;
+
+	public static CountResult create() {
+		return createBuilder().build();
+	}
+
+	public static CountResult.CountResultBuilder createBuilder() {
+		return CountResult.builder().name(NAME).value(VALUE);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountStatisticMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountStatisticMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f65d6f60d7421e0e061fc8e62e73a82d9839d7f
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/CountStatisticMapperTest.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Spy;
+
+class CountStatisticMapperTest {
+
+	@Spy
+	private CountStatisticMapper mapper = new CountStatisticMapper();
+
+	@DisplayName("Map to")
+	@Nested
+	class TestMapTo {
+
+		@DisplayName("path count result")
+		@Nested
+		class TestPathCountResult {
+
+			@Test
+			void shouldHaveSize() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getPathCountResultList()).hasSize(1);
+			}
+
+			@Test
+			void shouldHaveSetName() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getPathCountResultList().get(0).getName()).isEqualTo(StatisticTestFactory.FIELD_PATH_ALIAS);
+			}
+
+			@Test
+			void shouldHaveSetValue() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getPathCountResultList().get(0).getValue()).isEqualTo(StatisticTestFactory.FIELD_PATH_VALUE);
+			}
+		}
+
+		@Nested
+		@DisplayName("by status")
+		class TestMapByStatus {
+
+			@Test
+			@DisplayName("should map NEU status")
+			void shouldMapNeu() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getByStatus().getNeu()).isEqualTo(StatisticTestFactory.NEU_COUNT);
+			}
+
+			@Test
+			@DisplayName("should map ANGENOMMEN status")
+			void shouldMapAngenommen() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getByStatus().getAngenommen()).isEqualTo(StatisticTestFactory.ANGENOMMEN_COUNT);
+			}
+
+			@Test
+			@DisplayName("should map VERWORFEN status")
+			void shouldMapVerworfen() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getByStatus().getVerworfen()).isEqualTo(StatisticTestFactory.VERWORFEN_COUNT);
+			}
+
+			@Test
+			@DisplayName("should map IN_BEARBEITUNG status")
+			void shouldMapInBearbeitung() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getByStatus().getInBearbeitung()).isEqualTo(StatisticTestFactory.IN_BEARBEITUNG_COUNT);
+			}
+
+			@Test
+			@DisplayName("should map BESCHIEDEN status")
+			void shouldMapBeschieden() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getByStatus().getBeschieden()).isEqualTo(StatisticTestFactory.BESCHIEDEN_COUNT);
+			}
+
+			@Test
+			@DisplayName("should map ABGESCHLOSSEN status")
+			void shouldMapAbgeschlossen() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getByStatus().getAbgeschlossen()).isEqualTo(StatisticTestFactory.ABGESCHLOSSEN_COUNT);
+			}
+
+			@Test
+			@DisplayName("should map WEITERGELEITET status")
+			void shouldMapWeitergeleitet() {
+				var response = mapper.mapTo(StatisticTestFactory.create());
+
+				assertThat(response.getByStatus().getWeitergeleitet()).isEqualTo(StatisticTestFactory.WEITERGELEITET_COUNT);
+			}
+		}
+	}
+
+	@DisplayName("Map from gRPC request")
+	@Nested
+	class TestMapToRequest {
+
+		private final String countPath = CountResultTestFactory.NAME + ":" + CountPathRequestTestFactory.FIELD_PATH;
+
+		@Test
+		void shouldMapPath() {
+			var countRequest = mapper.mapPathCountRequest(countPath);
+
+			assertThat(countRequest).usingRecursiveComparison().isEqualTo(CountPathRequestTestFactory.create());
+		}
+
+		@Test
+		void shouldMapGrpcRequest() {
+			doReturn(CountPathRequestTestFactory.create()).when(mapper).mapPathCountRequest(anyString());
+			var grpcRequest = GrpcVorgangCountRequest.newBuilder().addCountByPath(countPath).build();
+
+			var request = mapper.mapFromVorgangCountRequest(grpcRequest);
+
+			assertThat(request.getCountByPaths()).hasSize(1).first().usingRecursiveComparison().isEqualTo(CountPathRequestTestFactory.create());
+		}
+
+		@Nested
+		@DisplayName("Extract request parts")
+		class TestExtract {
+
+			@Test
+			void shouldExtractFieldPath() {
+				var fieldPath = mapper.extractFieldPath(countPath);
+
+				assertThat(fieldPath).isEqualTo(CountPathRequestTestFactory.FIELD_PATH);
+			}
+
+			@Test
+			void shouldThrowExceptionOnInvalidPath() {
+				assertThrows(VorgangStatisticBadRequestException.class, () -> mapper.extractFieldPath(""));
+			}
+
+			@Test
+			void shouldExtractAlias() {
+				var alias = mapper.extractAlias(countPath);
+
+				assertThat(alias).isEqualTo(CountResultTestFactory.NAME);
+			}
+
+			@Test
+			void shouldThrowExceptionOnInvalidAlias() {
+				assertThrows(VorgangStatisticBadRequestException.class, () -> mapper.extractAlias("invalid"));
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticQueryTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticQueryTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..d66e87661606065cf4dd030eecf0f014838d30eb
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticQueryTestFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.GroupMethod;
+
+public class GrpcVorgangStatisticQueryTestFactory {
+
+	static final String OPERAND_STRING_VALUE = "NEU";
+	static final GroupMethod GROUP_METHOD = GroupMethod.COUNT;
+	static final String QUERY_PATH = "Vorgang.status";
+	static final String PATH = "status";
+	static final String RESULT_NAME = "countByStatusNeu";
+
+	static GrpcVorgangStatisticQuery create() {
+		return createBuilder().build();
+	}
+
+	static GrpcVorgangStatisticQuery.Builder createBuilder() {
+		return GrpcVorgangStatisticQuery.newBuilder()
+				.setResultName(RESULT_NAME)
+				.setGroupMethod(GROUP_METHOD)
+				.setPath(QUERY_PATH)
+				.setOperator(GrpcQueryOperator.EQUAL)
+				.setOperandStringValue(OPERAND_STRING_VALUE);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..afd7059e5b2892dc773252cb31915fbc947548ed
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticRequestTestFactory.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+class GrpcVorgangStatisticRequestTestFactory {
+
+	static GrpcVorgangStatisticRequest create() {
+		return createBuilder().build();
+	}
+
+	static GrpcVorgangStatisticRequest.Builder createBuilder() {
+		return GrpcVorgangStatisticRequest.newBuilder()
+				.addQuery(GrpcVorgangStatisticQueryTestFactory.create());
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticResponseTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticResponseTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0553a5616a2880acdccdb88bf4b39e58a4ae23e8
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticResponseTestFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+class GrpcVorgangStatisticResponseTestFactory {
+
+	static GrpcVorgangStatisticResponse create() {
+		return createBuilder().build();
+	}
+
+	static GrpcVorgangStatisticResponse.Builder createBuilder() {
+		return GrpcVorgangStatisticResponse.newBuilder()
+				.addResult(GrpcVorgangStatisticResultTestFactory.create());
+	}
+
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticResultTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticResultTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..26df9e6964e8540ecc945dc0149372d195da00f5
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/GrpcVorgangStatisticResultTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+class GrpcVorgangStatisticResultTestFactory {
+
+	static final int RESULT_INT_VALUE = 42;
+
+	static GrpcVorgangStatisticResult create() {
+		return createBuilder().build();
+	}
+
+	static GrpcVorgangStatisticResult.Builder createBuilder() {
+		return GrpcVorgangStatisticResult.newBuilder()
+				.setName(GrpcVorgangStatisticQueryTestFactory.RESULT_NAME)
+				.setResultIntValue(RESULT_INT_VALUE);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/OperatorTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/OperatorTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..05b8aa0c13e2217b19390823e14f87ca42dc3c90
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/OperatorTestFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+
+public class OperatorTestFactory {
+
+	public static Operator create() {
+		return createBuilder().build();
+	}
+
+	public static OperatorBuilder createBuilder() {
+		return OperatorBuilder
+				.from(GrpcQueryOperator.UNEQUAL)
+				.fieldPath(VorgangStatisticRequestTestFactory.REQUEST_FIELD_PATH);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticGrpcServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticGrpcServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..373ebb45f2fc1fe4de513539e6c143479b989069
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticGrpcServiceTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import io.grpc.stub.StreamObserver;
+
+class StatisticGrpcServiceTest {
+
+	@Spy
+	@InjectMocks
+	private StatisticGrpcService grpcStatisticService;
+
+	@Mock
+	private StatisticService statisticService;
+	@Mock
+	private CountStatisticMapper countStatisticMapper;
+	@Mock
+	private StatisticMapper statisticMapper;
+
+	@DisplayName("Count vorgang")
+	@Nested
+	class TestCountVorgang {
+
+		@Mock
+		private GrpcVorgangCountRequest grpcRequest;
+		@Mock
+		private StreamObserver<GrpcVorgangCountResponse> responseStreamObserver;
+		@Mock
+		private GrpcVorgangCountResponse grpcResponse;
+
+		private Statistic statistic = StatisticTestFactory.create();
+		private VorgangCountRequest request = VorgangCountRequest.builder().build();
+
+		@BeforeEach
+		void setUp() {
+			when(statisticService.countVorgang(any())).thenReturn(statistic);
+			when(countStatisticMapper.mapFromVorgangCountRequest(any())).thenReturn(request);
+		}
+
+		@Test
+		void shouldCallMapFrom() {
+			grpcStatisticService.countVorgang(grpcRequest, responseStreamObserver);
+
+			verify(countStatisticMapper).mapFromVorgangCountRequest(grpcRequest);
+		}
+
+		@Test
+		void shouldCallService() {
+			grpcStatisticService.countVorgang(grpcRequest, responseStreamObserver);
+
+			verify(statisticService).countVorgang(request);
+		}
+
+		@Test
+		void shouldCallMapTo() {
+			grpcStatisticService.countVorgang(grpcRequest, responseStreamObserver);
+
+			verify(countStatisticMapper).mapTo(statistic);
+		}
+
+		@Test
+		void shouldSetResponse() {
+			when(countStatisticMapper.mapTo(any())).thenReturn(grpcResponse);
+
+			grpcStatisticService.countVorgang(grpcRequest, responseStreamObserver);
+
+			verify(responseStreamObserver).onNext(grpcResponse);
+		}
+
+		@Test
+		void shouldCompleteResponse() {
+			grpcStatisticService.countVorgang(grpcRequest, responseStreamObserver);
+
+			verify(responseStreamObserver).onCompleted();
+		}
+	}
+
+	@Nested
+	class TestGetVorgangStatistic {
+
+		@Mock
+		private StreamObserver<GrpcVorgangStatisticResponse> responseObserver;
+
+		private GrpcVorgangStatisticRequest request = GrpcVorgangStatisticRequestTestFactory.create();
+		private GrpcVorgangStatisticResponse response = GrpcVorgangStatisticResponseTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			doReturn(response).when(statisticMapper).mapToVorgangStatisticResponse(any());
+		}
+
+		@Test
+		void shouldSetResponse() {
+			grpcStatisticService.getVorgangStatistic(request, responseObserver);
+
+			verify(responseObserver).onNext(response);
+		}
+
+		@Test
+		void shouldCompleteResponse() {
+			grpcStatisticService.getVorgangStatistic(request, responseObserver);
+
+			verify(responseObserver).onCompleted();
+		}
+
+		@Test
+		void shouldCallMapFromStatisticRequest() {
+			grpcStatisticService.getVorgangStatistic(request, responseObserver);
+
+			verify(statisticMapper).mapFromVorgangStatisticRequest(request);
+		}
+
+		@Test
+		void shouldCallStatisticService() {
+			var statisticRequests = List.of(VorgangStatisticRequestTestFactory.create());
+			when(statisticMapper.mapFromVorgangStatisticRequest(any())).thenReturn(statisticRequests);
+
+			grpcStatisticService.getVorgangStatistic(request, responseObserver);
+
+			verify(statisticService).collectStatistic(statisticRequests);
+		}
+
+		@Test
+		void shouldCallMapToStatisticRequest() {
+			var statistic = StatisticTestFactory.create();
+			when(statisticService.collectStatistic(any())).thenReturn(statistic);
+
+			grpcStatisticService.getVorgangStatistic(request, responseObserver);
+
+			verify(statisticMapper).mapToVorgangStatisticResponse(statistic);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e70be63d4485295dc7b5373ced6aa1c0b5ddaad8
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticMapperTest.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.vorgang.common.operator.OperandFunctionParser;
+
+class StatisticMapperTest {
+
+	@Spy
+	@InjectMocks
+	private StatisticMapper mapper;
+
+	@Mock
+	private OperandFunctionParser operandFunctionParser;
+
+	@Nested
+	class TestMapFromVorgangStatisticRequest {
+
+		@Test
+		void shouldCallMapFromVorgangStatisticQuery() {
+			var statisticQuery = GrpcVorgangStatisticQuery.newBuilder().setPath(VorgangStatisticRequestTestFactory.REQUEST_FIELD_PATH)
+					.setOperandIntValue(1).build();
+			var grpcRequest = GrpcVorgangStatisticRequest.newBuilder().addQuery(statisticQuery).build();
+
+			mapper.mapFromVorgangStatisticRequest(grpcRequest);
+
+			verify(mapper).mapFromVorgangStatisticQuery(statisticQuery);
+		}
+
+		@Nested
+		@DisplayName("Map from VorgangStatisticQuery")
+		class TestMapFromVorgangStatisticQuery {
+
+			@BeforeEach
+			void setup() {
+			}
+
+			@Test
+			void shouldSetResultName() {
+				var vorgangStatisticRequest = mapper.mapFromVorgangStatisticQuery(GrpcVorgangStatisticQueryTestFactory.create());
+
+				assertThat(vorgangStatisticRequest.getResultName()).isEqualTo(GrpcVorgangStatisticQueryTestFactory.RESULT_NAME);
+			}
+
+			@Test
+			void shouldCallGetFieldPath() {
+				var statisticQuery = GrpcVorgangStatisticQueryTestFactory.create();
+
+				mapper.mapFromVorgangStatisticQuery(statisticQuery);
+
+				verify(mapper, times(1)).getFieldPath(statisticQuery);
+			}
+
+			@Test
+			void shouldSetGroupMethod() {
+				var vorgangStatisticRequest = mapper.mapFromVorgangStatisticQuery(GrpcVorgangStatisticQueryTestFactory.create());
+
+				assertThat(vorgangStatisticRequest.getStatisticGroupMethod()).isEqualTo(
+						StatisticGroupMethod.from(GrpcVorgangStatisticQueryTestFactory.GROUP_METHOD));
+			}
+
+			@Test
+			void shouldCallBuildStatisticFilter() {
+				GrpcVorgangStatisticQuery statisticQuery = GrpcVorgangStatisticQueryTestFactory.create();
+
+				mapper.mapFromVorgangStatisticQuery(statisticQuery);
+
+				verify(mapper).buildOperator(statisticQuery);
+			}
+
+			@Nested
+			class TestGetFieldPath {
+
+				@Test
+				void shouldReturnOriginPath() {
+					var statisticQuery = GrpcVorgangStatisticQueryTestFactory.create();
+
+					var fieldPath = mapper.getFieldPath(statisticQuery);
+
+					assertThat(fieldPath).isEqualTo(GrpcVorgangStatisticQueryTestFactory.QUERY_PATH);
+				}
+
+				@Test
+				@DisplayName("should extend field path by '.value' parameter begins with 'clientAttributes'")
+				void shouldExtendPath() {
+					var statisticQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder().setPath("clientAttributes.path").build();
+
+					var fieldPath = mapper.getFieldPath(statisticQuery);
+
+					assertThat(fieldPath).endsWith(".value");
+				}
+			}
+		}
+
+		@Nested
+		class TestBuildOperator {
+
+			@Test
+			void shouldSetFieldPath() {
+				var operator = mapper.buildOperator(GrpcVorgangStatisticQueryTestFactory.create());
+
+				assertThat(operator).extracting("fieldPath").isEqualTo(GrpcVorgangStatisticQueryTestFactory.PATH);
+			}
+
+			@Test
+			void shouldExtendFieldPathWhenClientAttribute() {
+				var statisticQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder().setPath("ClientAttribute.path").build();
+
+				var operator = mapper.buildOperator(statisticQuery);
+
+				assertThat(operator).extracting("fieldPath").isEqualTo("clientAttributes.path.value");
+			}
+
+			@Test
+			void shouldSetOperand() {
+				var operator = mapper.buildOperator(GrpcVorgangStatisticQueryTestFactory.create());
+
+				assertThat(operator).extracting("operand").isEqualTo(GrpcVorgangStatisticQueryTestFactory.OPERAND_STRING_VALUE);
+			}
+
+		}
+
+		@Nested
+		class TestGetValue {
+
+			@Test
+			void shouldReturnNullWhenNotSet() {
+				var statisticQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder().clearOperandStringValue().build();
+
+				var value = mapper.getValue(statisticQuery);
+
+				assertThat(value).isNull();
+			}
+
+			@Test
+			void shouldCallGetStringValue() {
+				var statisticQuery = GrpcVorgangStatisticQueryTestFactory.create();
+
+				mapper.getValue(statisticQuery);
+
+				verify(mapper).getStringValue(statisticQuery);
+			}
+
+			@Test
+			void shouldReturnInteger() {
+				var statisticQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder().setOperandIntValue(1).build();
+
+				var value = mapper.getValue(statisticQuery);
+
+				assertThat(value).isEqualTo(1);
+			}
+
+			@Test
+			void shouldReturnBoolean() {
+				var statisticQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder().setOperandBoolValue(true).build();
+
+				var value = mapper.getValue(statisticQuery);
+
+				assertThat(value).isEqualTo(true);
+			}
+
+			@Nested
+			class TestGetStringValue {
+
+				@Test
+				void shouldCallOperandFunctionParser() {
+					var functionValue = "function()";
+					var statisticQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder().setOperandStringValue(functionValue).build();
+
+					mapper.getStringValue(statisticQuery);
+
+					verify(operandFunctionParser).parse(functionValue);
+				}
+
+				@Test
+				void shouldReturnNull() {
+					var statisticQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder().setOperandStringValue("null").build();
+
+					var value = mapper.getStringValue(statisticQuery);
+
+					assertThat(value).isNull();
+				}
+
+				@Test
+				void shouldReturnStringValue() {
+					var statisticQuery = GrpcVorgangStatisticQueryTestFactory.create();
+
+					var value = mapper.getStringValue(statisticQuery);
+
+					assertThat(value).isEqualTo(GrpcVorgangStatisticQueryTestFactory.OPERAND_STRING_VALUE);
+				}
+			}
+		}
+	}
+
+	@Nested
+	@DisplayName("Map to VorgangStatisticResponse")
+	class TestMapToVorgangStatisticResponse {
+
+		@Test
+		void shouldCallMapCountByPathStatistic() {
+			mapper.mapToVorgangStatisticResponse(StatisticTestFactory.create());
+
+			verify(mapper).mapCountByPathStatistic(StatisticTestFactory.BY_PATH_MAP);
+		}
+
+		@Test
+		void shouldCallMapIsFieldExistsStatistic() {
+			mapper.mapToVorgangStatisticResponse(StatisticTestFactory.create());
+
+			verify(mapper).mapIsFieldExistsStatistic(StatisticTestFactory.FIELD_EXISTS_MAP);
+		}
+
+		@Test
+		void shouldSetStatisticResults() {
+			var countByPathStatisticResult = GrpcVorgangStatisticResultTestFactory.create();
+			var isFieldExistsStatisticResult = GrpcVorgangStatisticResultTestFactory.createBuilder().setResultBoolValue(true).build();
+			init(countByPathStatisticResult, isFieldExistsStatisticResult);
+
+			var response = mapper.mapToVorgangStatisticResponse(StatisticTestFactory.create());
+
+			assertThat(response.getResultList()).containsExactly(countByPathStatisticResult, isFieldExistsStatisticResult);
+		}
+
+		private void init(GrpcVorgangStatisticResult countByPathStatisticResult, GrpcVorgangStatisticResult isFieldExistsStatisticResult) {
+			var list = new ArrayList<GrpcVorgangStatisticResult>();
+			list.add(countByPathStatisticResult);
+			doReturn(list).when(mapper).mapCountByPathStatistic(anyMap());
+			doReturn(List.of(isFieldExistsStatisticResult)).when(mapper).mapIsFieldExistsStatistic(anyMap());
+		}
+
+		@Nested
+		@DisplayName("Map CountByPathStatistic")
+		class TestMapByPathStatistic {
+
+			@Test
+			void shouldCallMapToCountResult() {
+				mapper.mapCountByPathStatistic(StatisticTestFactory.BY_PATH_MAP);
+
+				verify(mapper).mapToCountResult(StatisticTestFactory.FIELD_PATH_ALIAS, StatisticTestFactory.FIELD_PATH_VALUE);
+			}
+
+			@Test
+			void shouldGetEmptyList() {
+				var result = mapper.mapCountByPathStatistic(Collections.emptyMap());
+
+				assertThat(result).isEmpty();
+			}
+
+			@Nested
+			@DisplayName("Map to CountResult")
+			class TestMapToCountResult {
+
+				@Test
+				void shouldSetName() {
+					var result = mapper.mapToCountResult(StatisticTestFactory.FIELD_PATH_ALIAS, StatisticTestFactory.FIELD_PATH_VALUE);
+
+					assertThat(result.getName()).isEqualTo(StatisticTestFactory.FIELD_PATH_ALIAS);
+				}
+
+				@Test
+				void shouldSetIntValue() {
+					var result = mapper.mapToCountResult(StatisticTestFactory.FIELD_PATH_ALIAS, StatisticTestFactory.FIELD_PATH_VALUE);
+
+					assertThat(result.getResultIntValue()).isEqualTo(StatisticTestFactory.FIELD_PATH_VALUE);
+				}
+			}
+		}
+
+		@Nested
+		@DisplayName("Map IsFieldExistsStatistic")
+		class TestMapIsFieldExistsStatistic {
+
+			@Test
+			void shouldCallMapToIsFieldExistsResult() {
+				mapper.mapIsFieldExistsStatistic(StatisticTestFactory.FIELD_EXISTS_MAP);
+
+				verify(mapper).mapToIsFieldExistsResult(StatisticTestFactory.FIELD_PATH_ALIAS, true);
+			}
+
+			@Test
+			void shouldGetEmptyList() {
+				var result = mapper.mapIsFieldExistsStatistic(Collections.emptyMap());
+
+				assertThat(result).isEmpty();
+			}
+
+			@Nested
+			@DisplayName("Map to IsFieldExistsResult")
+			class TestMapToIsFieldExistsResult {
+
+				@Test
+				void shouldSetName() {
+					var result = mapper.mapToIsFieldExistsResult(StatisticTestFactory.FIELD_PATH_ALIAS, true);
+
+					assertThat(result.getName()).isEqualTo(StatisticTestFactory.FIELD_PATH_ALIAS);
+				}
+
+				@Test
+				void shouldSetBoolValue() {
+					var result = mapper.mapToIsFieldExistsResult(StatisticTestFactory.FIELD_PATH_ALIAS, true);
+
+					assertThat(result.getResultBoolValue()).isTrue();
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticRepositoryITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..60cb4a0273bf720ad8fbb048e8c6584b994b0148
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticRepositoryITCase.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static de.ozgcloud.vorgang.statistic.CountByPathTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMapTestFactory;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangStubTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
+
+@DataITCase
+class StatisticRepositoryITCase {
+
+	@Autowired
+	private StatisticRepository statisticRepository;
+	@Autowired
+	private MongoOperations mongoOperations;
+
+	@Nested
+	@DisplayName("Count by status")
+	class TestByStatus {
+
+		@Nested
+		@DisplayName("with filters")
+		class TestFilters {
+			private static final String ANOTHER_ORGA_ID = "another-orga-id";
+
+			private Vorgang vorgangInBearbeitung = VorgangTestFactory.createBuilder().id(null).status(Vorgang.Status.IN_BEARBEITUNG).build();
+
+			@BeforeEach
+			void setUp() {
+				mongoOperations.dropCollection(Vorgang.class);
+
+				var vorgangNeu = VorgangTestFactory.createBuilder().id(null).build();
+				var zustaendigeStelle = ZustaendigeStelleTestFactory.createBuilder().organisationseinheitenId(ANOTHER_ORGA_ID).build();
+				var eingang = EingangTestFactory.createBuilder().zustaendigeStelle(zustaendigeStelle).build();
+				var vorgangNeuAnotherOrgaId = VorgangTestFactory.createBuilder().id(null).clearEingangs().eingang(eingang).build();
+				mongoOperations.insertAll(List.of(vorgangNeu, vorgangNeuAnotherOrgaId, vorgangInBearbeitung));
+			}
+
+			@Test
+			void shouldCountAllVorgang() {
+				var statusCounts = statisticRepository.countVorgangByStatus(StatisticFilter.builder().build());
+
+				assertThat(statusCounts).containsOnly(
+						CountResultTestFactory.createBuilder().name(Vorgang.Status.NEU.toString()).value(2).build(),
+						CountResultTestFactory.createBuilder().name(Vorgang.Status.IN_BEARBEITUNG.toString()).build());
+			}
+
+			@Test
+			void shouldCountAllVorgangByOrganisatorischeEinheitenIds() {
+				var filter = StatisticFilter.builder()
+						.organisationsEinheitIds(List.of(ANOTHER_ORGA_ID, ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID)).build();
+
+				var statusCounts = statisticRepository.countVorgangByStatus(filter);
+
+				assertThat(statusCounts).containsOnly(
+						CountResultTestFactory.createBuilder().name(Vorgang.Status.NEU.toString()).value(2).build(),
+						CountResultTestFactory.createBuilder().name(Vorgang.Status.IN_BEARBEITUNG.toString()).build());
+			}
+
+			@Test
+			void shouldFilterByOrganisatorischeEinheitenId() {
+				var filter = StatisticFilter.builder().organisationsEinheitIds(List.of(ANOTHER_ORGA_ID)).build();
+
+				var statusCounts = statisticRepository.countVorgangByStatus(filter);
+
+				assertThat(statusCounts).containsOnly(CountResult.builder().name(Vorgang.Status.NEU.toString()).value(1).build());
+			}
+
+			@Test
+			void shouldNotCountInCreation() {
+				mongoOperations.dropCollection(Vorgang.class);
+				var vorgangInCreation = VorgangTestFactory.createBuilder().id(null).inCreation(true).build();
+				mongoOperations.insert(vorgangInCreation);
+
+				var statusCounts = statisticRepository.countVorgangByStatus(StatisticFilter.builder().build());
+
+				assertThat(statusCounts).isEmpty();
+			}
+		}
+
+		@DisplayName("per status")
+		@Nested
+		class TestPerStatus {
+
+			@BeforeEach
+			void setUp() {
+				mongoOperations.dropCollection(Vorgang.class);
+			}
+
+			@Test
+			void shouldCountAngenommen() {
+				initTestWithStatus(Vorgang.Status.ANGENOMMEN);
+
+				var statusCounts = statisticRepository.countVorgangByStatus(StatisticFilter.builder().build());
+
+				assertThat(statusCounts).hasSize(1).first().isEqualTo(buildCountResultForStatus(Vorgang.Status.ANGENOMMEN));
+			}
+
+			@Test
+			void shouldCountVerworfen() {
+				initTestWithStatus(Vorgang.Status.VERWORFEN);
+
+				var statusCounts = countVorgangByStatus();
+
+				assertThat(statusCounts).hasSize(1).first().isEqualTo(buildCountResultForStatus(Vorgang.Status.VERWORFEN));
+
+			}
+
+			@Test
+			void shouldCountAbgeschlossen() {
+				initTestWithStatus(Vorgang.Status.ABGESCHLOSSEN);
+
+				var statusCounts = countVorgangByStatus();
+
+				assertThat(statusCounts).hasSize(1).first().isEqualTo(buildCountResultForStatus(Vorgang.Status.ABGESCHLOSSEN));
+
+			}
+
+			@Test
+			void shouldCountWeitergeleitet() {
+				initTestWithStatus(Vorgang.Status.WEITERGELEITET);
+
+				var statusCounts = countVorgangByStatus();
+
+				assertThat(statusCounts).hasSize(1).first().isEqualTo(buildCountResultForStatus(Vorgang.Status.WEITERGELEITET));
+
+			}
+
+			@Test
+			void shouldCountBeschieden() {
+				initTestWithStatus(Vorgang.Status.BESCHIEDEN);
+
+				var statusCounts = countVorgangByStatus();
+
+				assertThat(statusCounts).hasSize(1).first().isEqualTo(buildCountResultForStatus(Vorgang.Status.BESCHIEDEN));
+			}
+
+			private void initTestWithStatus(Vorgang.Status status) {
+				var vorgang = VorgangTestFactory.createBuilder().id(null).status(status).build();
+				mongoOperations.save(vorgang);
+			}
+
+			private CountResult buildCountResultForStatus(Vorgang.Status status) {
+				return CountResultTestFactory.createBuilder().name(status.toString()).build();
+			}
+		}
+
+		private List<CountResult> countVorgangByStatus() {
+			return statisticRepository.countVorgangByStatus(StatisticFilter.builder().build());
+		}
+	}
+
+	@Nested
+	class TestByPath {
+
+		private final String FIELD_NAME = "nextFrist";
+		private final String FIELD_PATH = "ClientAttribute.%s.%s".formatted(ClientAttributeTestFactory.CLIENT_NAME,
+				FIELD_NAME);
+
+		private final static Vorgang DEFAULT_VORGANG = VorgangTestFactory.createBuilder().id(null).build();
+
+		private StatisticFilter statisticFilter = StatisticFilter.builder().build();
+
+		@BeforeEach
+		void setup() {
+			mongoOperations.dropCollection(Vorgang.COLLECTION_NAME);
+			mongoOperations.save(DEFAULT_VORGANG);
+
+			var nextWiedervorlageAttribute = ClientAttributeTestFactory.createBuilder().attributeName(FIELD_NAME).build();
+			var vorgangWithNextFrist = VorgangTestFactory.createBuilder().id(null)
+					.clientAttributes(ClientAttributesMapTestFactory.createWithAttribute(nextWiedervorlageAttribute))
+					.build();
+			mongoOperations.save(vorgangWithNextFrist);
+		}
+
+		@Test
+		void shouldCountVorgangsByPath() {
+			var countRequest = CountByPathTestFactory.createBuilder().fieldPath(FIELD_PATH).build();
+			var operator = OperatorBuilder.from(GrpcQueryOperator.UNEQUAL).fieldPath(FIELD_PATH).operand(null).build();
+
+			var countEntries = statisticRepository.countVorgangByPath(countRequest, operator, statisticFilter);
+
+			assertThat(countEntries).hasSize(1).first().isEqualTo(CountResultTestFactory.create());
+		}
+
+		@Test
+		void shouldReturnZeroWhenNotFound() {
+			var countRequest = CountByPathTestFactory.createBuilder().fieldPath(FIELD_NAME).build();
+			var operator = OperatorBuilder.from(GrpcQueryOperator.UNEQUAL).fieldPath("ClientAttribute." + FIELD_NAME + 1)
+					.operand(null).build();
+
+			var countEntries = statisticRepository.countVorgangByPath(countRequest, operator, statisticFilter);
+
+			assertThat(countEntries).hasSize(1).first().isEqualTo(CountResultTestFactory.createBuilder().value(0).build());
+		}
+
+		@Test
+		void shouldReturnCountVorgangByPathWithCondition() {
+			saveVorgangDateClientAttribute(LocalDate.now());
+			var countRequest = CountByPathTestFactory.createBuilder().fieldPath(FIELD_PATH).build();
+			// TODO hier müssen wir noch mal ran - im Repository-Code dürfen wir keine
+			// Abhängigkeit auf gRPC Code haben
+			var operator = OperatorBuilder.from(GrpcQueryOperator.LESS_THEN).fieldPath("Vorgang." + FIELD_PATH)
+					.operand(LocalDate.now().minusDays(2).toString()).build();
+
+			var countEntries = statisticRepository.countVorgangByPath(countRequest, operator, statisticFilter);
+
+			assertThat(countEntries).hasSize(1).first().usingRecursiveComparison()
+					.isEqualTo(CountResultTestFactory.createBuilder().value(3).name(ALIAS).build());
+		}
+
+		@Test
+		void shouldNotCountDELETEDVorgang() {
+			mongoOperations.dropCollection(Vorgang.COLLECTION_NAME);
+			mongoOperations.save(VorgangStubTestFactory.create());
+
+			var statistic = statisticRepository.countVorgangByPath(CountByPathTestFactory.create(),
+					OperatorTestFactory.createBuilder().fieldPath(CountByPathTestFactory.FIELD_PATH).operand("other").build(), statisticFilter);
+
+			assertThat(statistic).hasSize(1).first().usingRecursiveComparison()
+					.isEqualTo(CountResultTestFactory.createBuilder().value(0).build());
+		}
+
+		@Test
+		void shouldReturnZeroOnEmptyCollection() {
+			mongoOperations.dropCollection(Vorgang.COLLECTION_NAME);
+
+			var statistic = statisticRepository.countVorgangByPath(CountByPathTestFactory.create(), OperatorTestFactory.create(), statisticFilter);
+
+			assertThat(statistic).hasSize(1).first().usingRecursiveComparison()
+					.isEqualTo(CountResultTestFactory.createBuilder().value(0).build());
+		}
+
+		private void saveVorgangDateClientAttribute(LocalDate date) {
+			var nextWiedervorlageAttribute = ClientAttributeTestFactory.createBuilder().attributeName(FIELD_NAME)
+					.stringValue(Optional.of(date.toString())).build();
+			var vorgangWithNextFrist = VorgangTestFactory.createBuilder().id(null)
+					.clientAttributes(ClientAttributesMapTestFactory.createWithAttribute(nextWiedervorlageAttribute))
+					.build();
+			mongoOperations.save(vorgangWithNextFrist);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticRepositoryTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticRepositoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..bfe89cdc8655eda47e2f981760587ee5c024575f
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticRepositoryTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Set;
+
+import org.assertj.core.data.MapEntry;
+import org.bson.Document;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.data.mongodb.core.aggregation.AggregationResults;
+import org.springframework.data.mongodb.core.query.Query;
+
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
+
+class StatisticRepositoryTest {
+
+	@InjectMocks
+	@Spy
+	private StatisticRepository statisticRepository;
+
+	@Mock
+	private MongoOperations mongoOperations;
+
+	private final StatisticFilter ORGANISATIONSEINHEIT_IDS_FILTER = StatisticFilter.builder()
+			.organisationsEinheitId(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID).build();
+
+	@Nested
+	@DisplayName("Count vorgang")
+	class TestCount {
+
+		@Nested
+		@DisplayName("by status")
+		class TestByStatus {
+
+			@Mock
+			private AggregationResults aggregationResults;
+
+			@BeforeEach
+			void setUp() {
+				doReturn(aggregationResults).when(statisticRepository).executeAggregation(any(), any());
+			}
+
+			@Test
+			@DisplayName("should call initAggregationOperations")
+			void shouldCallExecuteAggregationAll() {
+				statisticRepository.countVorgangByStatus(ORGANISATIONSEINHEIT_IDS_FILTER);
+
+				verify(statisticRepository).initAggregationOperations(ORGANISATIONSEINHEIT_IDS_FILTER);
+			}
+
+			@Test
+			@DisplayName("should call executeAggregation")
+			void shouldCallExecuteAggregation() {
+				statisticRepository.countVorgangByStatus(ORGANISATIONSEINHEIT_IDS_FILTER);
+
+				verify(statisticRepository).executeAggregation(any(), any());
+			}
+
+			@Test
+			@DisplayName("should call get results")
+			void shouldCallGetResults() {
+				statisticRepository.countVorgangByStatus(ORGANISATIONSEINHEIT_IDS_FILTER);
+
+				verify(aggregationResults).getMappedResults();
+			}
+		}
+
+		@Nested
+		@DisplayName("by path")
+		class TestByPath {
+
+			private final static CountByPath COUNT_PATH_REQUEST = CountPathRequestTestFactory.create();
+
+			@Mock
+			private Document document;
+			@Mock
+			private AggregationResults aggregationResults;
+
+			private Operator statisticQuery = OperatorTestFactory.create();
+
+			@BeforeEach
+			void setup() {
+				when(aggregationResults.getUniqueMappedResult()).thenReturn(document).getMock();
+				doReturn(aggregationResults).when(statisticRepository).executeAggregation(any(), any());
+			}
+
+			@Test
+			@DisplayName("should call initAggregationOperations")
+			void shouldCallExecuteAggregationAll() {
+				statisticRepository.countVorgangByPath(COUNT_PATH_REQUEST, statisticQuery, ORGANISATIONSEINHEIT_IDS_FILTER);
+
+				verify(statisticRepository).initAggregationOperations(ORGANISATIONSEINHEIT_IDS_FILTER);
+			}
+
+			@Test
+			@DisplayName("should call executeAggregation")
+			void shouldCallExecuteAggregation() {
+				statisticRepository.countVorgangByPath(COUNT_PATH_REQUEST, statisticQuery, ORGANISATIONSEINHEIT_IDS_FILTER);
+
+				verify(statisticRepository).executeAggregation(any(), any());
+			}
+
+			@Test
+			@DisplayName("should call get results")
+			void shouldCallGetResults() {
+				statisticRepository.countVorgangByPath(COUNT_PATH_REQUEST, statisticQuery, StatisticFilter.builder().build());
+
+				verify(aggregationResults).getUniqueMappedResult();
+			}
+
+			@Test
+			@DisplayName("should call map count results")
+			void shouldCallMapCountResults() {
+				statisticRepository.countVorgangByPath(COUNT_PATH_REQUEST, statisticQuery, StatisticFilter.builder().build());
+
+				verify(statisticRepository).mapCountByPathResults(document, CountByPathTestFactory.ALIAS);
+			}
+		}
+	}
+
+	@Nested
+	class TestMapByPathResults {
+
+		@Mock
+		private Document document;
+
+		@Test
+		void shouldFilterIdField() {
+			when(document.entrySet()).thenReturn(Set.of(MapEntry.entry("_id", "id")));
+
+			var result = statisticRepository.mapCountByPathResults(document, CountByPathTestFactory.ALIAS);
+
+			assertThat(result).isEmpty();
+		}
+
+		@Test
+		void shouldCallMapCountResult() {
+			var entry = MapEntry.<String, Object>entry("key", 1);
+			when(document.entrySet()).thenReturn(Set.of(entry));
+
+			statisticRepository.mapCountByPathResults(document, CountByPathTestFactory.ALIAS);
+
+			verify(statisticRepository, times(1)).mapCountResult(entry);
+		}
+
+		@Test
+		void shouldReturnResult() {
+			var entry = MapEntry.<String, Object>entry(CountResultTestFactory.NAME, CountResultTestFactory.VALUE);
+			when(document.entrySet()).thenReturn(Set.of(entry));
+			doReturn(CountResultTestFactory.create()).when(statisticRepository).mapCountResult(entry);
+
+			var results = statisticRepository.mapCountByPathResults(document, CountByPathTestFactory.ALIAS);
+
+			assertThat(results).containsExactly(CountResultTestFactory.create());
+		}
+
+		@Test
+		void shouldZeroResultOnNull() {
+			var results = statisticRepository.mapCountByPathResults(null, CountByPathTestFactory.ALIAS);
+
+			assertThat(results).hasSize(1).first().usingRecursiveComparison().isEqualTo(CountResultTestFactory.createBuilder().value(0).build());
+		}
+	}
+
+	@Nested
+	class TestMapCountResults {
+
+		@Test
+		void shouldMapValue() {
+			var entry = MapEntry.<String, Object>entry(CountResultTestFactory.NAME, CountResultTestFactory.VALUE);
+
+			var result = statisticRepository.mapCountResult(entry);
+
+			assertThat(result.getName()).isEqualTo(CountResultTestFactory.NAME);
+		}
+
+		@Test
+		void shouldMapCount() {
+			var entry = MapEntry.<String, Object>entry(CountResultTestFactory.NAME, CountResultTestFactory.VALUE);
+
+			var result = statisticRepository.mapCountResult(entry);
+
+			assertThat(result.getValue()).isEqualTo(CountResultTestFactory.VALUE);
+		}
+	}
+
+	@Nested
+	@DisplayName("Init aggregation operations")
+	class TestInitAggregationOperation {
+
+		@Test
+		void addInCreationCriteria() {
+			var result = statisticRepository.initAggregationOperations(StatisticFilter.builder().build());
+
+			assertThat(result).hasSize(1);
+		}
+
+	}
+
+	@Nested
+	class TestIsFieldExists {
+
+		@Spy
+		private StatisticFilter filter = StatisticFilter.builder().build();
+
+		@Test
+		void shouldCallExists() {
+			statisticRepository.isFieldsExists(filter);
+
+			verify(mongoOperations).exists(any(Query.class), eq(Vorgang.COLLECTION_NAME));
+		}
+
+		@Test
+		void shouldCallGetCriteria() {
+			statisticRepository.isFieldsExists(filter);
+
+			verify(filter).getCriteria();
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b0c62ac641321b7c288f61a69c358a2c201b80b
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticServiceTest.java
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import de.ozgcloud.vorgang.callcontext.CallContextUser;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.common.operator.Operator;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+import de.ozgcloud.vorgang.common.operator.OperatorFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
+
+class StatisticServiceTest {
+
+	@Spy
+	@InjectMocks
+	private StatisticService statisticService;
+
+	@Mock
+	private StatisticRepository statisticRepository;
+	@Mock
+	private OperatorFactory operatorFactory;
+	@Mock
+	private CurrentUserService currentUserService;
+	@Mock
+	private CallContextUser user;
+
+	private final VorgangCountRequest request = VorgangCountRequestTestFactory.create();
+
+	@DisplayName("Count vorgang")
+	@Nested
+	class TestCountVorgang {
+
+		@Mock
+		private OperatorBuilder operatorBuilder;
+
+		@BeforeEach
+		void setUp() {
+			when(currentUserService.getUser()).thenReturn(user);
+		}
+
+		@Test
+		void shouldCallBuildStatistic() {
+			when(operatorBuilder.fieldPath(any())).thenReturn(operatorBuilder);
+			when(operatorBuilder.operand(any())).thenReturn(operatorBuilder);
+			when(operatorFactory.newUnequalOperatorBuilder()).thenReturn(operatorBuilder);
+			statisticService.countVorgang(request);
+
+			verify(statisticService).countVorgang(request);
+		}
+
+		@DisplayName("Get organisationsEinheitenIds")
+		@Nested
+		class TestGetOrganisationsEinheitenIds {
+
+			@BeforeEach
+			void setup() {
+				lenient().when(operatorBuilder.fieldPath(any())).thenReturn(operatorBuilder);
+				lenient().when(operatorBuilder.operand(any())).thenReturn(operatorBuilder);
+				lenient().when(operatorFactory.newUnequalOperatorBuilder()).thenReturn(operatorBuilder);
+			}
+
+			@DisplayName("should return organisationsEinheitIds when check is necessary")
+			@Test
+			void shouldReturnOrganisationsEinheitIds() {
+				var expectedOrganisationsEinheitIds = List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
+				when(user.isOrganisationEinheitenIdCheckNecessary()).thenReturn(true);
+				when(user.getOrganisatorischeEinheitenIds()).thenReturn(expectedOrganisationsEinheitIds);
+
+				var organisationsEinheitIds = statisticService.getOrganisationsEinheitIds();
+
+				assertThat(organisationsEinheitIds).isPresent().get().isEqualTo(expectedOrganisationsEinheitIds);
+			}
+
+			@DisplayName("should return empty list when check is not necessary")
+			@Test
+			void shouldReturnEmptyCollection() {
+				var organisationsEinheitIds = statisticService.getOrganisationsEinheitIds().get();
+
+				assertThat(organisationsEinheitIds).isEmpty();
+			}
+
+			@DisplayName("should return empty optional when check necessary but no organisationsEinheitIds")
+			@Test
+			void shouldThrowException() {
+				when(user.isOrganisationEinheitenIdCheckNecessary()).thenReturn(true);
+				when(user.getOrganisatorischeEinheitenIds()).thenReturn(Collections.emptyList());
+
+				var organisationsEinheitIds = statisticService.getOrganisationsEinheitIds();
+
+				assertThat(organisationsEinheitIds).isEmpty();
+			}
+		}
+	}
+
+	@DisplayName("Build statistic")
+	@Nested
+	class TestBuildStatistic {
+
+		@Mock
+		private OperatorBuilder operatorBuilder;
+
+		@BeforeEach
+		void setUp() {
+			when(currentUserService.getUser()).thenReturn(user);
+			when(user.isOrganisationEinheitenIdCheckNecessary()).thenReturn(true);
+			when(user.getOrganisatorischeEinheitenIds()).thenReturn(List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+		}
+
+		@Test
+		void shouldSetCountByStatus() {
+			var resultsCountByStatus = Map.of(Vorgang.Status.NEU, 1);
+			doReturn(resultsCountByStatus).when(statisticService).countVorgangByStatus();
+			when(operatorBuilder.fieldPath(any())).thenReturn(operatorBuilder);
+			when(operatorBuilder.operand(any())).thenReturn(operatorBuilder);
+			when(operatorFactory.newUnequalOperatorBuilder()).thenReturn(operatorBuilder);
+
+			var statistic = statisticService.countVorgang(request);
+
+			assertThat(statistic.getCountByStatus()).isEqualTo(resultsCountByStatus);
+		}
+
+		@Test
+		void shouldSetCountByPaths() {
+			var resultsCountByPath = Map.of(CountResultTestFactory.NAME, 1);
+			doReturn(resultsCountByPath).when(statisticService).countVorgangByPathsOld(any());
+
+			var statistic = statisticService.countVorgang(request);
+
+			assertThat(statistic.getCountResult()).isEqualTo(resultsCountByPath);
+		}
+	}
+
+	@Nested
+	class TestFilterByGroupMethod {
+
+		private VorgangStatisticRequest existsRequest = VorgangStatisticRequestTestFactory.createBuilder()
+				.statisticGroupMethod(StatisticGroupMethod.EXISTS).build();
+		private VorgangStatisticRequest countRequest = VorgangStatisticRequestTestFactory.create();
+
+		@Test
+		void shouldReturnCountRequests() {
+			var statisticRequests = List.of(countRequest, existsRequest);
+
+			var countRequests = statisticService.getCountRequests(statisticRequests);
+
+			assertThat(countRequests).hasSize(1).first().isEqualTo(countRequest);
+		}
+
+		@Test
+		void shouldReturnExistsRequests() {
+			var statisticRequests = List.of(existsRequest, countRequest);
+
+			var existsRequests = statisticService.getExistsRequests(statisticRequests);
+
+			assertThat(existsRequests).hasSize(1).first().isEqualTo(existsRequest);
+		}
+	}
+
+	@DisplayName("By status")
+	@Nested
+	class TestCountByStatus {
+
+		@BeforeEach
+		void setUp() {
+			when(currentUserService.getUser()).thenReturn(user);
+			when(user.isOrganisationEinheitenIdCheckNecessary()).thenReturn(true);
+			when(user.getOrganisatorischeEinheitenIds()).thenReturn(List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+		}
+
+		@Test
+		void shouldSetStatusStatistic() {
+			var expectedStatus = Vorgang.Status.NEU;
+			var countResults = List.of(CountResultTestFactory.createBuilder().name(expectedStatus.toString()).build());
+			when(statisticRepository.countVorgangByStatus(any())).thenReturn(countResults);
+
+			var countByStatus = statisticService.countVorgangByStatus();
+
+			assertThat(countByStatus).containsEntry(expectedStatus, CountResultTestFactory.VALUE);
+		}
+
+		@Test
+		void shouldReturnDefaultValues() {
+
+			var countByStatus = statisticService.countVorgangByStatus();
+
+			assertContainsAllStatusExcepting(countByStatus);
+		}
+
+	}
+
+	@Nested
+	class TestFillMissingStatusCounter {
+
+		@Test
+		void shouldAddMissingCounters() {
+			var filledCountByStatus = statisticService.fillMissingStatusCounters(Map.of(Vorgang.Status.NEU, 1));
+
+			assertThat(filledCountByStatus).containsEntry(Vorgang.Status.NEU, 1);
+			assertContainsAllStatusExcepting(filledCountByStatus, Vorgang.Status.NEU);
+		}
+
+		@Test
+		void shouldFillEmptyMap() {
+			var countByStatus = statisticService.fillMissingStatusCounters(Collections.emptyMap());
+
+			assertContainsAllStatusExcepting(countByStatus);
+		}
+
+	}
+
+	private void assertContainsAllStatusExcepting(Map<Vorgang.Status, Integer> countByStatus, Vorgang.Status... exceptStatus) {
+		Arrays.stream(Vorgang.Status.values()).filter(status -> !ArrayUtils.contains(exceptStatus, status))
+				.forEach(status -> assertThat(countByStatus).containsEntry(status, 0));
+	}
+
+	@DisplayName("By path")
+	@Nested
+	class TestCountByPath {
+
+		@Mock
+		private OperatorBuilder operatorBuilder;
+
+		@BeforeEach
+		void setup() {
+			when(operatorBuilder.fieldPath(any())).thenReturn(operatorBuilder);
+			when(operatorBuilder.operand(any())).thenReturn(operatorBuilder);
+			when(operatorFactory.newUnequalOperatorBuilder()).thenReturn(operatorBuilder);
+		}
+
+		private final CountByPath countByPath = CountPathRequestTestFactory.create();
+
+		@Test
+		void shouldCallRepository() {
+			doReturn(Optional.of(Collections.emptyList())).when(statisticService).getOrganisationsEinheitIds();
+
+			statisticService.countVorgangByPathsOld(List.of(countByPath));
+
+			verify(statisticRepository).countVorgangByPath(eq(countByPath), any(), any());
+		}
+
+		@Test
+		void shouldReturnCountResults() {
+			doReturn(Optional.of(Collections.emptyList())).when(statisticService).getOrganisationsEinheitIds();
+			when(statisticRepository.countVorgangByPath(any(), any(), any())).thenReturn(List.of(CountResultTestFactory.create()));
+
+			var countResults = statisticService.countVorgangByPathsOld(List.of(countByPath));
+
+			assertThat(countResults).hasSize(1).containsEntry(CountResultTestFactory.NAME, CountResultTestFactory.VALUE);
+		}
+	}
+
+	@Nested
+	@DisplayName("Collect Statistic")
+	class TestCollectStatistic {
+
+		private final List<String> expectedOrganisationsEinheitIds = List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
+
+		@Captor
+		private ArgumentCaptor<Set<VorgangStatisticRequest>> statisticCountRequestCaptor;
+
+		@BeforeEach
+		void setUp() {
+			lenient().when(currentUserService.getUser()).thenReturn(user);
+			lenient().when(user.isOrganisationEinheitenIdCheckNecessary()).thenReturn(true);
+			lenient().when(user.getOrganisatorischeEinheitenIds()).thenReturn(expectedOrganisationsEinheitIds);
+		}
+
+		@Test
+		void shouldCallCountVorgangByPaths() {
+			var statisticCountRequest = VorgangStatisticRequestTestFactory.create();
+
+			statisticService.collectStatistic(List.of(statisticCountRequest));
+
+			verify(statisticService).countVorgangByPaths(statisticCountRequestCaptor.capture());
+			assertThat(statisticCountRequestCaptor.getValue()).hasSize(1).contains(statisticCountRequest);
+		}
+
+		@Test
+		void shouldReturnStatistic() {
+			var statisticCountRequest = VorgangStatisticRequestTestFactory.createBuilder().statisticGroupMethod(StatisticGroupMethod.EXISTS).build();
+
+			statisticService.collectStatistic(List.of(statisticCountRequest));
+
+			verify(statisticService).collectFieldExistsStatistic(statisticCountRequestCaptor.capture());
+			assertThat(statisticCountRequestCaptor.getValue()).hasSize(1).contains(statisticCountRequest);
+
+		}
+
+		@Test
+		void shouldSetCountByPath() {
+			doReturn(StatisticTestFactory.BY_PATH_MAP).when(statisticService).countVorgangByPaths(any());
+
+			var statistic = statisticService.collectStatistic(List.of(VorgangStatisticRequestTestFactory.create()));
+
+			assertThat(statistic.getCountResult()).isEqualTo(StatisticTestFactory.BY_PATH_MAP);
+		}
+
+		@Test
+		void shouldSetFieldExistsStatistic() {
+			var resultMap = Map.of(VorgangStatisticRequestTestFactory.RESULT_NAME, true);
+			doReturn(resultMap).when(statisticService).collectFieldExistsStatistic(any());
+			doReturn(Collections.emptyMap()).when(statisticService).countVorgangByPaths(any());
+
+			var statistic = statisticService.collectStatistic(List.of(VorgangStatisticRequestTestFactory.create()));
+
+			assertThat(statistic.getExistsResult()).isEqualTo(resultMap);
+		}
+
+		@Nested
+		class TestCollectFieldExistsStatistic {
+
+			@Captor
+			private ArgumentCaptor<StatisticFilter> statisticFilterCaptor;
+
+			@Test
+			void shouldCallIsFieldExists() {
+				var statisticCountRequest = VorgangStatisticRequestTestFactory.createBuilder().statisticGroupMethod(StatisticGroupMethod.EXISTS)
+						.build();
+
+				statisticService.collectFieldExistsStatistic(List.of(statisticCountRequest));
+
+				verify(statisticService).isFieldExists(statisticCountRequest);
+			}
+
+			@Test
+			void shouldAddOrganisationsEinheitIds() {
+				var organisationsEinheitIds = List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
+				doReturn(Optional.of(organisationsEinheitIds)).when(statisticService).getOrganisationsEinheitIds();
+
+				statisticService.isFieldExists(VorgangStatisticRequestTestFactory.create());
+
+				verify(statisticRepository).isFieldsExists(statisticFilterCaptor.capture());
+				assertThat(statisticFilterCaptor.getValue()).extracting("organisationsEinheitIds").isEqualTo(organisationsEinheitIds);
+			}
+
+			@Test
+			void shouldAddFilterCriteria() {
+				var expectedCriteria = Criteria.where("field").exists(true);
+				Operator operator = when(mock(Operator.class).getCriteria()).thenReturn(expectedCriteria).getMock();
+				var statisticRequest = VorgangStatisticRequestTestFactory.createBuilder().operator(operator).build();
+
+				statisticService.isFieldExists(statisticRequest);
+
+				verify(statisticRepository).isFieldsExists(statisticFilterCaptor.capture());
+				assertThat(statisticFilterCaptor.getValue()).extracting("filterCriteria").isEqualTo(expectedCriteria);
+			}
+
+		}
+
+		@Nested
+		@DisplayName("Count Vorgang by paths")
+		class TestCountVorgangByPaths {
+
+			@Captor
+			private ArgumentCaptor<StatisticFilter> statisticFilterArgumentCaptor;
+
+			@BeforeEach
+			void setUp() {
+				lenient().doReturn(Optional.of(List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID))).when(statisticService)
+						.getOrganisationsEinheitIds();
+			}
+
+			@Test
+			void shouldCallCountVorgangByPathForRequest() {
+				var vorgangStatisticRequest = VorgangStatisticRequestTestFactory.create();
+
+				statisticService.countVorgangByPaths(List.of(vorgangStatisticRequest));
+
+				verify(statisticService).countVorgangByPath(vorgangStatisticRequest);
+			}
+
+			@Test
+			void shouldSetOrganisationsEinheitIds() {
+				var statisticRequest = VorgangStatisticRequestTestFactory.create();
+
+				statisticService.countVorgangByPath(statisticRequest);
+
+				verify(statisticRepository).countVorgangByPath(any(), any(), statisticFilterArgumentCaptor.capture());
+				assertThat(statisticFilterArgumentCaptor.getValue()).extracting("organisationsEinheitIds").isEqualTo(expectedOrganisationsEinheitIds);
+			}
+
+			@Test
+			void shouldReturnCountResults() {
+				doReturn(Stream.of(CountResultTestFactory.create())).when(statisticService).countVorgangByPath(any());
+
+				var countResults = statisticService.countVorgangByPaths(List.of(VorgangStatisticRequestTestFactory.create()));
+
+				assertThat(countResults).hasSize(1).containsEntry(CountResultTestFactory.NAME, CountResultTestFactory.VALUE);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2158f14a391cc6fd06127d14c1c30d98f34a0b1
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/StatisticTestFactory.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import java.util.Map;
+
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+
+public class StatisticTestFactory {
+
+	public static final Integer NEU_COUNT = 1;
+	public static final Integer ANGENOMMEN_COUNT = 2;
+	public static final Integer IN_BEARBEITUNG_COUNT = 3;
+	public static final Integer BESCHIEDEN_COUNT = 4;
+	public static final Integer ABGESCHLOSSEN_COUNT = 5;
+	public static final Integer VERWORFEN_COUNT = 6;
+	public static final Integer WEITERGELEITET_COUNT = 7;
+
+	private static final Map<Vorgang.Status, Integer> BY_STATUS_MAP = Map.of(
+			Vorgang.Status.NEU, NEU_COUNT,
+			Vorgang.Status.ANGENOMMEN, ANGENOMMEN_COUNT,
+			Vorgang.Status.IN_BEARBEITUNG, IN_BEARBEITUNG_COUNT,
+			Vorgang.Status.BESCHIEDEN, BESCHIEDEN_COUNT,
+			Vorgang.Status.ABGESCHLOSSEN, ABGESCHLOSSEN_COUNT,
+			Vorgang.Status.VERWORFEN, VERWORFEN_COUNT,
+			Vorgang.Status.WEITERGELEITET, WEITERGELEITET_COUNT);
+
+	public static final String FIELD_PATH_ALIAS = "countByPathAlias";
+	public static final Integer FIELD_PATH_VALUE = 10;
+
+	public static final Map<String, Integer> BY_PATH_MAP = Map.of(FIELD_PATH_ALIAS, FIELD_PATH_VALUE);
+
+	public static final Map<String, Boolean> FIELD_EXISTS_MAP = Map.of(FIELD_PATH_ALIAS, true);
+
+	public static Statistic create() {
+		return createBuilder().build();
+	}
+
+	public static Statistic.StatisticBuilder createBuilder() {
+		return Statistic.builder()
+				.countByStatus(BY_STATUS_MAP)
+				.countResult(BY_PATH_MAP)
+				.existsResult(FIELD_EXISTS_MAP);
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/VorgangCountRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/VorgangCountRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..5426ab630c407a221dca36cda94926e570b6a153
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/VorgangCountRequestTestFactory.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+public class VorgangCountRequestTestFactory {
+
+	public static VorgangCountRequest create() {
+		return createBuilder().build();
+	}
+
+	public static VorgangCountRequest.VorgangCountRequestBuilder createBuilder() {
+		return VorgangCountRequest.builder().countByPath(CountPathRequestTestFactory.create());
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/VorgangStatisticRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/VorgangStatisticRequestTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7ff722d91613840f0ed7315c34aba72da68191f
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/statistic/VorgangStatisticRequestTestFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.statistic;
+
+import de.ozgcloud.vorgang.statistic.VorgangStatisticRequest.VorgangStatisticRequestBuilder;
+
+public class VorgangStatisticRequestTestFactory {
+
+	public static final String RESULT_NAME = "resultName";
+	public static final String REQUEST_FIELD_PATH = "Vorgang.fieldPath";
+	public static final String FIELD_PATH = "fieldPath";
+	public static final StatisticGroupMethod STATISTIC_GROUP_METHOD = StatisticGroupMethod.COUNT;
+
+	public static VorgangStatisticRequest create() {
+		return createBuilder().build();
+	}
+
+	public static VorgangStatisticRequestBuilder createBuilder() {
+		return VorgangStatisticRequest.builder()
+				.resultName(RESULT_NAME)
+				.fieldPath(REQUEST_FIELD_PATH)
+				.statisticGroupMethod(STATISTIC_GROUP_METHOD)
+				.operator(OperatorTestFactory.create());
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusEventListenerITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..21d6bcc6db617decbe12e184a194b2ebf624f056
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusEventListenerITCase.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.status;
+
+import static org.awaitility.Awaitility.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.command.PersistedCommand;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+@ITCase
+class StatusEventListenerITCase {
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	@MockBean
+	private StatusService statusService;
+
+	@MockBean
+	private VorgangService vorgangService;
+
+	@MockBean
+	private CommandService commandService;
+
+	@BeforeEach
+	void init() {
+		when(vorgangService.getById(anyString())).thenReturn(VorgangTestFactory.create());
+
+		when(commandService.findCommand(anyString())).thenReturn(Optional.of(CommandTestFactory.create()));
+	}
+
+	@DisplayName("Test creating status events")
+	@Nested
+	class TestStatusEvents {
+
+		@Test
+		void shouldCreateStatusChangeEventForVorgangAnnehmen() {
+			publishCommandCreatedEvent(Order.VORGANG_ANNEHMEN);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).annehmen(any()));
+		}
+
+		@Test
+		void shouldCreateStatusChangeEventForVorgangAbschliessen() {
+			publishCommandCreatedEvent(Order.VORGANG_ABSCHLIESSEN);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).abschliessen(any()));
+		}
+
+		@Test
+		void shouldCreateStatusChangeEventForVorgangBearbeiten() {
+			publishCommandCreatedEvent(Order.VORGANG_BEARBEITEN);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).bearbeiten(any()));
+		}
+
+		@Test
+		void shouldCreateStatusChangeEventForVorgangBescheiden() {
+			publishCommandCreatedEvent(Order.VORGANG_BESCHEIDEN);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).bescheiden(any()));
+		}
+
+		@Test
+		void shouldCreateStatusChangeEventForVorgangVerwerfen() {
+			publishCommandCreatedEvent(Order.VORGANG_VERWERFEN);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).verwerfen(any()));
+		}
+
+		@Test
+		void shouldCreateStatusChangeEventForVorgangWiedereroeffnen() {
+			publishCommandCreatedEvent(Order.VORGANG_WIEDEREROEFFNEN);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).wiedereroeffnen(any()));
+		}
+
+		@Test
+		void shouldCreateStatusChangeEventForVorgangZurueckholen() {
+			publishCommandCreatedEvent(Order.VORGANG_ZURUECKHOLEN);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).setStatusNeu(any()));
+		}
+
+		@Test
+		void shouldCreateStatusChangeEventForVorgangZurueckstellen() {
+			publishCommandCreatedEvent(Order.VORGANG_ZURUECKSTELLEN);
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).annehmen(any()));
+		}
+
+		@Nested
+		class ZumLoeschenMarkieren {
+			@Test
+			void shouldCallService() {
+				publishCommandCreatedEvent(Order.VORGANG_ZUM_LOESCHEN_MARKIEREN);
+
+				await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).zumLoeschenMarkieren(any()));
+			}
+		}
+
+		private void publishCommandCreatedEvent(Order order) {
+			publisher.publishEvent(CommandCreatedEventTestFactory.create(
+					CommandTestFactory.createBuilder().order(order.name()).build()));
+		}
+	}
+
+	@Nested
+	class TestRevokeStatusEvent {
+
+		@BeforeEach
+		void init() {
+			when(vorgangService.getById(anyString())).thenReturn(VorgangTestFactory.create());
+		}
+
+		@Test
+		void shouldSkipRevokeStatusEvents() {
+			var command = CommandTestFactory.createBuilder().order(Order.REDIRECT_VORGANG.name()).build();
+
+			publisher.publishEvent(new RevokeCommandEvent(command));
+
+			verify(statusService, never()).revokeStatusChange(any(PersistedCommand.class));
+		}
+
+		@DisplayName("Test revoking status events")
+		@ParameterizedTest(name = "should revoke status change event for {0}")
+		@ValueSource(strings = { "VORGANG_ANNEHMEN", "VORGANG_ABSCHLIESSEN", "VORGANG_BEARBEITEN",
+				"VORGANG_BESCHEIDEN", "VORGANG_VERWERFEN", "VORGANG_WIEDEREROEFFNEN", "VORGANG_ZURUECKHOLEN",
+				"VORGANG_ZURUECKSTELLEN", "VORGANG_ZUM_LOESCHEN_MARKIEREN" })
+		void shouldRevokeStatusChangeEvent(String orderName) {
+			var command = CommandTestFactory.createBuilder().order(orderName).build();
+
+			publisher.publishEvent(new RevokeCommandEvent(command));
+
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(statusService).revokeStatusChange(any(PersistedCommand.class)));
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusEventListenerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b9e68f0392c318a6b9d1edf0ae37486dbcf75f9
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusEventListenerTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.status;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandRevokeFailedEvent;
+import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.command.PersistedCommand;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemService;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+
+class StatusEventListenerTest {
+
+	@Spy
+	@InjectMocks
+	private StatusEventListener eventListener;
+
+	@Mock
+	private StatusService statusService;
+	@Mock
+	private VorgangService vorgangService;
+	@Mock
+	private VorgangAttachedItemService attachedItemService;
+
+	@Mock
+	private CommandService commandService;
+	@Mock
+	private CommandCreatedEvent event;
+	@Mock
+	private Command command;
+
+	@Mock
+	private ApplicationEventPublisher publisher;
+
+	@DisplayName("Test handling Vorgang status events")
+	@Nested
+	class TestVorgangStatusEvents {
+
+		@BeforeEach
+		void init() {
+			when(event.getSource()).thenReturn(command);
+			when(vorgangService.getById(any())).thenReturn(VorgangTestFactory.create());
+			when(commandService.findCommand(any())).thenReturn(Optional.of(CommandTestFactory.create()));
+		}
+
+		@Test
+		void shouldCallVorgangService() {
+			eventListener.abschiessen(event);
+
+			verify(vorgangService).getById(any());
+		}
+
+		@Test
+		void shouldCallCommandService() {
+			eventListener.abschiessen(event);
+
+			verify(commandService).findCommand(any());
+		}
+
+		@Test
+		void shouldHandleVorgangAbschliessen() {
+			eventListener.abschiessen(event);
+
+			verify(statusService).abschliessen(any());
+		}
+
+		@Test
+		void shouldHandleVorgangAnnehmen() {
+			eventListener.annehmen(event);
+
+			verify(statusService).annehmen(any());
+		}
+
+		@Test
+		void shouldHandleVorgangBearbeiten() {
+			eventListener.bearbeiten(event);
+
+			verify(statusService).bearbeiten(any());
+		}
+
+		@Test
+		void shouldHandleVorgangBescheiden() {
+			eventListener.bescheiden(event);
+
+			verify(statusService).bescheiden(any());
+		}
+
+		@Test
+		void shouldHandleVorgangVerwerfen() {
+			eventListener.verwerfen(event);
+
+			verify(statusService).verwerfen(any());
+		}
+
+		@Test
+		void shouldHandleVorgangWiedereroeffnen() {
+			eventListener.wiedereroeffnen(event);
+
+			verify(statusService).wiedereroeffnen(any());
+		}
+
+		@Test
+		void shouldHandleVorgangZurueckholen() {
+			eventListener.zurueckholen(event);
+
+			verify(statusService).setStatusNeu(any());
+		}
+
+		@Test
+		void shouldHandleVorgangZurueckstellen() {
+			eventListener.zurueckstellen(event);
+
+			verify(statusService).annehmen(any());
+		}
+
+		@Test
+		void shouldHandleZuLoeschenMarkieren() {
+			eventListener.zuLoeschenMarkieren(event);
+
+			verify(statusService).zumLoeschenMarkieren(notNull());
+		}
+	}
+
+	@DisplayName("Test setting the previous state value")
+	@Nested
+	class TestPreviousStatus {
+
+		@Test
+		void shouldSetPreviousStatusNeu() {
+			var map = eventListener.getPreviousStateMap(VorgangTestFactory.create());
+
+			assertThat(map).containsEntry(Vorgang.MONGODB_FIELDNAME_STATUS, Status.NEU);
+		}
+
+		@Test
+		void shouldSetPreviousStatusAbgeschlossen() {
+			var map = eventListener.getPreviousStateMap(VorgangTestFactory.createBuilder().status(Status.ABGESCHLOSSEN).build());
+
+			assertThat(map).containsEntry(Vorgang.MONGODB_FIELDNAME_STATUS, Status.ABGESCHLOSSEN);
+		}
+	}
+
+	@DisplayName("Test handling status revoked events")
+	@Nested
+	class TestStatusRevokedEvent {
+
+		@Test
+		void shouldHandleStatusRevokedEvent() {
+			eventListener.statusRevokedEvent(new RevokeCommandEvent(CommandTestFactory.create()));
+
+			verify(statusService).revokeStatusChange(any(PersistedCommand.class));
+		}
+
+		@Test
+		void shouldPublishFailedEventOnException() {
+			doThrow(new RuntimeException()).when(statusService).revokeStatusChange(any());
+
+			eventListener.statusRevokedEvent(new RevokeCommandEvent(CommandTestFactory.create()));
+
+			verify(publisher).publishEvent(any(CommandRevokeFailedEvent.class));
+		}
+	}
+
+	@DisplayName("Test handling exceptions")
+	@Nested
+	class TestExceptionHandling {
+
+		@Test
+		void shouldHandleNoSuchElementException() {
+			when(commandService.findCommand(any())).thenReturn(Optional.empty());
+			when(vorgangService.getById(any())).thenReturn(VorgangTestFactory.create());
+
+			eventListener.annehmen(CommandCreatedEventTestFactory.create(CommandTestFactory.create()));
+
+			verify(publisher).publishEvent(any(CommandFailedEvent.class));
+		}
+
+		@Test
+		void shouldHandleNotFoundException() {
+			when(vorgangService.getById(any())).thenThrow(NotFoundException.class);
+
+			eventListener.annehmen(CommandCreatedEventTestFactory.create(CommandTestFactory.create()));
+
+			verify(publisher).publishEvent(any(CommandFailedEvent.class));
+		}
+	}
+
+	@DisplayName("Test predicated for filtering CommandCreatedEvents")
+	@Nested
+	class TestPredicates {
+
+		@ParameterizedTest
+		@MethodSource("knownOrdersAndMatchingPredicated")
+		void shouldFilter(Order order, Predicate<Command> predicate) {
+			assertThat(predicate.test(CommandTestFactory.createBuilder().order(order.name()).build())).isTrue();
+		}
+
+		@ParameterizedTest
+		@MethodSource("knownOrdersAndMatchingPredicated")
+		void shouldNotFilter(Order order, Predicate<Command> predicate) {
+			assertThat(predicate.test(CommandTestFactory.createBuilder().order(Order.ASSIGN_USER.name()).build())).isFalse();
+		}
+
+		private static Stream<Arguments> knownOrdersAndMatchingPredicated() {
+			return Stream.of(
+					Arguments.of(Order.VORGANG_ABSCHLIESSEN, StatusEventListener.IS_ABSCHLIESSEN_EVENT),
+					Arguments.of(Order.VORGANG_ANNEHMEN, StatusEventListener.IS_ANNEHMEN_EVENT),
+					Arguments.of(Order.VORGANG_BEARBEITEN, StatusEventListener.IS_BEARBEITEN_EVENT),
+					Arguments.of(Order.VORGANG_BESCHEIDEN, StatusEventListener.IS_BESCHEIDEN_EVENT),
+					Arguments.of(Order.VORGANG_VERWERFEN, StatusEventListener.IS_VERWERFEN_EVENT),
+					Arguments.of(Order.VORGANG_WIEDEREROEFFNEN, StatusEventListener.IS_WIEDEREROEFFNEN_EVENT),
+					Arguments.of(Order.VORGANG_ZURUECKHOLEN, StatusEventListener.IS_ZURUECKHOLEN_EVENT),
+					Arguments.of(Order.VORGANG_ZURUECKSTELLEN, StatusEventListener.IS_ZURUECKSTELLEN_EVENT));
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusRepositoryITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3149e7164983742505da49c6379568accc6fcff
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusRepositoryITCase.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.status;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.ConcurrentModificationException;
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoOperations;
+
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+@DataITCase
+class StatusRepositoryITCase {
+
+	@Autowired
+	private StatusRepository repository;
+	@Autowired
+	private MongoOperations mongoOperations;
+
+	@Nested
+	class TestUpdateStatus {
+
+		@BeforeEach
+		void init() {
+			mongoOperations.dropCollection(Vorgang.class);
+
+			mongoOperations.save(VorgangTestFactory.create());
+		}
+
+		@Test
+		void shouldUpdateVorgangStatus() {
+			repository.patch(VorgangTestFactory.ID, VorgangTestFactory.VERSION, Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Status.IN_BEARBEITUNG));
+
+			assertThat(mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class).getStatus()).isEqualTo(Status.IN_BEARBEITUNG);
+		}
+
+		@Test
+		void shouldUpdateVorgangVersion() {
+			repository.patch(VorgangTestFactory.ID, VorgangTestFactory.VERSION, Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Status.ANGENOMMEN));
+
+			assertThat(mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class).getVersion()).isEqualTo(VorgangTestFactory.VERSION + 1);
+		}
+
+		@Test
+		void shouldNotUpdateOnVersionMismatch() {
+			Map<String, Object> patch = Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Status.VERWORFEN.toString());
+
+			assertThatThrownBy(() -> repository.patch(VorgangTestFactory.ID, VorgangTestFactory.VERSION + 5, patch))
+					.isInstanceOf(ConcurrentModificationException.class);
+
+			var vorgang = mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
+			assertThat(vorgang.getVersion()).isEqualTo(VorgangTestFactory.VERSION);
+			assertThat(vorgang.getStatus()).isEqualTo(VorgangTestFactory.STATUS);
+		}
+	}
+
+	@Nested
+	class TestUpdateStatusWithoutVersionCheck {
+
+		@BeforeEach
+		void init() {
+			mongoOperations.dropCollection(Vorgang.class);
+
+			mongoOperations.save(VorgangTestFactory.create());
+		}
+
+		@Test
+		void shouldUpdateVorgangStatus() {
+			repository.updateStatusWithoutVersionCheck(VorgangTestFactory.ID, Status.VERWORFEN);
+
+			assertThat(mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class).getStatus()).isEqualTo(Status.VERWORFEN);
+		}
+
+		@Test
+		void shouldUpdateVorgangVersion() {
+			repository.updateStatusWithoutVersionCheck(VorgangTestFactory.ID, Status.VERWORFEN);
+
+			assertThat(mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class).getVersion()).isEqualTo(VorgangTestFactory.VERSION + 1);
+		}
+	}
+
+	@Nested
+	class TestStatusChangeWithCollision {
+
+		private final Map<String, Object> STATUS_PATCH = Map.of("status", Vorgang.Status.BESCHIEDEN.toString());
+
+		@Test
+		void shouldThrowException() {
+			mongoOperations.save(VorgangTestFactory.create());
+
+			assertThatThrownBy(() -> repository.patch(VorgangTestFactory.ID, VorgangTestFactory.VERSION - 1, STATUS_PATCH))
+					.isInstanceOf(ConcurrentModificationException.class);
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusRepositoryTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusRepositoryTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ede0bdbd7f6fcb3bef6d85ff2e624647e9e15fef
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusRepositoryTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.status;
+
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.data.mongodb.core.MongoOperations;
+
+import com.mongodb.client.result.UpdateResult;
+
+import de.ozgcloud.vorgang.common.db.CollisionVerifier;
+
+class StatusRepositoryTest {
+
+	@InjectMocks
+	@Spy
+	private StatusRepository repository;
+
+	@Mock
+	private MongoOperations mongoOperations;
+	@Mock
+	private CollisionVerifier collisionVerifier;
+
+	@Test
+	void shouldCallCollisionVerifier() {
+		var updateResult = mock(UpdateResult.class);
+		when(mongoOperations.updateFirst(any(), any(), any(Class.class))).thenReturn(updateResult);
+
+		repository.patch("vorgangId", 1, Map.of());
+
+		verify(collisionVerifier).verify(any(UpdateResult.class), eq("vorgangId"));
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..48402f85fdcc10ecd454d0fe67d377a5521d0cda
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/status/StatusServiceTest.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.status;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ConcurrentModificationException;
+import java.util.Map;
+import java.util.Optional;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.command.CommandRevokedEvent;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.PersistedCommand;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+class StatusServiceTest {
+
+	@DisplayName("Test handling vorgang status changes")
+	@Nested
+	class TestVorgangStatusChanges {
+		@Spy
+		@InjectMocks
+		private StatusService service;
+
+		@Mock
+		private StatusRepository repository;
+
+		@Mock
+		private ApplicationEventPublisher publisher;
+
+		private PersistedCommand command = CommandTestFactory.create();
+
+		@DisplayName("Test Vorgang ABSCHLIESSEN events")
+		@Nested
+		class OnVorgangAbschliessen {
+
+			@Test
+			void shouldHandleVorgangAbschliessen() {
+				service.abschliessen(command);
+
+				verify(repository).patch(anyString(), anyLong(), any());
+			}
+
+			@Test
+			void shouldUpdateStatus() {
+				service.abschliessen(command);
+
+				verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.ABGESCHLOSSEN.name())));
+			}
+		}
+
+		@DisplayName("Test Vorgang ANNEHMEN events")
+		@Nested
+		class OnVorgangAnnehmen {
+			@Test
+			void shouldHandleVorgangAnnehmen() {
+				service.annehmen(command);
+
+				verify(repository).patch(anyString(), anyLong(), any());
+			}
+
+			@Test
+			void shouldUpdateStatus() {
+				service.annehmen(command);
+
+				verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.ANGENOMMEN.name())));
+			}
+		}
+
+		@DisplayName("Test Vorgang IN_BEARBEITUNG events")
+		@Nested
+		class OnVorgangBearbieten {
+			@Test
+			void shouldHandleVorgangBearbeiten() {
+				service.bearbeiten(command);
+
+				verify(repository).patch(anyString(), anyLong(), any());
+			}
+
+			@Test
+			void shouldUpdateStatus() {
+				service.bearbeiten(command);
+
+				verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.IN_BEARBEITUNG.name())));
+			}
+		}
+
+		@DisplayName("Test Vorgang BESCHIEDEN events")
+		@Nested
+		class OnVorgangBescheiden {
+			@Test
+			void shouldHandleVorgangBeschieden() {
+				service.bescheiden(command);
+
+				verify(repository).patch(anyString(), anyLong(), any());
+			}
+
+			@Test
+			void shouldUpdateStatus() {
+				service.bescheiden(command);
+
+				verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.BESCHIEDEN.name())));
+			}
+		}
+
+		@DisplayName("Test Vorgang VERWORFEN events")
+		@Nested
+		class OnVorgangVerwerfen {
+			@Test
+			void shouldHandleVorgangVerworfen() {
+				service.verwerfen(command);
+
+				verify(repository).patch(anyString(), anyLong(), any());
+			}
+
+			@Test
+			void shouldUpdateStatus() {
+				service.verwerfen(command);
+
+				verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.VERWORFEN.name())));
+			}
+		}
+
+		@DisplayName("Test Vorgang WIEDEREROEFFNEN events")
+		@Nested
+		class OnVorgangWiedereroeffnen {
+			@Test
+			void shouldHandleVorgangWiedereroeffnen() {
+				service.wiedereroeffnen(command);
+
+				verify(repository).patch(anyString(), anyLong(), any());
+			}
+
+			@Test
+			void shouldUpdateStatus() {
+				service.bearbeiten(command);
+
+				verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.IN_BEARBEITUNG.name())));
+			}
+		}
+
+		@DisplayName("Test Vorgang ZURUECKHOLEN events")
+		@Nested
+		class OnVorgangZurueckholen {
+			@Test
+			void shouldHandleVorgangZurueckholen() {
+				service.setStatusNeu(command);
+
+				verify(repository).patch(anyString(), anyLong(), any());
+			}
+
+			@Test
+			void shouldUpdateStatus() {
+				service.setStatusNeu(command);
+
+				verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.NEU.name())));
+			}
+		}
+
+		@DisplayName("Test Vorgang ZURUECKSTELLEN events")
+		@Nested
+		class OnVorgangZurueckstellen {
+			@Test
+			void shouldHandleVorgangZurueckStellen() {
+				service.annehmen(command);
+
+				verify(repository).patch(anyString(), anyLong(), any());
+			}
+
+			@Test
+			void shouldUpdateStatus() {
+				service.annehmen(command);
+
+				verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.ANGENOMMEN.name())));
+			}
+		}
+
+		@DisplayName("Test Vorgang ZUM LOESCHEN MARKIEREN events")
+		@Nested
+		class OnVorgangZumLoeschenMarkieren {
+			@Test
+			void shouldHandleVorgangZumLoeschenMarkieren() {
+				service.zumLoeschenMarkieren(command);
+
+				verify(service).executeStatusChangeCommand(command, Status.ZU_LOESCHEN);
+			}
+		}
+
+		@Nested
+		@DisplayName("Changing status by command")
+		class TestExecuteStatsuChangeByCommand {
+
+			private Command command = CommandTestFactory.create();
+
+			@Test
+			@DisplayName("should trigger status change")
+			void shouldTriggerUpdate() {
+				service.executeStatusChangeCommand(command, Status.ANGENOMMEN);
+
+				verify(service).doUpdateStatus(CommandTestFactory.RELATION_ID, CommandTestFactory.RELATION_VERSION, Status.ANGENOMMEN.toString());
+			}
+
+			@Test
+			@DisplayName("should publish status changed event")
+			void shouldPublishEvent() {
+				service.executeStatusChangeCommand(command, Status.ANGENOMMEN);
+
+				verify(publisher).publishEvent(any(StatusChangedEvent.class));
+			}
+
+			@Test
+			@DisplayName("should publish failed event on error")
+			void shouldPublishFailedEvent() {
+				doThrow(ConcurrentModificationException.class).when(service).doUpdateStatus(anyString(), anyLong(), anyString());
+
+				service.executeStatusChangeCommand(command, Status.ANGENOMMEN);
+
+				verify(publisher).publishEvent(any(CommandFailedEvent.class));
+			}
+		}
+
+	}
+
+	@DisplayName("Test status changes when a Vorgang is forwarded")
+	@Nested
+	class TestVorgangWeiterleiten {
+		@Spy
+		@InjectMocks
+		private StatusService service;
+
+		@Mock
+		private StatusRepository repository;
+
+		@Mock
+		private ApplicationEventPublisher publisher;
+
+		@Mock
+		private PersistedCommand command;
+
+		@Test
+		void shouldNotUpdateVersionOnWeitergeleitet() {
+			service.setStatusToWeitergeleitet(VorgangTestFactory.ID, CommandTestFactory.ID);
+
+			verify(repository).updateStatusWithoutVersionCheck(anyString(), eq(Vorgang.Status.WEITERGELEITET));
+		}
+
+		@Test
+		void shouldNotUpdateVersionOnBearbeitet() {
+			service.setStatusToInBearbeitung(VorgangTestFactory.ID, CommandTestFactory.ID);
+
+			verify(repository).updateStatusWithoutVersionCheck(anyString(), eq(Vorgang.Status.IN_BEARBEITUNG));
+		}
+
+		@Test
+		void shouldPatchOnInBearbeitung() {
+			service.setStatusToInBearbeitung(VorgangTestFactory.ID, VorgangTestFactory.VERSION);
+
+			verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.IN_BEARBEITUNG.name())));
+		}
+	}
+
+	@DisplayName("Test handling revoke command status changes")
+	@Nested
+	class TestRevokeStatusChanges {
+		@Spy
+		@InjectMocks
+		private StatusService service;
+
+		@Mock
+		private StatusRepository repository;
+
+		@Mock
+		private ApplicationEventPublisher publisher;
+
+		private static final String PREVIOUS_STATUS = Vorgang.Status.BESCHIEDEN.name();
+		private PersistedCommand command = CommandTestFactory.createBuilder()
+				.previousState(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, PREVIOUS_STATUS)).build();
+
+		@Test
+		void shouldUpdateVersion() {
+			service.revokeStatusChange(command);
+
+			verify(repository).patch(anyString(), eq(CommandTestFactory.RELATION_VERSION + 1), any());
+		}
+
+		@Test
+		void shouldUpdateStatus() {
+			service.revokeStatusChange(command);
+
+			verify(repository).patch(anyString(), anyLong(), eq(Map.of(Vorgang.MONGODB_FIELDNAME_STATUS, Vorgang.Status.BESCHIEDEN.name())));
+		}
+
+		@Test
+		void shouldPublishEvent() {
+			service.revokeStatusChange(command);
+
+			verify(publisher).publishEvent(any(CommandRevokedEvent.class));
+		}
+
+		@Test
+		void shouldPublishFailEventOnConcurrentModification() {
+			doThrow(ConcurrentModificationException.class).when(service).doUpdateStatus(any(), anyLong(), any());
+
+			service.revokeStatusChange(command);
+
+			verify(publisher).publishEvent(any(CommandFailedEvent.class));
+		}
+
+		@Test
+		void shouldThrowTechnicalExceptionOnWrongPrevState() {
+			doReturn(Optional.empty()).when(service).getPreviousStatus(any());
+
+			assertThatThrownBy(() -> service.revokeStatusChange(command)).isInstanceOf(TechnicalException.class);
+		}
+
+		@Nested
+		class TestCheckPreviousStatus {
+			@Test
+			void shouldReturnStatus() {
+				var prevStatus = service.getPreviousStatus(command);
+
+				assertThat(prevStatus).contains(PREVIOUS_STATUS);
+			}
+
+			@Test
+			void shouldReturnEmptyOnMissingState() {
+				var prevStatus = service.getPreviousStatus(CommandTestFactory.createBuilder().previousState(null).build());
+
+				assertThat(prevStatus).isEmpty();
+			}
+
+			@Test
+			void shouldReturnEmptyOnEmptyState() {
+				var prevStatus = service.getPreviousStatus(CommandTestFactory.createBuilder().previousState(Map.of()).build());
+
+				assertThat(prevStatus).isEmpty();
+			}
+
+			@Test
+			void shouldReturnEmptyOnWrongStateField() {
+				var prevStatus = service.getPreviousStatus(CommandTestFactory.create());
+
+				assertThat(prevStatus).isEmpty();
+			}
+		}
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/system/SystemStatusGrpcServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/system/SystemStatusGrpcServiceTest.java
similarity index 95%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/system/SystemStatusGrpcServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/system/SystemStatusGrpcServiceTest.java
index 5014e7a150a69c275aa75d36c634736f739a77c9..8ff2ac16114293684c29bbcd8a2b070c84601941 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/system/SystemStatusGrpcServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/system/SystemStatusGrpcServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.system;
+package de.ozgcloud.vorgang.system;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
 
-import de.itvsh.ozg.pluto.common.search.SearchService;
-import io.grpc.stub.StreamObserver;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -36,8 +37,8 @@ import org.mockito.Mock;
 import org.springframework.boot.info.BuildProperties;
 import org.springframework.test.util.ReflectionTestUtils;
 
-import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
+import de.ozgcloud.vorgang.common.search.SearchService;
+import io.grpc.stub.StreamObserver;
 
 class SystemStatusGrpcServiceTest {
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/DeleteUserSchedulerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/DeleteUserSchedulerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f58885de7f2bc648f13dd3ec38cf6c360b4f625
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/DeleteUserSchedulerTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.user;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.vorgang.command.CommandService;
+
+class DeleteUserSchedulerTest {
+
+	@InjectMocks
+	private DeleteUserScheduler scheduler;
+
+	@Mock
+	private UserService service;
+	@Mock
+	private CommandService commandService;
+
+	@Test
+	void shouldCallFindInactiveUserIds() {
+		when(service.findInactiveUserIds()).thenReturn(Stream.empty());
+
+		scheduler.deleteUsers();
+
+		verify(service).findInactiveUserIds();
+	}
+
+	@Test
+	void shouldCallExistsCommandWithUserIds() {
+		var userId = "userId";
+		when(service.findInactiveUserIds()).thenReturn(Stream.of(userId));
+
+		scheduler.deleteUsers();
+
+		verify(commandService).existsCommandWithUserId(userId);
+	}
+
+	@Test
+	void shouldCallDeleteInactiveUser() {
+		var userId = "userId";
+		when(service.findInactiveUserIds()).thenReturn(Stream.of(userId));
+
+		scheduler.deleteUsers();
+
+		verify(service).deleteInactiveUser(userId);
+	}
+
+	@Nested
+	class TestCatchException {
+
+		@Test
+		void shouldCatchFindUserIds() {
+			when(service.findInactiveUserIds()).thenThrow(new RuntimeException());
+
+			assertThatNoException().isThrownBy(scheduler::deleteUsers);
+		}
+
+		@Test
+			void shouldCatchExistsCommandWithUserIds() {
+			when(service.findInactiveUserIds()).thenReturn(Stream.of("userId"));
+			when(commandService.existsCommandWithUserId(anyString())).thenThrow(new RuntimeException());
+
+			assertThatNoException().isThrownBy(scheduler::deleteUsers);
+		}
+
+		@Test
+		void shouldCatchDeleteInactiveUsers() {
+			when(service.findInactiveUserIds()).thenReturn(Stream.of("userId"));
+			doThrow(new RuntimeException()).when(service).deleteInactiveUser(anyString());
+
+			assertThatNoException().isThrownBy(scheduler::deleteUsers);
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/UserProfileRemoteServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/UserProfileRemoteServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..57a37291dd47a88d99da12b24d0b7ae311090a03
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/UserProfileRemoteServiceTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.user;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import de.ozgcloud.user.grpc.userprofile.UserProfileServiceGrpc.UserProfileServiceBlockingStub;
+import de.ozgcloud.user.userprofile.GrpcDeleteInactiveUserRequest;
+import de.ozgcloud.user.userprofile.GrpcFindInactiveUserIdsResponse;
+import de.ozgcloud.user.userprofile.GrpcUserProfileId;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+
+class UserProfileRemoteServiceTest {
+
+	@Spy
+	@InjectMocks
+	private UserProfileRemoteService service;
+
+	@Mock
+	private UserProfileServiceBlockingStub userProfileServiceStub;
+
+	private static final GrpcFindInactiveUserIdsResponse RESPONSE = GrpcFindInactiveUserIdsResponse.newBuilder()
+			.addUserProfileIds(GrpcUserProfileId.newBuilder().setId(UserTestFactory.ID)).build();
+
+	@Nested
+	class TestFindInactiveUserIds {
+
+		@BeforeEach
+		void setup() {
+			doReturn(userProfileServiceStub).when(service).getUserServiceStub();
+			when(userProfileServiceStub.findInactiveUserIds(any())).thenReturn(RESPONSE);
+		}
+
+		@Test
+		void shouldCallUserServiceStub() {
+			service.findInactiveUserIds();
+
+			verify(userProfileServiceStub).findInactiveUserIds(any());
+		}
+
+		@Test
+		void shouldMapResponse() {
+			service.findInactiveUserIds();
+
+			verify(service).mapFindInactiveUserIdsResponse(RESPONSE);
+		}
+	}
+
+	@Nested
+	class TestResponseMapping {
+
+		@Test
+		void shouldReturnUserIds() {
+			var result = service.mapFindInactiveUserIdsResponse(RESPONSE);
+
+			assertThat(result).containsExactly(UserTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestDeleteInactiveUser {
+
+		@BeforeEach
+		void setup() {
+			doReturn(userProfileServiceStub).when(service).getUserServiceStub();
+		}
+
+		@Test
+		void shouldCallUserServiceStub() {
+			var deleteRequest = GrpcDeleteInactiveUserRequest.newBuilder().setUserId(UserTestFactory.ID).build();
+			doReturn(deleteRequest).when(service).buildDeleteInactiveUsersRequest(any());
+
+			service.deleteInactiveUser(UserTestFactory.ID);
+
+			verify(userProfileServiceStub).deleteInactiveUser(deleteRequest);
+		}
+
+		@Test
+		void shouldCallBuildRequest() {
+			service.deleteInactiveUser(UserTestFactory.ID);
+
+			verify(service).buildDeleteInactiveUsersRequest(UserTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestBuildDeleteInactiveUsersRequest {
+
+		@Test
+		void shouldBuildRequest() {
+			var result = service.buildDeleteInactiveUsersRequest(UserTestFactory.ID);
+
+			assertThat(result.getUserId()).isEqualTo(UserTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestGetInterceptor {
+
+		@Test
+		void shouldCallSetInterceptor() {
+			service.getUserServiceStub();
+
+			verify(userProfileServiceStub).withInterceptors(any());
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/UserServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/UserServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..05ed5a42b5708d757f2d6224366f10ab6f6633ba
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/UserServiceTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.user;
+
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+
+class UserServiceTest {
+
+	@InjectMocks
+	private UserService service;
+
+	@Mock
+	private UserProfileRemoteService userRemoteService;
+
+	@Nested
+	class TestFindInactiveUserIds {
+
+		@Test
+		void shouldCallUserRemoteService() {
+			service.findInactiveUserIds();
+
+			verify(userRemoteService).findInactiveUserIds();
+		}
+	}
+
+	@Nested
+	class TestDeleteInactiveUsers {
+
+		@Test
+		void shouldCallUserRemoteService() {
+			service.deleteInactiveUser(UserTestFactory.ID);
+
+			verify(userRemoteService).deleteInactiveUser(UserTestFactory.ID);
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/VorgangManagerCallContextAttachingInterceptorTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/VorgangManagerCallContextAttachingInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a20578fdc8ab5249e23e253b66992012cf5a292
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/user/VorgangManagerCallContextAttachingInterceptorTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.user;
+
+import static de.ozgcloud.common.grpc.GrpcUtil.*;
+import static de.ozgcloud.vorgang.user.VorgangManagerCallContextAttachingInterceptor.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+
+class VorgangManagerCallContextAttachingInterceptorTest {
+
+	@InjectMocks
+	private VorgangManagerCallContextAttachingInterceptor interceptor;
+
+	@Nested
+	class TestInterceptCall<A, B> {
+
+		@Mock
+		private MethodDescriptor<A, B> method;
+		@Mock
+		private CallOptions callOptions;
+		@Mock
+		private Channel next;
+		@Mock
+		private ClientCall<Object, Object> nextCall;
+
+		@Mock
+		private ClientCall.Listener<B> listener;
+		@Mock
+		private Metadata headers;
+		@Captor
+		private ArgumentCaptor<Metadata> metadataCaptor;
+
+		@BeforeEach
+		void initMocks() {
+			when(next.newCall(any(), any())).thenReturn(nextCall);
+		}
+
+		@Test
+		void shouldAddUserId() {
+			var addedMetadata = interceptCall();
+
+			assertThat(addedMetadata.get(createKeyOf(KEY_USER_ID))).isEqualTo(VORGANG_MANAGER_SENDER_USER_ID.getBytes());
+		}
+
+		@Test
+		void shouldAddClientName() {
+			var addedMetadata = interceptCall();
+
+			assertThat(addedMetadata.get(createKeyOf(KEY_CLIENT_NAME))).isEqualTo(VORGANG_MANAGER_CLIENT_NAME.getBytes());
+		}
+
+		@Test
+		void shouldAddRequestId() {
+			var addedMetadata = interceptCall();
+
+			assertThat(addedMetadata.get(createKeyOf(KEY_REQUEST_ID))).isNotNull();
+		}
+
+		private Metadata interceptCall() {
+			var call = interceptor.interceptCall(method, callOptions, next);
+
+			call.start(listener, headers);
+
+			verify(headers).merge(metadataCaptor.capture());
+			return metadataCaptor.getValue();
+		}
+	}
+
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderEATest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderEATest.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderEATest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderEATest.java
index 0e51d59bad24c78fcd685bd06f94f70cec46680d..3c8665d2070af46d7ab99341a70ce6b625d703b2 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenProviderEATest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AktenzeichenProviderEATest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AktenzeichenServiceITCase.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenServiceITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AktenzeichenServiceITCase.java
index e7af5a6be7b3721b60b4834e2df264b525603694..2a74ca5d5a47611ee34e570888b651e9fbbf4dbc 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AktenzeichenServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AktenzeichenServiceITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -29,7 +29,7 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import de.itvsh.kop.common.test.ITCase;
+import de.ozgcloud.common.test.ITCase;
 
 @ITCase
 class AktenzeichenServiceITCase {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AntragstellerMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AntragstellerMapperTest.java
similarity index 93%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AntragstellerMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AntragstellerMapperTest.java
index e3331ea28e14a13eac3381d5a83cff5b09f37feb..3ded5e7ab335b3bb9e73122b77dbe0732db08043 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AntragstellerMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AntragstellerMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
@@ -32,7 +32,7 @@ import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcFormDataMapper;
+import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper;
 
 class AntragstellerMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AntragstellerTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AntragstellerTestFactory.java
similarity index 96%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AntragstellerTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AntragstellerTestFactory.java
index 0cee8bdbbd5c0df61929e856cace8a93bee02afb..6dffcc0a9c83c20f7475f8ff6afd552292cab673 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/AntragstellerTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/AntragstellerTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.Map;
 import java.util.UUID;
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/DefaultAktenzeichenProviderTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/DefaultAktenzeichenProviderTest.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/DefaultAktenzeichenProviderTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/DefaultAktenzeichenProviderTest.java
index 34fef9375d56cef39f20bba5012db950ee4ea5f3..eb97e3daf75746e364958441545c9fd1be85fee7 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/DefaultAktenzeichenProviderTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/DefaultAktenzeichenProviderTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangHeaderMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangHeaderMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8b2d32e4937927fdad6b0f12ea866aded85eb758
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangHeaderMapperTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import de.ozgcloud.vorgang.servicekonto.GrpcServiceKontoTestFactory;
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoMapper;
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoTestFactory;
+
+@DisplayName("Eingang header mapper")
+class EingangHeaderMapperTest {
+
+	@InjectMocks
+	private final EingangHeaderMapper mapper = Mappers.getMapper(EingangHeaderMapper.class);
+	@Mock
+	private final ServiceKontoMapper serviceKontoMapper = Mappers.getMapper(ServiceKontoMapper.class);
+
+	@DisplayName("map from grpc")
+	@Nested
+	class TestFromGrpc {
+
+		@BeforeEach
+		void mockPostfachAddressMapper() {
+			when(serviceKontoMapper.fromServiceKonto(any())).thenReturn(ServiceKontoTestFactory.create());
+		}
+
+		@Test
+		void shouldCallPostfachAddressMapper() {
+			fromGrpc();
+
+			verify(serviceKontoMapper).fromServiceKonto(any());
+		}
+
+		@Test
+		void shouldMapDateStrToZonedDateTime() {
+			var eingangHeader = fromGrpc();
+
+			assertThat(eingangHeader.getCreatedAt()).isEqualTo(GrpcEingangHeaderTestFactory.CREATED_AT);
+		}
+
+		@Test
+		void shouldMapAllFields() {
+			var eingangHeader = fromGrpc();
+
+			assertThat(eingangHeader).usingRecursiveComparison().ignoringFields("serviceKonto").isEqualTo(EingangHeaderTestFactory.create());
+		}
+
+		private EingangHeader fromGrpc() {
+			return mapper.fromGrpc(GrpcEingangHeaderTestFactory.create());
+		}
+	}
+
+	@DisplayName("map to grpc")
+	@Nested
+	class TestToGrpc {
+
+		@BeforeEach
+		void mockPostfachAddressMapper() {
+			when(serviceKontoMapper.toServiceKonto(any())).thenReturn(GrpcServiceKontoTestFactory.create());
+		}
+
+		@Test
+		void shouldMapZonedDateTimeToDateStr() {
+			var eingangHeader = fromGrpc(EingangHeaderTestFactory.create());
+
+			assertThat(eingangHeader.getCreatedAt()).isEqualTo(EingangHeaderTestFactory.CREATED_AT_STR);
+		}
+
+		@Test
+		void shouldProceedWithEmptyValues() {
+			var eingangHeader = fromGrpc(EingangHeaderTestFactory.createBuilder().createdAt(null).build());
+
+			assertThat(eingangHeader.getCreatedAt()).isEqualTo(StringUtils.EMPTY);
+		}
+
+		private GrpcEingangHeader fromGrpc(EingangHeader eingangHeader) {
+			return mapper.toGrpc(eingangHeader);
+		}
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangHeaderTestFactory.java
similarity index 84%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangHeaderTestFactory.java
index d9e87ac45f1ee1e429730fc896553c1ac10b43c8..d64ca3c2b8930b153205d7086ee2d491ac16e183 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangHeaderTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangHeaderTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.time.ZonedDateTime;
 import java.util.UUID;
 
 import com.thedeanda.lorem.LoremIpsum;
 
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoTestFactory;
+
 public class EingangHeaderTestFactory {
 
 	public static final String CREATED_AT_STR = "2021-01-10T10:30:00Z";
@@ -39,6 +41,8 @@ public class EingangHeaderTestFactory {
 	public static final String FORM_ID = UUID.randomUUID().toString();
 	public static final String SENDER = LoremIpsum.getInstance().getWords(2);
 
+	public static final String VORGANG_NUMMER = "1234";
+
 	public static EingangHeader create() {
 		return createBuilder().build();
 	}
@@ -50,7 +54,9 @@ public class EingangHeaderTestFactory {
 				.formId(FORM_ID)
 				.formName(FORM_NAME)
 				.formEngineName(VorgangTestFactory.FORM_ENGINE_NAME)
-				.sender(SENDER);
+				.vorgangNummer(VORGANG_NUMMER)
+				.sender(SENDER)
+				.serviceKonto(ServiceKontoTestFactory.create());
 
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangMapperTest.java
similarity index 89%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangMapperTest.java
index eb3bdcb3854f0a2bc506c1f9380f2041f5f01223..e343c9c1e4ebcd9b4fd3fa45f79499861fbd53e0 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import static de.itvsh.kop.pluto.common.grpc.GrpcSubFormTestFactory.*;
+import static de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory.*;
+import static de.ozgcloud.vorgang.vorgang.LabelProcessor.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -42,9 +43,9 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.springframework.test.util.ReflectionTestUtils;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcFormDataMapper;
-import de.itvsh.kop.pluto.common.grpc.GrpcSubFormTestFactory;
-import de.itvsh.ozg.pluto.files.FileIdMapper;
+import de.ozgcloud.vorgang.common.grpc.GrpcFormDataMapper;
+import de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory;
+import de.ozgcloud.vorgang.files.FileIdMapper;
 
 class EingangMapperTest {
 
@@ -149,22 +150,28 @@ class EingangMapperTest {
 			@Test
 			void fieldsInSubForm() {
 				var eingang = mapper.fromGrpc(grpcEingang);
-				@SuppressWarnings("unchecked")
-				Map<String, Object> formData = (Map<String, Object>) eingang.getFormData().get(TITLE);
 
-				assertThat(formData).containsEntry(FIELD_NAME, FIELD_VALUE);
+				Map<String, Object> formData = getSubForm(eingang);
+				assertThat(formData).containsEntry(FIELD_NAME, FIELD);
 			}
 
 			@DisplayName("mapped FormData should contains subForm")
 			@Test
 			void shouldHaveMappedSubFormWithSubForm() {
 				var eingang = mapper.fromGrpc(grpcEingang);
-				@SuppressWarnings("unchecked")
-				Map<String, Object> formData = (Map<String, Object>) eingang.getFormData().get(TITLE);
 
-				assertThat(formData).containsKey(GrpcSubFormTestFactory.SUBFORM_NAME);
+				Map<String, Object> formData = getSubForm(eingang);
+				assertThat(formData).containsKey(GrpcSubFormTestFactory.SUBFORM_TITLE);
 			}
 
+			@SuppressWarnings("unchecked")
+			private Map<String, Object> getSubForm(Eingang eingang) {
+				Map<String, Object> formData = (Map<String, Object>) eingang.getFormData().get(TITLE);
+				formData = (Map<String, Object>) formData.get(VALUE_KEY);
+				return formData;
+			}
+
+			@SuppressWarnings("unchecked")
 			@DisplayName("mapped SubForm should contain List of SubForms")
 			@Test
 			void shouldHaveMappedListOfSubForms() {
@@ -174,20 +181,23 @@ class EingangMapperTest {
 						.build()).build();
 
 				var eingang = mapper.fromGrpc(grpcEingang);
-				@SuppressWarnings("unchecked")
-				var formData = (List<Map<String, Object>>) eingang.getFormData().get(TITLE);
 
-				assertThat(formData).contains(EingangTestFactory.FORM_DATA, EingangTestFactory.FORM_DATA);
+				var formData = (Map<String, Object>) eingang.getFormData().get(TITLE);
+				var formList = (List<Map<String, Object>>) formData.get(VALUE_KEY);
+
+				assertThat(formList).contains(EingangTestFactory.FORM_DATA, EingangTestFactory.FORM_DATA);
 			}
 
+			@SuppressWarnings("unchecked")
 			@DisplayName("mapped SubForm should contain field")
 			@Test
 			void subFormShouldContainField() {
 				var eingang = mapper.fromGrpc(grpcEingang);
-				@SuppressWarnings("unchecked")
-				Map<String, Object> subForm = (Map<String, Object>) ((Map<String, Object>) eingang.getFormData().get(TITLE)).get(SUBFORM_NAME);
 
-				assertThat(subForm).containsEntry(SUBFORM_FIELD_NAME, SUBFORM_FIELD_VALUE);
+				Map<String, Object> subForm = (Map<String, Object>) getSubForm(eingang).get(SUBFORM_TITLE);
+				subForm = (Map<String, Object>) subForm.get(VALUE_KEY);
+
+				assertThat(subForm).containsEntry(SUBFORM_FIELD_NAME, SUBFORM_FIELD);
 			}
 		}
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangTestFactory.java
similarity index 69%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangTestFactory.java
index 8fcfc1965cd879b9831ccf48e036eebb95ddd054..2f159b648610da0e8310d6706f9db8c44e28d3a7 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/EingangTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/EingangTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,26 +21,33 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.Map;
 import java.util.UUID;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcSubFormTestFactory;
+import de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory;
 
 public class EingangTestFactory {
 
 	public static final String ID = UUID.randomUUID().toString();
 
+	public static final String SINGLE_FIELD_LABEL = GrpcSubFormTestFactory.FIELD_LABEL;
 	public static final String SINGLE_FIELD_NAME = GrpcSubFormTestFactory.FIELD_NAME;
 	public static final String SINGLE_FIELD_VALUE = GrpcSubFormTestFactory.FIELD_VALUE;
+	public static final Map<String, Object> SINGLE_FIELD = GrpcSubFormTestFactory.FIELD;
 
+	public static final String SUBFORM_LABEL = GrpcSubFormTestFactory.SUBFORM_LABEL;
+	public static final String SUBFORM_NAME = GrpcSubFormTestFactory.SUBFORM_TITLE;
+
+	public static final String SUBFORM_FIELD_LABEL = GrpcSubFormTestFactory.SUBFORM_FIELD_LABEL;
 	public static final String SUBFORM_FIELD_NAME = GrpcSubFormTestFactory.SUBFORM_FIELD_NAME;
 	public static final String SUBFORM_FIELD_VALUE = GrpcSubFormTestFactory.SUBFORM_FIELD_VALUE;
-	public static final String SUBFORM_NAME = GrpcSubFormTestFactory.SUBFORM_NAME;
-	public static final Map<String, Object> SUBFORM = Map.of(SUBFORM_FIELD_NAME, SUBFORM_FIELD_VALUE);
+	public static final Map<String, Object> SUBFORM_FIELD = GrpcSubFormTestFactory.SUBFORM_FIELD;
 
-	public static final Map<String, Object> FORM_DATA = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, SUBFORM_NAME, SUBFORM);
+	public static final Map<String, Object> SUBFORM = GrpcSubFormTestFactory.SUBFORM;
+	public static final Map<String, Object> SUBFORM_FLAT = Map.of(SUBFORM_FIELD_NAME, SUBFORM_FIELD);
+	public static final Map<String, Object> FORM_DATA = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD, SUBFORM_NAME, SUBFORM);
 
 	public static Eingang create() {
 		return createBuilder().build();
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FilterByMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FilterByMapperTest.java
similarity index 95%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FilterByMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FilterByMapperTest.java
index 0923b6afe492960e942e18d9335215daa94691c1..e871d3dc9f7227b990984fc7847a0d7c354f7b27 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FilterByMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FilterByMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.mockito.Mockito.*;
 
@@ -38,9 +38,9 @@ import org.mockito.Mock;
 
 import static org.assertj.core.api.Assertions.*;
 
-import de.itvsh.ozg.pluto.common.callcontext.CallContextUserTestFactory;
-import de.itvsh.ozg.pluto.common.callcontext.CurrentUserService;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
 
 class FilterByMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FilterCriteriaTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FilterCriteriaTestFactory.java
similarity index 77%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FilterCriteriaTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FilterCriteriaTestFactory.java
index bb5c6810301a3a4b8c3a293d252650bcda01dcaa..869c3032580cbce1f03785770f3ec7049d87a847 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FilterCriteriaTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FilterCriteriaTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,16 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
 
 public class FilterCriteriaTestFactory {
 
 	public static final String ORGANISATIONSEINHEIT_ID = ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID;
 	public static final boolean FILTER_BY_ORGANISATIONSEINHEITEN_ID = true;
 	public static final Status STATUS = Status.NEU;
+	public static final boolean FILTER_BY_ASSIGNED_TO = true;
+	public static final boolean HAS_NEXT_WIEDERVORLAGE_FRIST = false;
 
 	public static FilterCriteria createEmpty() {
 		return FilterCriteria.builder().build();
@@ -45,6 +47,8 @@ public class FilterCriteriaTestFactory {
 				.filterByOrganisationseinheitenId(FILTER_BY_ORGANISATIONSEINHEITEN_ID)
 				.organisationseinheitId(ORGANISATIONSEINHEIT_ID)
 				.singleStatus(STATUS)
-				.assignedTo(UserTestFactory.ID);
+				.filterByAssignedTo(FILTER_BY_ASSIGNED_TO)
+				.assignedTo(UserTestFactory.ID)
+				.hasNextWiedervorlageFrist(HAS_NEXT_WIEDERVORLAGE_FRIST);
 	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba55b0ab6ed4680ee30ccfefa7a75ec5e61474af
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryMapperTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.common.operator.OperandFunctionParser;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+import de.ozgcloud.vorgang.common.operator.OperatorTestFactory;
+
+class FindVorgangQueryMapperTest {
+
+	@InjectMocks
+	private FindVorgangQueryMapper mapper = spy(Mappers.getMapper(FindVorgangQueryMapper.class));
+
+	@Mock
+	private OperandFunctionParser operandFunctionParser;
+
+	@Nested
+	class TestFromFindVorgangQuery {
+
+		@Test
+		void shouldSetLogicalOperator() {
+			var result = mapper.fromQuery(GrpcQueryTestFactory.create());
+
+			assertThat(result.getLogicalOperator()).isEqualTo(FindVorgangQueryTestFactory.LOGICAL_OPERATOR);
+		}
+
+		@Test
+		void shouldCallBuildOperator() {
+			var grpcFindVorgangQuery = GrpcQueryTestFactory.create();
+			var expectedExpression = grpcFindVorgangQuery.getExpressions(0);
+
+			mapper.fromQuery(grpcFindVorgangQuery);
+
+			verify(mapper).buildOperator(expectedExpression);
+		}
+
+		@Test
+		void shouldSetOperator() {
+			var expectedOperator = OperatorTestFactory.createEqualOperator();
+			doReturn(expectedOperator).when(mapper).buildOperator(any());
+
+			var result = mapper.fromQuery(GrpcQueryTestFactory.create());
+
+			assertThat(result.getOperators()).containsExactly(expectedOperator);
+		}
+
+		@Test
+		void shouldSkipMappingNestedQuery() {
+			doReturn(false).when(mapper).hasSubQuery(any());
+
+			mapper.fromQuery(GrpcQueryTestFactory.create());
+
+			verify(mapper).fromQuery(any());
+		}
+
+		@Test
+		void shouldSetNestedQuery() {
+			var expectedNestedQuery = FindVorgangQueryTestFactory.createBuilder()
+					.logicalOperator(FindVorgangQuery.LogicalOperator.OR)
+					.clearOperators()
+					.operator(OperatorTestFactory.createLessThenOperator())
+					.build();
+			var nestedQuery = GrpcQueryTestFactory.createBuilder().setLogicalOperator(GrpcLogicalOperator.OR)
+					.clearExpressions()
+					.addExpressions(GrpcVorgangQueryExpressionTestFactory.createBuilder()
+							.setOperator(GrpcQueryOperator.LESS_THEN)
+							.setOperandIntValue(OperatorTestFactory.INT_VALUE))
+					.build();
+
+			var result = mapper.fromQuery(GrpcQueryTestFactory.createBuilder().setNestedQuery(nestedQuery).build());
+
+			assertThat(result.getNestedQuery()).usingRecursiveComparison().isEqualTo(expectedNestedQuery);
+		}
+
+	}
+
+	@Nested
+	class TestHasSubForm {
+
+		@Test
+		void shouldApproveSubQuery() {
+			var result = mapper.hasSubQuery(GrpcQueryTestFactory.createBuilder().setNestedQuery(GrpcQueryTestFactory.create()).build());
+
+			assertThat(result).isTrue();
+		}
+
+		@Test
+		void shouldRejectIfNoSubQuery() {
+			var result = mapper.hasSubQuery(GrpcQueryTestFactory.create());
+
+			assertThat(result).isFalse();
+		}
+	}
+
+	@Nested
+	class TestFromLogicalOperator {
+
+		@Test
+		void shouldMapAnd() {
+			var result = mapper.fromLogicalOperator(GrpcLogicalOperator.AND);
+
+			assertThat(result).isEqualTo(FindVorgangQuery.LogicalOperator.AND);
+		}
+
+		@Test
+		void shouldMapOr() {
+			var result = mapper.fromLogicalOperator(GrpcLogicalOperator.OR);
+
+			assertThat(result).isEqualTo(FindVorgangQuery.LogicalOperator.OR);
+		}
+	}
+
+	@Nested
+	class TestBuildOperator {
+
+		@Mock
+		private OperatorBuilder operatorBuilder;
+
+		@Test
+		void shouldSetFieldPath() {
+			var operator = mapper.buildOperator(GrpcVorgangQueryExpressionTestFactory.create());
+
+			assertThat(operator).extracting("fieldPath").isEqualTo(OperatorTestFactory.PATH);
+		}
+
+		@Test
+		void shouldCallGetValue() {
+			var queryExpression = GrpcVorgangQueryExpressionTestFactory.create();
+
+			mapper.buildOperator(queryExpression);
+
+			verify(mapper).getValue(queryExpression);
+		}
+
+		@Test
+		void shouldSetOperand() {
+			doReturn(OperatorTestFactory.STRING_VALUE).when(mapper).getValue(any());
+
+			var operator = mapper.buildOperator(GrpcVorgangQueryExpressionTestFactory.create());
+
+			assertThat(operator).extracting("operand").isEqualTo(OperatorTestFactory.STRING_VALUE);
+		}
+
+		@Test
+		void shouldCallOperatorBuilder() {
+			try(var mockOperatorBuilder = Mockito.mockStatic(OperatorBuilder.class)) {
+				mockOperatorBuilder.when(() -> OperatorBuilder.from(any())).thenReturn(operatorBuilder);
+				mockOperatorBuilder.when(() -> operatorBuilder.fieldPath(any())).thenReturn(operatorBuilder);
+				mockOperatorBuilder.when(() -> operatorBuilder.operand(any())).thenReturn(operatorBuilder);
+
+				mapper.buildOperator(GrpcVorgangQueryExpressionTestFactory.create());
+
+				mockOperatorBuilder.verify(() -> OperatorBuilder.from(GrpcVorgangQueryExpressionTestFactory.OPERATOR));
+			}
+		}
+
+	}
+
+	@Nested
+	class TestGetValue {
+
+		@Test
+		void shouldReturnNullWhenNotSet() {
+			var statisticQuery = GrpcVorgangQueryExpressionTestFactory.createBuilder().clearOperandStringValue().build();
+
+			var value = mapper.getValue(statisticQuery);
+
+			assertThat(value).isNull();
+		}
+
+		@Test
+		void shouldCallGetStringValue() {
+			var statisticQuery = GrpcVorgangQueryExpressionTestFactory.create();
+
+			mapper.getValue(statisticQuery);
+
+			verify(mapper).getStringValue(statisticQuery);
+		}
+
+		@Test
+		void shouldReturnInteger() {
+			var statisticQuery = GrpcVorgangQueryExpressionTestFactory.createBuilder().setOperandIntValue(1).build();
+
+			var value = mapper.getValue(statisticQuery);
+
+			assertThat(value).isEqualTo(1);
+		}
+
+		@Test
+		void shouldReturnBoolean() {
+			var statisticQuery = GrpcVorgangQueryExpressionTestFactory.createBuilder().setOperandBoolValue(true).build();
+
+			var value = mapper.getValue(statisticQuery);
+
+			assertThat(value).isEqualTo(true);
+		}
+
+		@Nested
+		class TestGetStringValue {
+
+			@Test
+			void shouldCallOperandFunctionParser() {
+				var functionValue = "function()";
+				var statisticQuery = GrpcVorgangQueryExpressionTestFactory.createBuilder().setOperandStringValue(functionValue).build();
+
+				mapper.getStringValue(statisticQuery);
+
+				verify(operandFunctionParser).parse(functionValue);
+			}
+
+			@Test
+			void shouldReturnNull() {
+				var statisticQuery = GrpcVorgangQueryExpressionTestFactory.createBuilder().setOperandStringValue("null").build();
+
+				var value = mapper.getStringValue(statisticQuery);
+
+				assertThat(value).isNull();
+			}
+
+			@Test
+			void shouldReturnStringValue() {
+				var statisticQuery = GrpcVorgangQueryExpressionTestFactory.create();
+
+				var value = mapper.getStringValue(statisticQuery);
+
+				assertThat(value).isEqualTo(OperatorTestFactory.STRING_VALUE);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed24d87053b5b5d275222ad59310e301f51f7ed4
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangQueryTestFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import de.ozgcloud.vorgang.common.operator.OperatorTestFactory;
+import de.ozgcloud.vorgang.vorgang.FindVorgangQuery.LogicalOperator;
+
+public class FindVorgangQueryTestFactory {
+
+	public static final LogicalOperator LOGICAL_OPERATOR = LogicalOperator.AND;
+
+	public static FindVorgangQuery create() {
+		return createBuilder().build();
+	}
+
+	public static FindVorgangQuery.FindVorgangQueryBuilder createBuilder() {
+		return FindVorgangQuery.builder()
+				.logicalOperator(LOGICAL_OPERATOR)
+				.operator(OperatorTestFactory.createEqualOperator());
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestMapperTest.java
similarity index 83%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestMapperTest.java
index cbeffe58c4b38b4d3779e21b6fcb92de40c4703e..c20f7fd2eadb82b654775397b734ce2c587a58ba 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -42,6 +42,8 @@ class FindVorgangRequestMapperTest {
 	private final FindVorgangRequestMapper mapper = Mappers.getMapper(FindVorgangRequestMapper.class);
 	@Mock
 	private FilterByMapper filterByMapper;
+	@Mock
+	private FindVorgangQueryMapper findVorgangQueryMapper;
 
 	@DisplayName("Map from find vorgang request")
 	@Nested
@@ -72,5 +74,15 @@ class FindVorgangRequestMapperTest {
 
 			verify(filterByMapper).fromFilterBy(GrpcFilterByTestFactory.create());
 		}
+
+		@Test
+		void shouldMapQuery() {
+			var expectedQuery = GrpcQueryTestFactory.create();
+			var findVorgangRequest = GrpcFindVorgangRequestTestFactory.createBuilder().setQuery(expectedQuery).build();
+
+			mapper.fromFindVorgangRequest(findVorgangRequest);
+
+			verify(findVorgangQueryMapper).fromQuery(expectedQuery);
+		}
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestTestFactory.java
similarity index 90%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestTestFactory.java
index 5ec1ae9420a9a59803b27a013531ef57ec6e9cd0..ba6a6dad1677f1a9f72e9522111f235b29c320c7 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/FindVorgangRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/FindVorgangRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import com.thedeanda.lorem.LoremIpsum;
 
-import de.itvsh.ozg.pluto.vorgang.FindVorgangRequest.OrderCriteria;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest.OrderCriteria;
 
 public class FindVorgangRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcAntragstellerTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcAntragstellerTestFactory.java
similarity index 96%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcAntragstellerTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcAntragstellerTestFactory.java
index 3da6713956dbbaca629cf3f173853ba28da2a8dd..e8432194ba616096acf444cf76102ccca61e51f7 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcAntragstellerTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcAntragstellerTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 public class GrpcAntragstellerTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcCreateVorgangRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcCreateVorgangRequestTestFactory.java
similarity index 81%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcCreateVorgangRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcCreateVorgangRequestTestFactory.java
index e090c0fb120c11b86da13647e8b8ed75fab89dd4..e4afb5eb723e0f019479c9c29f0370cbb7ad6585 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcCreateVorgangRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcCreateVorgangRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 public class GrpcCreateVorgangRequestTestFactory {
 
@@ -31,6 +31,10 @@ public class GrpcCreateVorgangRequestTestFactory {
 		return createBuilder().build();
 	}
 
+	public static GrpcCreateVorgangRequest createWithFormData(GrpcFormData formData) {
+		return createBuilder().setEingang(GrpcEingangTestFactory.createBuilder().setFormData(formData)).build();
+	}
+
 	public static GrpcCreateVorgangRequest.Builder createBuilder() {
 		return GrpcCreateVorgangRequest.newBuilder()
 				.setEingang(GRPC_EINGANG);
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcEingangHeaderTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangHeaderTestFactory.java
similarity index 81%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcEingangHeaderTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangHeaderTestFactory.java
index 8d9a0c77ebcdef90b43d68d9d0246d4bcb3398d3..795f65f7026e86628a40dc27cfb52af71954af16 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcEingangHeaderTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangHeaderTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.time.ZonedDateTime;
 
+import de.ozgcloud.vorgang.servicekonto.GrpcServiceKontoTestFactory;
+
 public class GrpcEingangHeaderTestFactory {
 
 	private final static String REQUEST_ID = EingangHeaderTestFactory.REQUEST_ID;
 	private final static String CREATED_AT_STR = EingangHeaderTestFactory.CREATED_AT_STR;
-	public static ZonedDateTime CREATED_AT = EingangHeaderTestFactory.CREATED_AT;
+	public static final ZonedDateTime CREATED_AT = EingangHeaderTestFactory.CREATED_AT;
 
 	private final static String FORM_ID = EingangHeaderTestFactory.FORM_ID;
 	public final static String FORM_NAME = EingangHeaderTestFactory.FORM_NAME;
@@ -46,6 +48,8 @@ public class GrpcEingangHeaderTestFactory {
 				.setFormId(FORM_ID)
 				.setFormName(FORM_NAME)
 				.setFormEngineName(VorgangTestFactory.FORM_ENGINE_NAME)
-				.setSender(SENDER);
+				.setVorgangNummer(EingangHeaderTestFactory.VORGANG_NUMMER)
+				.setSender(SENDER)
+				.setServiceKonto(GrpcServiceKontoTestFactory.create());
 	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcEingangTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangTestFactory.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcEingangTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangTestFactory.java
index 4c375df331616bd46c2138410cba2466630fe1ac..2c90bbfae9989b2bfabe3587cb1e2d91d2a12463 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcEingangTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcEingangTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.UUID;
 
-import de.itvsh.kop.pluto.common.grpc.GrpcSubFormTestFactory;
+import de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory;
 
 public class GrpcEingangTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFilterByTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFilterByTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFilterByTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFilterByTestFactory.java
index 015277b768b204d28a0d99263611734e2f632796..56039680769e02e6055735070b49876dc53d81c2 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFilterByTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFilterByTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import static de.itvsh.ozg.pluto.vorgang.FilterCriteriaTestFactory.*;
+import static de.ozgcloud.vorgang.vorgang.FilterCriteriaTestFactory.*;
 
-import de.itvsh.ozg.pluto.command.UserTestFactory;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
 
 public class GrpcFilterByTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFindVorgangRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFindVorgangRequestTestFactory.java
similarity index 90%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFindVorgangRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFindVorgangRequestTestFactory.java
index 7cb96878e6d5efcbad8c0544b02332a1ad849d82..e337f9730a4fc13d73f9044d9455078cc4b185f0 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFindVorgangRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFindVorgangRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import static de.itvsh.ozg.pluto.vorgang.FindVorgangRequestTestFactory.*;
+import static de.ozgcloud.vorgang.vorgang.FindVorgangRequestTestFactory.*;
 
 public class GrpcFindVorgangRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFinishCreationRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFinishCreationRequestTestFactory.java
similarity index 85%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFinishCreationRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFinishCreationRequestTestFactory.java
index bff54f4989ceebf043621b4bd41cb7c2e31ab504..d7603e1d526acf45ad15797d3aab2df54191b811 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcFinishCreationRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcFinishCreationRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.util.List;
 
@@ -33,10 +33,13 @@ public class GrpcFinishCreationRequestTestFactory {
 	private static List<GrpcIncomingFile> representations = List.of(representation);
 
 	public static GrpcFinishCreationRequest create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcFinishCreationRequest.Builder createBuilder() {
 		return GrpcFinishCreationRequest.newBuilder()
 				.setVorgangId(VorgangTestFactory.ID)
 				.addAllAttachments(attachments)
-				.addAllRepresentations(representations)
-				.build();
+				.addAllRepresentations(representations);
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcIncomingFileGroupTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcIncomingFileGroupTestFactory.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcIncomingFileGroupTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcIncomingFileGroupTestFactory.java
index ce0f94a55cd12bd43816ab447ba3564a6b04902b..a8708aa0cae2e2e60bcdf09fa9c3f5969c7f5ab9 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcIncomingFileGroupTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcIncomingFileGroupTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 public class GrpcIncomingFileGroupTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcIncomingFileTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcIncomingFileTestFactory.java
similarity index 94%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcIncomingFileTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcIncomingFileTestFactory.java
index b4916ce9f292fa2facda5aba1a702f11ba7c747e..5ebe3c0592de4719bbd165f3bd6ea17c71b97913 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcIncomingFileTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcIncomingFileTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import com.google.protobuf.ByteString;
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcQueryTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcQueryTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a17c49a25f7b615fac077e25cc8c4f7305ee136
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcQueryTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+public class GrpcQueryTestFactory {
+
+	public static final GrpcLogicalOperator LOGICAL_OPERATOR = GrpcLogicalOperator.AND;
+
+	public static GrpcQuery create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcQuery.Builder createBuilder() {
+		return GrpcQuery.newBuilder()
+				.setLogicalOperator(LOGICAL_OPERATOR)
+				.addExpressions(GrpcVorgangQueryExpressionTestFactory.create());
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangHeadTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangHeadTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0469d8948ce3689a63a81968e4014ad1abe1ef20
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangHeadTestFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import de.ozgcloud.vorgang.servicekonto.GrpcServiceKontoTestFactory;
+
+public class GrpcVorgangHeadTestFactory {
+
+	public static GrpcVorgangHead create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcVorgangHead.Builder createBuilder() {
+		return GrpcVorgangHead.newBuilder()
+				.setServiceKonto(GrpcServiceKontoTestFactory.create());
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangQueryExpressionTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangQueryExpressionTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..7da9b7c5516dc79e1487a9572f729383885fafc0
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangQueryExpressionTestFactory.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static de.ozgcloud.vorgang.common.operator.OperatorTestFactory.*;
+
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+
+public class GrpcVorgangQueryExpressionTestFactory {
+
+	public static final String PATH = "Vorgang.field";
+	public static final GrpcQueryOperator OPERATOR = GrpcQueryOperator.EQUAL;
+
+	public static GrpcVorgangQueryExpression create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcVorgangQueryExpression.Builder createBuilder() {
+		return GrpcVorgangQueryExpression.newBuilder()
+				.setPath(PATH)
+				.setOperator(OPERATOR)
+				.setOperandStringValue(STRING_VALUE);
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceFindQueryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceFindQueryITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ddc093f2727aaed4422855233cff852b8475da8
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceFindQueryITCase.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.time.LocalDate;
+import java.time.ZonedDateTime;
+import java.util.Optional;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.test.annotation.DirtiesContext;
+
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMapTestFactory;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.common.db.CriteriaUtil;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@SpringBootTest(properties = {
+		"grpc.server.inProcessName=test",
+		"grpc.server.port=-1",
+		"grpc.client.inProcess.address=in-process:test"
+})
+@DirtiesContext
+@DataITCase
+class GrpcVorgangServiceFindQueryITCase {
+
+	private static final String VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH = "ClientAttribute.OzgCloud_NachrichtenManager.hasNewPostfachNachricht";
+
+	@Autowired
+	private VorgangHeaderRepository repository;
+	@Autowired
+	private MongoOperations mongoOperations;
+
+	@MockBean
+	private CurrentUserService currentUserService;
+
+	@GrpcClient("inProcess")
+	private VorgangServiceGrpc.VorgangServiceBlockingStub vorgangServiceStub;
+
+	private Vorgang vorgangWithNextFristMinus2Days;
+	private Vorgang vorgangNewCreatedAt;
+
+	@BeforeEach
+	void init() {
+		when(currentUserService.findUser()).thenReturn(Optional.of(CallContextUserTestFactory.create()));
+		when(currentUserService.getUser()).thenReturn(CallContextUserTestFactory.create());
+
+		mongoOperations.dropCollection(Vorgang.class);
+		mongoOperations.save(VorgangTestFactory.createBuilder().id(null)
+				.createdAt(ZonedDateTime.now())
+				.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now())).build());
+		vorgangWithNextFristMinus2Days = mongoOperations.save(VorgangTestFactory.createBuilder().id(null)
+				.status(Vorgang.Status.BESCHIEDEN)
+				.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minusDays(2))).build());
+		vorgangNewCreatedAt = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).build());
+	}
+
+	@Test
+	void shouldFindWhereExists() {
+		var request = GrpcFindVorgangRequestTestFactory.createBuilder().clearFilterBy().setQuery(
+				GrpcQuery.newBuilder()
+						.addExpressions(GrpcVorgangQueryExpression.newBuilder()
+								.setOperator(GrpcQueryOperator.EXISTS)
+								.setPath("ClientAttribute.%s.nextWiedervorlageFrist".formatted(CriteriaUtil.DEFAULT_CLIENT)))).build();
+
+		var result = vorgangServiceStub.findVorgang(request);
+
+		assertThat(result.getVorgangList()).hasSize(2);
+	}
+
+	@Test
+	void shouldFindWithCertainNextFrist() {
+		var request = GrpcFindVorgangRequestTestFactory.createBuilder()
+				.clearFilterBy()
+				.setOrderBy(GrpcFindVorgangRequest.GrpcOrderBy.CREATED_AT_DESC)
+				.setQuery(GrpcQuery.newBuilder().addExpressions(
+						GrpcVorgangQueryExpression.newBuilder()
+								.setOperator(GrpcQueryOperator.LESS_THEN)
+								.setPath("ClientAttribute.%s.nextWiedervorlageFrist".formatted(CriteriaUtil.DEFAULT_CLIENT))
+								.setOperandStringValue(LocalDate.now().minusDays(1).toString())))
+				.build();
+
+		var result = vorgangServiceStub.findVorgang(request);
+
+		assertThat(result.getVorgangList()).hasSize(1).first().extracting(GrpcVorgangHeader::getId).isEqualTo(vorgangWithNextFristMinus2Days.getId());
+	}
+
+	@Test
+	void shouldFindByComplexCondition() {
+		var request = GrpcFindVorgangRequestTestFactory.createBuilder().clearFilterBy()
+				.setOrderBy(GrpcFindVorgangRequest.GrpcOrderBy.CREATED_AT_DESC)
+				.setQuery(GrpcQuery.newBuilder()
+						.addExpressions(GrpcVorgangQueryExpression.newBuilder()
+								.setOperator(GrpcQueryOperator.EQUAL)
+								.setPath("Vorgang." + Vorgang.MONGODB_FIELDNAME_STATUS)
+								.setOperandStringValue("NEU"))
+						.addExpressions(GrpcVorgangQueryExpression.newBuilder()
+								.setOperator(GrpcQueryOperator.LESS_THEN_OR_EQUAL_TO)
+								.setPath("Vorgang." + Vorgang.MONGODB_FIELDNAME_CREATED_AT)
+								.setOperandStringValue(VorgangTestFactory.CREATED_AT.toString()))
+				)
+				.build();
+
+		var result = vorgangServiceStub.findVorgang(request);
+
+		assertThat(result.getVorgangList()).hasSize(1).first().extracting(GrpcVorgangHeader::getId).isEqualTo(vorgangNewCreatedAt.getId());
+	}
+
+	@Test
+	void shouldFindVorgangWithNewPostfachNachricht() {
+		var vorgang = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).clientAttributes(createClientAttributesMap()).build());
+
+		var request = GrpcFindVorgangRequestTestFactory.createBuilder().clearFilterBy()
+				.setOrderBy(GrpcFindVorgangRequest.GrpcOrderBy.CREATED_AT_DESC)
+				.setQuery(GrpcQuery.newBuilder().addExpressions(
+						GrpcVorgangQueryExpression.newBuilder()
+								.setPath(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH)
+								.setOperator(GrpcQueryOperator.UNEQUAL)))
+				.build();
+
+		var result = vorgangServiceStub.findVorgang(request);
+
+		assertThat(result.getVorgangList()).hasSize(1).first().extracting(GrpcVorgangHeader::getId).isEqualTo(vorgang.getId());
+	}
+
+	private ClientAttributesMap createClientAttributesMapWithWiedervorlageNextFrist(LocalDate nextFrist) {
+		return ClientAttributesMapTestFactory.createWithAttribute(buildWiedervorlageNextFristClientAttribute(nextFrist));
+	}
+
+	private ClientAttribute buildWiedervorlageNextFristClientAttribute(LocalDate nextFrist) {
+		return ClientAttributeTestFactory.createBuilder()
+				.clientName(CriteriaUtil.DEFAULT_CLIENT)
+				.attributeName(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST)
+				.stringValue(Optional.of(nextFrist.toString())).build();
+	}
+
+	private ClientAttributesMap createClientAttributesMap() {
+		return ClientAttributesMapTestFactory.createWithAttribute(buildClientAttribute());
+	}
+
+	private ClientAttribute buildClientAttribute() {
+		return ClientAttributeTestFactory.createBuilder()
+				.clientName("OzgCloud_NachrichtenManager")
+				.attributeName("hasNewPostfachNachricht")
+				.intValue(Optional.empty())
+				.boolValue(Optional.of(true))
+				.build();
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..fca3f0bfb13a7072c4a6bf359aae20fd1bc19a46
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceITCase.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.annotation.DirtiesContext;
+
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.callcontext.CallContextUserTestFactory;
+import de.ozgcloud.vorgang.callcontext.CurrentUserService;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMapTestFactory;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.common.db.CriteriaUtil;
+import de.ozgcloud.vorgang.common.grpc.GrpcFormDataTestFactory;
+import de.ozgcloud.vorgang.common.grpc.GrpcFormFieldTestFactory;
+import de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub;
+import io.grpc.stub.StreamObserver;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+
+@ITCase
+class GrpcVorgangServiceITCase {
+
+	static final String VALUE_KEY = "value";
+	static final String LABEL_KEY = "label";
+
+	private static final String NAME_FIELD_1 = "field1";
+	private static final String VALUE_FIELD_1 = "value1";
+	private static final String LABEL_FIELD_1 = "label1";
+	private static final Map<String, Object> FIELD_1 = Map.of(LABEL_KEY, LABEL_FIELD_1, VALUE_KEY, VALUE_FIELD_1);
+
+	private static final String NAME_FIELD_2 = "field2";
+	private static final String VALUE_FIELD_2 = "value2";
+	private static final String LABEL_FIELD_2 = "label2";
+	private static final Map<String, Object> FIELD_2 = Map.of(LABEL_KEY, LABEL_FIELD_2, VALUE_KEY, VALUE_FIELD_2);
+
+	private static final String NAME_FIELD_3 = "field3";
+	private static final String VALUE_FIELD_3 = "value3";
+	private static final String LABEL_FIELD_3 = "label3";
+	private static final Map<String, Object> FIELD_3 = Map.of(LABEL_KEY, LABEL_FIELD_3, VALUE_KEY, VALUE_FIELD_3);
+
+	private static final List<GrpcFormField> formFields = List.of(
+			createFormField(NAME_FIELD_1, VALUE_FIELD_1, LABEL_FIELD_1),
+			createFormField(NAME_FIELD_2, VALUE_FIELD_2, LABEL_FIELD_2),
+			createFormField(NAME_FIELD_3, VALUE_FIELD_3, LABEL_FIELD_3));
+
+	private static final String TITLE_SUBFORM_1 = "SUBFORM_1";
+	private static final String TITLE_SUBFORM_2 = "SUBFORM_2";
+	private static final String TITLE_SUBFORM_3 = "SUBFORM_3";
+
+	@Autowired
+	private GrpcVorgangService grpcVorgangService;
+	@MockBean
+	private VorgangService service;
+
+	@Nested
+	class TestCreateVorgang {
+		@Mock
+		private StreamObserver<GrpcCreateVorgangResponse> responseObserver;
+		@Captor
+		private ArgumentCaptor<Eingang> eingangCaptor;
+
+		@BeforeEach
+		void init() {
+			when(service.startCreation(any())).thenReturn(VorgangTestFactory.create());
+		}
+
+		@Test
+		void shouldKeepFieldsOrder() {
+			var grpcFormData = GrpcFormData.newBuilder().addAllField(formFields).build();
+
+			Map<String, Object> formData = startCreation(grpcFormData);
+
+			assertThat(removeControlData(formData)).containsExactly(
+					entry(NAME_FIELD_1, FIELD_1),
+					entry(NAME_FIELD_2, FIELD_2),
+					entry(NAME_FIELD_3, FIELD_3));
+		}
+
+		@Test
+		void shouldKeepSubFormOrder() {
+			var grpcFormData = GrpcFormData.newBuilder().addForm(GrpcSubFormTestFactory.createBuilder().setTitle(TITLE_SUBFORM_1))
+					.addForm(GrpcSubFormTestFactory.createBuilder().setTitle(TITLE_SUBFORM_2))
+					.addForm(GrpcSubFormTestFactory.createBuilder().setTitle(TITLE_SUBFORM_3)).build();
+
+			Map<String, Object> formData = startCreation(grpcFormData);
+
+			verifySubFormOrder(formData, TITLE_SUBFORM_1, TITLE_SUBFORM_2, TITLE_SUBFORM_3);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Test
+		void shouldKeepFieldsOrderInSubForm() {
+			var grpcFormData = GrpcFormDataTestFactory.createBuilder().addForm(
+							GrpcSubFormTestFactory.createBuilder().clearField().clearSubForm().setTitle(TITLE_SUBFORM_1).addAllField(formFields))
+					.build();
+
+			var formData = (Map<String, Object>) startCreation(grpcFormData).get(TITLE_SUBFORM_1);
+			formData = (Map<String, Object>) formData.get(VALUE_KEY);
+
+			assertThat(removeControlData(formData)).containsExactly(
+					entry(NAME_FIELD_1, FIELD_1),
+					entry(NAME_FIELD_2, FIELD_2),
+					entry(NAME_FIELD_3, FIELD_3));
+		}
+
+		private LinkedHashMap<String, Object> removeControlData(Map<String, Object> formData) {
+			var editable = new LinkedHashMap<>(formData);
+			editable.remove("_kopControlData");
+			return editable;
+		}
+
+		@SuppressWarnings("unchecked")
+		@Test
+		void shouldKeepOrderInSubForm() {
+			var grpcFormData = GrpcFormDataTestFactory.createBuilder().addForm(
+					GrpcSubFormTestFactory.createBuilder().setTitle(TITLE_SUBFORM_1).clearField().clearSubForm()
+							.addSubForm(GrpcSubFormTestFactory.createBuilder().setTitle(TITLE_SUBFORM_3))
+							.addSubForm(GrpcSubFormTestFactory.createBuilder().setTitle(TITLE_SUBFORM_2)))
+					.build();
+
+			var formData = (Map<String, Object>) startCreation(grpcFormData).get(TITLE_SUBFORM_1);
+			formData = (Map<String, Object>) formData.get(VALUE_KEY);
+
+			verifySubFormOrder(formData, TITLE_SUBFORM_3, TITLE_SUBFORM_2);
+		}
+
+		private static void verifySubFormOrder(Map<String, Object> formData, String... subFormTitle) {
+			var entries = new ArrayList<>(formData.entrySet());
+			for (int i = 0; i < subFormTitle.length; i++) {
+				var entry = entries.get(i);
+				assertThat(entry.getKey()).isEqualTo(subFormTitle[i]);
+			}
+		}
+
+		private Map<String, Object> startCreation(GrpcFormData grpcFormData) {
+			grpcVorgangService.startCreation(GrpcCreateVorgangRequestTestFactory.createWithFormData(grpcFormData), responseObserver);
+
+			verify(service).startCreation(eingangCaptor.capture());
+			return eingangCaptor.getValue().getFormData();
+
+		}
+	}
+
+	private static GrpcFormField createFormField(String fieldName, String fieldValue, String label) {
+		return GrpcFormFieldTestFactory.createBuilder().setName(fieldName).setValue(fieldValue).setLabel(label).build();
+	}
+
+	@Nested
+	class TestLoadVorgang {
+
+		private static final String REQUEST_ID = "request_id";
+
+		@Mock
+		private StreamObserver<GrpcFindVorgangWithEingangResponse> streamObserver;
+		@Captor
+		private ArgumentCaptor<GrpcFindVorgangWithEingangResponse> findVorgangResponseCaptor;
+
+		@BeforeEach
+		void initVorgang() {
+			var formData = createFormData();
+
+			var eingang = EingangTestFactory.createBuilder().formData(formData).build();
+			var vorgang = VorgangTestFactory.createBuilder().clearEingangs().eingangs(List.of(eingang)).build();
+
+			when(service.getById(any(), any())).thenReturn(vorgang);
+		}
+
+		@Test
+		@WithMockUser
+		void shouldKeepFieldOrder() {
+			var grpcFormData = requestFormData();
+
+			assertThat(grpcFormData).isEqualTo(expectedFormData());
+		}
+
+		private static Map<String, Object> createFormData() {
+			Map<String, Object> formData = new LinkedHashMap<>();
+			formData.put(NAME_FIELD_1, FIELD_1);
+			formData.put(NAME_FIELD_2, FIELD_2);
+			formData.put(NAME_FIELD_3, FIELD_3);
+			for (String subFormName : List.of(TITLE_SUBFORM_1, TITLE_SUBFORM_2, TITLE_SUBFORM_3)) {
+				var subForm = new LinkedHashMap<>();
+				formData.put(subFormName, subForm);
+				subForm.put(NAME_FIELD_1, FIELD_1);
+				subForm.put(NAME_FIELD_2, FIELD_2);
+				subForm.put(NAME_FIELD_3, FIELD_3);
+			}
+			return formData;
+		}
+
+		private static GrpcFormData expectedFormData() {
+			var grpcFormData = GrpcFormDataTestFactory.createBuilder().clearField().addAllField(formFields);
+			for (String subFormName : List.of(TITLE_SUBFORM_1, TITLE_SUBFORM_2, TITLE_SUBFORM_3)) {
+				grpcFormData.addForm(GrpcSubForm.newBuilder()
+						.setTitle(subFormName)
+						.addAllField(formFields));
+			}
+			return grpcFormData.build();
+		}
+
+		private GrpcFormData requestFormData() {
+			grpcVorgangService.findVorgangWithEingang(GrpcFindVorgangWithEingangRequest.newBuilder().setId(REQUEST_ID).build(), streamObserver);
+			verify(streamObserver).onNext(findVorgangResponseCaptor.capture());
+			return findVorgangResponseCaptor.getValue().getVorgangWithEingang().getEingang().getFormData();
+		}
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceTest.java
similarity index 79%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceTest.java
index 7f85cbc438594856af6ed5f9296dbc8f3229a25c..2d4a2f9fe85fb98e96e9f3fad58dd89781eaf0f5 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,8 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
+import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
@@ -40,8 +41,6 @@ import org.mockito.Mock;
 import org.mockito.Spy;
 import org.springframework.data.domain.Page;
 
-import static org.assertj.core.api.Assertions.*;
-
 import io.grpc.stub.StreamObserver;
 
 class GrpcVorgangServiceTest {
@@ -50,7 +49,7 @@ class GrpcVorgangServiceTest {
 	private static final int OFFSET = 0;
 	private static final long TOTAL = 42L;
 
-	@Spy // NOSONAR
+	@Spy
 	@InjectMocks
 	private GrpcVorgangService service;
 	@Mock
@@ -58,15 +57,18 @@ class GrpcVorgangServiceTest {
 	@Mock
 	private VorgangHeaderService headerService;
 	@Mock
-	private EingangMapper eingangMapper;
-	@Mock
 	private VorgangHeaderMapper vorgangHeaderMapper;
+
+	@Mock
+	private EingangMapper eingangMapper;
 	@Mock
 	private VorgangWithEingangMapper vorgangWithEingangMapper;
 	@Mock
 	private FindVorgangRequestMapper findVorgangRequestMapper;
+
 	@Mock
 	private FilterByMapper filterByMapper;
+
 	@Mock
 	private IncomingFileMapper incomingFileMapper;
 	@Mock
@@ -90,49 +92,6 @@ class GrpcVorgangServiceTest {
 			when(eingangMapper.fromGrpc(any())).thenReturn(eingang);
 		}
 
-		@Nested
-		class TestCreateVorgang {
-
-			@BeforeEach
-			void mockVorgangService() {
-				when(vorgangService.createVorgang(any())).thenReturn(VorgangTestFactory.create());
-			}
-
-			@Test
-			void shouldCallEingangMapper() throws Exception {
-				callCreateVorgang();
-
-				verify(eingangMapper).fromGrpc(GrpcEingangTestFactory.create());
-			}
-
-			@Test
-			void shouldCallService() throws Exception {
-				callCreateVorgang();
-
-				verify(vorgangService).createVorgang(eingang);
-			}
-
-			@Test
-			void shouldReturnMessage() throws Exception {
-				callCreateVorgang();
-
-				assertThat(responseCaptor.getValue().getMessage()).isEqualTo("ok");
-			}
-
-			@Test
-			void shouldReturnVorgangId() throws Exception {
-				callCreateVorgang();
-
-				assertThat(responseCaptor.getValue().getVorgangId()).isEqualTo(VorgangTestFactory.ID);
-			}
-
-			private void callCreateVorgang() throws Exception {
-				service.createVorgang(request, responseObserver);
-
-				verify(responseObserver).onNext(responseCaptor.capture());
-			}
-		}
-
 		@Nested
 		class TestStartCreation {
 
@@ -142,34 +101,27 @@ class GrpcVorgangServiceTest {
 			}
 
 			@Test
-			void shouldCallEingangMapper() throws Exception {
+			void shouldCallEingangMapper() {
 				callStartCreation();
 
 				verify(eingangMapper).fromGrpc(GrpcEingangTestFactory.create());
 			}
 
 			@Test
-			void shouldCallService() throws Exception {
-				callStartCreation();
-
-				verify(vorgangService).startCreation(eingang);
-			}
-
-			@Test
-			void shouldReturnMessage() throws Exception {
+			void shouldReturnMessage() {
 				callStartCreation();
 
 				assertThat(responseCaptor.getValue().getMessage()).isEqualTo("ok");
 			}
 
 			@Test
-			void shouldReturnVorgangId() throws Exception {
+			void shouldReturnVorgangId() {
 				callStartCreation();
 
 				assertThat(responseCaptor.getValue().getVorgangId()).isEqualTo(VorgangTestFactory.ID);
 			}
 
-			private void callStartCreation() throws Exception {
+			private void callStartCreation() {
 				service.startCreation(request, responseObserver);
 
 				verify(responseObserver).onNext(responseCaptor.capture());
@@ -253,36 +205,36 @@ class GrpcVorgangServiceTest {
 		@Captor
 		private ArgumentCaptor<FindVorgangRequest> findVorgangRequestCaptor;
 
-		private final GrpcVorgangHeader plutoVorgangHeader = GrpcVorgangHeader.newBuilder().build();
+		private final GrpcVorgangHeader grpcVorgangHeader = GrpcVorgangHeader.newBuilder().build();
 		private final GrpcFindVorgangRequest request = GrpcFindVorgangRequest.newBuilder().setLimit(LIMIT).setOffset(OFFSET)
 				.build();
 
 		@BeforeEach
-		void initMockReturnValues() throws Exception {
+		void initMockReturnValues() {
 			when(page.getContent()).thenReturn(Collections.singletonList(VorgangHeaderTestFactory.create()));
 			when(page.getTotalElements()).thenReturn(TOTAL);
 			when(headerService.findAll(any(FindVorgangRequest.class))).thenReturn(page);
-			when(vorgangHeaderMapper.toGrpcVorgangHeader(any())).thenReturn(plutoVorgangHeader);
+			when(vorgangHeaderMapper.toGrpcVorgangHeader(any())).thenReturn(grpcVorgangHeader);
 			when(findVorgangRequestMapper.fromFindVorgangRequest(any(GrpcFindVorgangRequest.class)))
 					.thenReturn(FindVorgangRequestTestFactory.create());
 		}
 
 		@Test
-		void shouldCallVorgangHeaderService() throws Exception {
+		void shouldCallVorgangHeaderService() {
 			callFindVorgaenge();
 
 			verify(headerService).findAll(findVorgangRequestCaptor.capture());
 		}
 
 		@Test
-		void shouldCallVorgangHeaderMapper() throws Exception {
+		void shouldCallVorgangHeaderMapper() {
 			callFindVorgaenge();
 
 			verify(vorgangHeaderMapper).toGrpcVorgangHeader(any());
 		}
 
 		@Test
-		void shouldContainVorgangData() throws Exception {
+		void shouldContainVorgangData() {
 			callFindVorgaenge();
 
 			verify(vorgangHeaderMapper).toGrpcVorgangHeader(headerCaptor.capture());
@@ -291,7 +243,7 @@ class GrpcVorgangServiceTest {
 		}
 
 		@Test
-		void shouldSetTotal() throws Exception {
+		void shouldSetTotal() {
 			callFindVorgaenge();
 
 			var response = responseCaptor.getValue();
@@ -299,7 +251,7 @@ class GrpcVorgangServiceTest {
 			assertThat(response.getTotal()).isEqualTo(TOTAL);
 		}
 
-		private void callFindVorgaenge() throws Exception {
+		private void callFindVorgaenge() {
 			service.findVorgang(request, responseObserver);
 
 			verify(responseObserver).onNext(responseCaptor.capture());
@@ -333,42 +285,46 @@ class GrpcVorgangServiceTest {
 		@Nested
 		class TestFindVorgangWithEingangService {
 
+			@Captor
+			private ArgumentCaptor<Vorgang> vorgangArgumentCaptor;
+
 			@BeforeEach
 			void mock() {
 				when(filterByMapper.fromFilterBy(any(GrpcFilterBy.class))).thenReturn(filterCriteria);
 			}
 
 			@Test
-			void shouldCallHeaderService() throws Exception {
+			void shouldCallHeaderService() {
 				callFindVorgangWithEingang();
 
 				verify(vorgangService).getById(VorgangTestFactory.ID, filterCriteria);
 			}
 
 			@Test
-			void shouldCallFindVorgangRequestMapper() throws Exception {
+			void shouldCallFindVorgangRequestMapper() {
 				callFindVorgangWithEingang();
 
 				verify(filterByMapper).fromFilterBy(GrpcFilterByTestFactory.create());
 			}
 
 			@Test
-			void shouldCallVorgangWithEingangMapper() throws Exception {
+			void shouldCallVorgangWithEingangMapper() {
 				callFindVorgangWithEingang();
 
 				verify(vorgangWithEingangMapper).toVorgangWithEingang(vorgang);
 			}
 
 			@Test
-			void shouldContainVorgangData() throws Exception {
+			void shouldContainVorgangData() {
 				callFindVorgangWithEingang();
 
 				assertThat(responseCaptor.getValue().getVorgangWithEingang()).usingRecursiveComparison()
 						.isEqualTo(GrpcVorgangWithEingangTestFactory.create());
 			}
+
 		}
 
-		private void callFindVorgangWithEingang() throws Exception {
+		private void callFindVorgangWithEingang() {
 			service.findVorgangWithEingang(request, responseObserver);
 
 			verify(responseObserver).onNext(responseCaptor.capture());
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangWithEingangTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangWithEingangTestFactory.java
similarity index 81%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangWithEingangTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangWithEingangTestFactory.java
index 59412d8b51a451737baee9cb4f8cdb189895753b..cae8291c21f0dce04a3d93f94ebfec6266770b8b 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangWithEingangTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcVorgangWithEingangTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import de.itvsh.ozg.pluto.clientattribute.GrpcClientAttributeTestFactory;
-import de.itvsh.ozg.pluto.command.GrpcUserTestFactory;
+import de.ozgcloud.vorgang.clientattribute.GrpcClientAttributeTestFactory;
+import de.ozgcloud.vorgang.command.GrpcUserTestFactory;
 
 public class GrpcVorgangWithEingangTestFactory {
 
@@ -32,10 +32,6 @@ public class GrpcVorgangWithEingangTestFactory {
 		return createBuilder().build();
 	}
 
-	static GrpcVorgangWithEingang createWithEingang(GrpcEingang eingang) {
-		return createBuilder().setEingang(eingang).build();
-	}
-
 	static GrpcVorgangWithEingang.Builder createBuilder() {
 		return GrpcVorgangWithEingang.newBuilder()
 				.setId(VorgangTestFactory.ID)
@@ -44,6 +40,7 @@ public class GrpcVorgangWithEingangTestFactory {
 				.setNummer(VorgangTestFactory.VORGANG_NUMMER)
 				.setStatus(VorgangTestFactory.STATUS.name())
 				.setCreatedAt(VorgangTestFactory.INITIAL_DATE_STR)
+				.setHeader(GrpcVorgangHeadTestFactory.create())
 				.setEingang(GrpcEingangTestFactory.create())
 				.setVersion(VorgangTestFactory.VERSION)
 				.setAssignedTo(GrpcUserTestFactory.ID)
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcZustaendigeStelleTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcZustaendigeStelleTestFactory.java
similarity index 93%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcZustaendigeStelleTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcZustaendigeStelleTestFactory.java
index da43cc4e7b21c87e16f718a4dce4aa2bf0711c3f..97f32ebc5800ca9a7db9859dc30076ba06e0cf0d 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcZustaendigeStelleTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/GrpcZustaendigeStelleTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 public class GrpcZustaendigeStelleTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupMapperTest.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupMapperTest.java
index 1d6cba1413217b73b42a8f07329049327925ec3f..989c5514713f415f78a39ae0c171a429f335c28f 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -32,7 +32,7 @@ import org.mockito.InjectMocks;
 import org.mockito.Spy;
 import org.springframework.test.util.ReflectionTestUtils;
 
-import de.itvsh.ozg.pluto.files.FileIdMapper;
+import de.ozgcloud.vorgang.files.FileIdMapper;
 
 class IncomingFileGroupMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupTestFactory.java
similarity index 92%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupTestFactory.java
index afb7f68c7315759c57c13d563200e4b4d3f6208f..a87818174da0b3ddeb4b790f6590e57d7095d376 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileGroupTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileGroupTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 public class IncomingFileGroupTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapperTest.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapperTest.java
index e5712d465311e5c89bd406dab0564969df780138..f2dbbc19b5433d9d6e226be5ac997af5af105372 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -31,7 +31,7 @@ import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
 import org.mockito.Spy;
 
-import de.itvsh.ozg.pluto.files.FileIdMapper;
+import de.ozgcloud.vorgang.files.FileIdMapper;
 
 class IncomingFileMapperTest {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileTestFactory.java
similarity index 93%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileTestFactory.java
index a2a8ae2494de8d1528b6c831cea27de6f85e87c6..b6999ec3194fcb22188a1a48be1b42a7d6f3a3a1 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/IncomingFileTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/IncomingFileTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -29,8 +29,8 @@ import java.io.InputStream;
 import java.util.Random;
 import java.util.UUID;
 
-import de.itvsh.kop.common.test.TestUtils;
-import de.itvsh.ozg.pluto.files.FileId;
+import de.ozgcloud.common.test.TestUtils;
+import de.ozgcloud.vorgang.files.FileId;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/LabelProcessorTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/LabelProcessorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8abdf16f6baeb79b588aaf8344be987e575ce2e9
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/LabelProcessorTest.java
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static de.ozgcloud.vorgang.vorgang.EingangTestFactory.*;
+import static de.ozgcloud.vorgang.vorgang.LabelProcessor.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+
+class LabelProcessorTest {
+
+	@Spy
+	@InjectMocks
+	private LabelProcessor mapper;
+
+	private Map<String, String> singleFieldLabelMap = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_LABEL);
+	private Map<String, String> subFormLabelMap = Map.of(SUBFORM_NAME, SUBFORM_LABEL);
+	private Map<String, String> fullFormLabelMap = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_LABEL, SUBFORM_NAME, SUBFORM_LABEL);
+
+	private Map<String, Object> singleFieldWithLabel = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, CONTROL_DATA_KEY, singleFieldLabelMap);
+
+	@Nested
+	class TestMoveLabelsToControlData {
+
+		private Map<String, Object> singleFieldMap = Map.of(VALUE_KEY, SINGLE_FIELD_VALUE, LABEL_KEY, SINGLE_FIELD_LABEL);
+
+		@Nested
+		class MoveLabels {
+			@BeforeEach
+			void init() {
+				doReturn(Optional.of(SINGLE_FIELD_LABEL)).when(mapper).getLabelFromFieldValue(any());
+
+			}
+
+			@Test
+			void shouldAddLabelToControlData() {
+				doReturn(SINGLE_FIELD_VALUE).when(mapper).getValueWithoutLabel(any());
+
+				var result = mapper.moveLabelsToControlData(Map.of(SINGLE_FIELD_NAME, singleFieldMap));
+
+				assertThat(result).contains(entry(CONTROL_DATA_KEY, Map.of(LABELS_KEY, singleFieldLabelMap)));
+			}
+
+			@Test
+			void shouldRemoveLabelFormValue() {
+				doReturn(SINGLE_FIELD_VALUE).when(mapper).getValueWithoutLabel(any());
+
+				var result = mapper.moveLabelsToControlData(Map.of(SINGLE_FIELD_NAME, singleFieldMap));
+
+				assertThat(result).contains(entry(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE));
+			}
+
+			@Test
+			void shouldProcessSubForm() {
+				mapper.moveLabelsToControlData(Map.of(SUBFORM_NAME, SUBFORM));
+
+				verify(mapper).doRecursionIfSubForm(Pair.of(SUBFORM_NAME, SUBFORM_FLAT));
+				verify(mapper).moveLabelsToControlData(SUBFORM_FLAT);
+			}
+		}
+
+		@Nested
+		class GetLables {
+			@Test
+			void shouldNotCallGetLabelForControlData() {
+				mapper.getLabelsFromFormData(Map.of(CONTROL_DATA_KEY, ""));
+
+				verify(mapper, never()).getLabelFromFieldValue(any());
+			}
+
+			@Test
+			void shouldReturnFieldLable() {
+				doReturn(Optional.of(SINGLE_FIELD_LABEL)).when(mapper).getLabelFromFieldValue(any());
+
+				var labels = mapper.getLabelsFromFormData(singleFieldWithLabel);
+
+				assertThat(labels).containsExactly(entry(SINGLE_FIELD_NAME, SINGLE_FIELD_LABEL));
+				verify(mapper).getLabelFromFieldValue(SINGLE_FIELD_VALUE);
+			}
+
+			@Test
+			void shouldOmitMissingLabel() {
+				doReturn(Optional.empty()).when(mapper).getLabelFromFieldValue(any());
+
+				var labels = mapper.getLabelsFromFormData(singleFieldWithLabel);
+
+				assertThat(labels).isEmpty();
+			}
+
+			@Nested
+			class FromFieldValue {
+				@Test
+				void shouldReturnLabel() {
+					var label = mapper.getLabelFromFieldValue(Map.of(VALUE_KEY, SINGLE_FIELD_VALUE, LABEL_KEY, SINGLE_FIELD_LABEL));
+
+					assertThat(label).contains(SINGLE_FIELD_LABEL);
+				}
+
+				@Test
+				void shouldReturnEmptyForValue() {
+					var label = mapper.getLabelFromFieldValue(SINGLE_FIELD_VALUE);
+
+					assertThat(label).isEmpty();
+				}
+
+				@Test
+				void shouldReturnLableForSubform() {
+					var label = mapper.getLabelFromFieldValue(Map.of(VALUE_KEY, SUBFORM, LABEL_KEY, SUBFORM_LABEL));
+
+					assertThat(label).contains(SUBFORM_LABEL);
+				}
+			}
+		}
+
+		@Nested
+		class RemoveLabel {
+			@Test
+			void shouldReturnSingleValue() {
+				var result = mapper.getValueWithoutLabel(SINGLE_FIELD_VALUE);
+
+				assertThat(result).isEqualTo(SINGLE_FIELD_VALUE);
+			}
+
+			@Test
+			void shouldReturnSingleValueWithoutLabel() {
+				var result = mapper.getValueWithoutLabel(Map.of(VALUE_KEY, SINGLE_FIELD_VALUE, LABEL_KEY, SINGLE_FIELD_LABEL));
+
+				assertThat(result).isEqualTo(SINGLE_FIELD_VALUE);
+			}
+
+			@Test
+			void shouldReturnSubForm() {
+				var result = mapper.getValueWithoutLabel(SUBFORM);
+
+				assertThat(result).isEqualTo(Map.of(SUBFORM_FIELD_NAME, SUBFORM_FIELD));
+			}
+
+			@Test
+			void shouldReturnSubFormWithoutLabel() {
+				var result = mapper.getValueWithoutLabel(Map.of(VALUE_KEY, SUBFORM, LABEL_KEY, SUBFORM_LABEL));
+
+				assertThat(result).isEqualTo(SUBFORM);
+			}
+		}
+
+		@Nested
+		class AddLabelsToControlData {
+			@Test
+			void shouldAddLables() {
+				doReturn(singleFieldLabelMap).when(mapper).getLabelsFromFormData(any());
+
+				var result = mapper.addLabelsToControlData(Map.of(SINGLE_FIELD_NAME, singleFieldMap));
+
+				assertThat(result).isEqualTo(Map.of(LABELS_KEY, Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_LABEL)));
+			}
+
+			@Test
+			void shouldAddNothingIfNoLabel() {
+				doReturn(Collections.emptyMap()).when(mapper).getLabelsFromFormData(any());
+
+				var result = mapper.addLabelsToControlData(Map.of(SINGLE_FIELD_NAME, singleFieldMap));
+
+				assertThat(result).isEmpty();
+			}
+		}
+
+		@Nested
+		class ReplaceControlData {
+			@Test
+			void shouldReplaceControlData() {
+				Map<String, Object> newControlData = Map.of("test", "test");
+
+				var result = mapper.replaceControlData(Map.of(CONTROL_DATA_KEY, Map.of("old", "old")), newControlData);
+
+				assertThat(result).containsOnly(entry(CONTROL_DATA_KEY, newControlData));
+			}
+
+			@Test
+			void shouldAddNothingIfEmpty() {
+				var result = mapper.replaceControlData(Collections.emptyMap(), Collections.emptyMap());
+
+				assertThat(result).isEmpty();
+			}
+		}
+
+		@Test
+		void shouldMapEmptyFormData() {
+			var eingang = EingangTestFactory.createBuilder().formData(Collections.emptyMap()).build();
+
+			var mapped = mapper.moveLabelsToControlData(eingang);
+
+			assertThat(mapped.getFormData()).isEqualTo(Collections.emptyMap());
+		}
+	}
+
+	@Nested
+	class TestMapKopControlDataToLabels {
+
+		@DisplayName("Mapping a single Field should call mapValue()")
+		@Test
+		void shouldCallMapValueForSingleField() {
+			addLabels(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE);
+
+			verify(mapper).addLabel(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, Collections.emptyMap());
+		}
+
+		@DisplayName("Should not map kopControlData")
+		@Test
+		void shouldNOTCallMapValueForControlData() {
+			addLabels(LabelProcessor.CONTROL_DATA_KEY, "");
+
+			verify(mapper, never()).addLabel(any(), any(), any());
+		}
+
+		private void addLabels(String key, Object value) {
+			mapper.addLabels(Map.of(key, value));
+		}
+
+		@Nested
+		class AddLabel {
+
+			@Test
+			void shouldCallAddToFieldValue() {
+				mapper.addLabel(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, singleFieldLabelMap);
+
+				verify(mapper).addLabelToFieldValue(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, singleFieldLabelMap);
+			}
+
+			@Test
+			void shouldJoinSingleFieldMappings() {
+				Map<String, List<Object>> mappingResult = Map.of(SINGLE_FIELD_NAME, Collections.emptyList());
+				doReturn(mappingResult).when(mapper).addLabelToFieldValue(any(), any(), any());
+
+				var mapped = mapper.addLabel(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, singleFieldLabelMap);
+
+				assertThat(mapped).containsAllEntriesOf(mappingResult);
+			}
+
+			@Nested
+			class ToFieldValue {
+				@Test
+				void shouldAddLabel() {
+					var mapped = mapper.addLabelToFieldValue(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_LABEL));
+
+					assertThat(mapped).isEqualTo(
+							Map.of(LabelProcessor.LABEL_KEY, SINGLE_FIELD_LABEL, LabelProcessor.VALUE_KEY, SINGLE_FIELD_VALUE));
+				}
+
+				@Test
+				void shouldHandleMissingLabel() {
+					var mapped = mapper.addLabelToFieldValue(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, Collections.emptyMap());
+
+					assertThat(mapped).isEqualTo(Map.of(LabelProcessor.VALUE_KEY, SINGLE_FIELD_VALUE));
+				}
+			}
+
+			@Test
+			void shouldCallAddLabelToSubForm() {
+				mapper.addLabel(SUBFORM_NAME, SUBFORM, Map.of(SUBFORM_NAME, SUBFORM_LABEL));
+
+				verify(mapper).addLabelsToSubForm(SUBFORM, Optional.of(SUBFORM_LABEL));
+			}
+
+			@Test
+			void shouldHandleMissingLabel() {
+				mapper.addLabel(SUBFORM_NAME, SUBFORM, Collections.emptyMap());
+
+				verify(mapper).addLabelsToSubForm(SUBFORM, Optional.empty());
+			}
+
+			@Nested
+			class ToSubForm {
+				@Test
+				void shouldAddLabel() {
+					var mapped = mapper.addLabelsToSubForm(SUBFORM, Optional.of(SUBFORM_LABEL));
+
+					assertThat(mapped).containsEntry(LabelProcessor.LABEL_KEY, SUBFORM_LABEL);
+				}
+
+				@Test
+				void shouldIgnoreMissingLable() {
+					var mapped = mapper.addLabelsToSubForm(SUBFORM, Optional.empty());
+
+					assertThat(mapped).doesNotContainKey(LabelProcessor.LABEL_KEY);
+				}
+
+				@Test
+				void shouldMapSubForm() {
+					mapper.addLabelsToSubForm(SUBFORM, Optional.of(SUBFORM_LABEL));
+
+					verify(mapper).addLabels(SUBFORM);
+				}
+
+				@Test
+				void shouldAddMappedValue() {
+					var mappedValue = Collections.emptyMap();
+					doReturn(mappedValue).when(mapper).addLabels(Mockito.<Map<String, Object>>any());
+
+					var mapped = mapper.addLabelsToSubForm(SUBFORM, Optional.of(SUBFORM_LABEL));
+
+					assertThat(mapped).containsEntry(LabelProcessor.VALUE_KEY, mappedValue);
+				}
+			}
+
+			@Nested
+			class MergedProcessedValues {
+				private Map<String, Object> singleFieldMap = Map.of(VALUE_KEY, SINGLE_FIELD_VALUE, LABEL_KEY, SINGLE_FIELD_LABEL);
+
+				private Map<String, Object> subFormFieldMap = Map.of(VALUE_KEY, SUBFORM_FIELD_VALUE, LABEL_KEY, SUBFORM_FIELD_LABEL);
+
+				private Map<String, Object> subFormMap = Map.of(LabelProcessor.VALUE_KEY, subFormFieldMap, LABEL_KEY, SUBFORM_LABEL);
+
+				@Test
+				void shouldContainFieldValue() {
+					doReturn(singleFieldMap).when(mapper).addLabelToFieldValue(any(), any(), any());
+
+					var mapped = mapper.addLabels(
+							Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, CONTROL_DATA_KEY, singleFieldLabelMap));
+
+					assertThat(mapped).containsExactly(entry(SINGLE_FIELD_NAME, singleFieldMap));
+				}
+
+				@Test
+				void shouldContainSubFormValue() {
+					doReturn(subFormMap).when(mapper).addLabelsToSubForm(any(), any());
+
+					var mapped = mapper.addLabels(
+							Map.of(CONTROL_DATA_KEY, subFormLabelMap, SUBFORM_NAME, SUBFORM));
+
+					assertThat(mapped).containsExactly(entry(SUBFORM_NAME, subFormMap));
+				}
+
+				@Test
+				void shouldContainsAllLabels() {
+					doReturn(singleFieldMap).when(mapper).addLabelToFieldValue(any(), any(), any());
+					doReturn(subFormMap).when(mapper).addLabelsToSubForm(any(), any());
+
+					var mapped = mapper.addLabels(
+							Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, CONTROL_DATA_KEY, fullFormLabelMap, SUBFORM_NAME, SUBFORM));
+
+					assertThat(mapped).isEqualTo(buildFullFormMap());
+				}
+
+				private Map<String, Object> buildFullFormMap() {
+					var map = new LinkedHashMap<String, Object>();
+					map.put(SINGLE_FIELD_NAME, singleFieldMap);
+					map.put(SUBFORM_NAME, subFormMap);
+
+					return map;
+				}
+			}
+		}
+
+		@Test
+		void shouldMapEmptyFormData() {
+			var eingang = EingangTestFactory.createBuilder().formData(Collections.emptyMap()).build();
+
+			var mapped = mapper.moveLabelsToControlData(eingang);
+
+			assertThat(mapped.getFormData()).isEqualTo(Collections.emptyMap());
+		}
+	}
+
+	@Nested
+	class TestIsFieldValue {
+
+		@Test
+		void shouldReturnTrueForSimpleValue() {
+			var field = SINGLE_FIELD_VALUE;
+
+			assertThat(mapper.isFieldValue(field)).isTrue();
+		}
+
+		@Test
+		void shouldReturnTrueForValueWithLabel() {
+			var field = Map.of(
+					LabelProcessor.LABEL_KEY, SINGLE_FIELD_LABEL,
+					LabelProcessor.VALUE_KEY, SINGLE_FIELD_VALUE);
+
+			assertThat(mapper.isFieldValue(field)).isTrue();
+		}
+
+		@Test
+		void shouldReturnFalseForSubFormValueWithoutLabel() {
+			var field = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE);
+
+			assertThat(mapper.isFieldValue(field)).isFalse();
+		}
+
+		@Test
+		void shouldReturnFalseForSubFormValueWithLabel() {
+			var field = Map.of(
+					LabelProcessor.LABEL_KEY, SUBFORM_LABEL,
+					LabelProcessor.VALUE_KEY, Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE));
+
+			assertThat(mapper.isFieldValue(field)).isFalse();
+		}
+
+		@Test
+		void shouldReturnFalseForEmptySubFormValue() {
+			var field = Map.of(
+					LabelProcessor.LABEL_KEY, SUBFORM_LABEL,
+					LabelProcessor.VALUE_KEY, Collections.emptyMap());
+
+			assertThat(mapper.isFieldValue(field)).isFalse();
+		}
+	}
+
+	@Nested
+	class TestGetFieldValue {
+
+		@Test
+		void shouldReturnValueForSimpleField() {
+			var fieldValue = SINGLE_FIELD_VALUE;
+
+			assertThat(mapper.getFieldValue(fieldValue)).isEqualTo(fieldValue);
+		}
+
+		@Test
+		void shouldReturnValueForFieldWithLabel() {
+			var fieldValue = Map.of(
+					LabelProcessor.LABEL_KEY, SINGLE_FIELD_LABEL,
+					LabelProcessor.VALUE_KEY, SINGLE_FIELD_VALUE);
+
+			assertThat(mapper.getFieldValue(fieldValue)).isEqualTo(SINGLE_FIELD_VALUE);
+		}
+
+		@Test
+		void shouldReturnValueForSubForm() {
+			var fieldValue = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE);
+
+			assertThat(mapper.getFieldValue(fieldValue)).isEqualTo(fieldValue);
+		}
+
+		@Test
+		void shouldReturnValueForSubFormWithLabel() {
+			var fieldValue = Map.of(
+					LabelProcessor.LABEL_KEY, SUBFORM_LABEL,
+					LabelProcessor.VALUE_KEY, SUBFORM);
+
+			assertThat(mapper.getFieldValue(fieldValue)).isEqualTo(SUBFORM);
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/QueryCriteriaBuilderTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/QueryCriteriaBuilderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3f855b46e3dd66c395e252e89ee965322039826
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/QueryCriteriaBuilderTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Spy;
+import org.springframework.data.mongodb.core.query.Criteria;
+
+import de.ozgcloud.vorgang.common.operator.OperatorTestFactory;
+import de.ozgcloud.vorgang.vorgang.FindVorgangQuery.LogicalOperator;
+
+class QueryCriteriaBuilderTest {
+
+	@Spy
+	@InjectMocks
+	private QueryCriteriaBuilder queryCriteriaBuilder;
+
+	private Criteria criteria = Criteria.where(OperatorTestFactory.PATH).is(OperatorTestFactory.STRING_VALUE);
+
+	@Nested
+	class TestFrom {
+
+		@Test
+		void shouldBuildCriteriaFromOperators() {
+			var result = queryCriteriaBuilder.from(FindVorgangQueryTestFactory.create());
+
+			assertThat(result).isEqualTo(criteria);
+		}
+
+		@Test
+		void shouldBuildFromNestedQuery() {
+			var nestedQuery = FindVorgangQueryTestFactory.createBuilder().logicalOperator(LogicalOperator.OR).build();
+			var query = FindVorgangQueryTestFactory.createBuilder().clearOperators().nestedQuery(nestedQuery).build();
+
+			var result = queryCriteriaBuilder.from(query);
+
+			assertThat(result).isEqualTo(criteria);
+		}
+
+		@Test
+		void shouldCallAddFromOperators() {
+			var query = FindVorgangQueryTestFactory.create();
+
+			queryCriteriaBuilder.from(query);
+
+			verify(queryCriteriaBuilder).addFromOperators(any(), eq(query.getOperators()));
+		}
+
+		@Test
+		void shouldCallConnect() {
+			var query = FindVorgangQueryTestFactory.create();
+
+			queryCriteriaBuilder.from(query);
+
+			verify(queryCriteriaBuilder).connect(eq(query.getLogicalOperator()), any());
+		}
+	}
+
+	@Nested
+	class TestAddFromOperators {
+
+		@Test
+		void shouldAddOperators() {
+			var resultList = new ArrayList<Criteria>();
+
+			queryCriteriaBuilder.addFromOperators(resultList, List.of(OperatorTestFactory.createEqualOperator()));
+
+			assertThat(resultList).containsExactly(criteria);
+		}
+
+	}
+
+	@Nested
+	class TestConnect {
+
+		private Criteria criteria1 = Criteria.where(OperatorTestFactory.PATH).is(OperatorTestFactory.STRING_VALUE);
+
+		@Test
+		void shouldConnectWithAnd() {
+			var result = queryCriteriaBuilder.connect(LogicalOperator.AND, List.of(criteria, criteria1));
+
+			assertThat(result.getCriteriaObject()).containsKey("$and");
+		}
+
+		@Test
+		void shouldConnectWithOr() {
+			var result = queryCriteriaBuilder.connect(LogicalOperator.OR, List.of(criteria, criteria1));
+
+			assertThat(result.getCriteriaObject()).containsKey("$or");
+		}
+
+		@Test
+		void shouldReturnEmptyCriteria() {
+			var result = queryCriteriaBuilder.connect(LogicalOperator.AND, List.of());
+
+			assertThat(result.getCriteriaObject()).isEmpty();
+		}
+
+		@Test
+		void shouldReturnSingleCriteria() {
+			var result = queryCriteriaBuilder.connect(LogicalOperator.AND, List.of(criteria));
+
+			assertThat(result).isEqualTo(criteria);
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangAuthorizationServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangAuthorizationServiceTest.java
similarity index 97%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangAuthorizationServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangAuthorizationServiceTest.java
index 293da70ab3f305bb4929b21fba0003f19575ab84..0e935bbcd7179abb43d2e010886de226791d75fd 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangAuthorizationServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangAuthorizationServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangDeletedEventTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangDeletedEventTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ceb6005829691709fcdb1ea9a658919010e02ba0
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangDeletedEventTestFactory.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+
+public class VorgangDeletedEventTestFactory {
+
+	public static VorgangDeletedEvent create() {
+		return new VorgangDeletedEvent(CommandTestFactory.createBuilder().order("VORGANG_LOESCHEN").build());
+	}
+
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..72df1a0cb6092339fceee746e691c95d60799693
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerITCase.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static de.ozgcloud.vorgang.vorgang.VorgangService.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+import org.springframework.context.ApplicationEventPublisher;
+
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandCreatedEvent;
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.notification.antragsteller.AntragstellerNotificationEventListener;
+import de.ozgcloud.notification.user.UserNotificationEventListener;
+import de.ozgcloud.processor.processor.ProcessorService;
+import de.ozgcloud.processor.vorgang.ProcessorVorgangMapper;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.files.FileService;
+
+@ITCase
+@SpringBootTest(properties = {
+		"ozgcloud.processors[0].address: http://test1",
+		"ozgcloud.processors[0].name: processor1",
+		"ozgcloud.processors[0].forms[0].formEngineName: formEngineTest1",
+		"ozgcloud.processors[0].forms[0].formId: ID1"
+})
+class VorgangEventListenerITCase {
+
+	@Autowired
+	private ApplicationEventPublisher publisher;
+
+	@SpyBean
+	private VorgangEventListener listener;
+	@SpyBean
+	private AntragstellerNotificationEventListener antragstellerNotificationEventListener;
+	@SpyBean
+	private UserNotificationEventListener userNotificationEventListener;
+
+	@MockBean
+	private VorgangService service;
+	@MockBean
+	private VorgangHeaderService vorgangHeaderService;
+	@MockBean
+	private FileService fileService;
+	@Autowired
+	private CommandService commandService;
+
+	@MockBean
+	private ProcessorService vorgagnProcessorService;
+	@MockBean
+	private OzgCloudVorgangService ozgCloudVorgangService;
+	@MockBean
+	private ProcessorVorgangMapper processorVorgangMapper;
+
+	@Nested
+	class TestOnVorgangLoeschen {
+
+		@BeforeEach
+		void init() {
+			doNothing().when(listener).publishEvent(any());
+		}
+
+		@Test
+		void shouldCallService() {
+			publisher.publishEvent(CommandCreatedEventTestFactory.create(CommandTestFactory.createBuilder().order("VORGANG_LOESCHEN").build()));
+
+			verify(service, timeout(500)).deleteVorgang(VorgangTestFactory.ID);
+		}
+
+	}
+
+	@Nested
+	class TestOnVorgangCreated {
+
+		@BeforeEach
+		void init() {
+			doNothing().when(antragstellerNotificationEventListener).onVorgangCreated(any());
+			doNothing().when(userNotificationEventListener).onVorgangCreated(any());
+
+		}
+
+		@Test
+		void shouldCallProcessorService() {
+			publisher.publishEvent(new VorgangCreatedEvent("id"));
+
+			verify(vorgagnProcessorService, timeout(500)).processVorgang(any());
+		}
+	}
+
+	@Nested
+	class TestOnSetAktenzeichen {
+
+		private static final Command SET_AKTENZEICHEN_COMMAND = CommandTestFactory.createBuilder().order(Order.SET_AKTENZEICHEN.name())
+				.bodyObject(Map.of(BODY_OBJECT_AKTENZEICHEN, VorgangTestFactory.AKTENZEICHEN)).build();
+		private static final CommandCreatedEvent SET_AKTENZEICHEN_EVENT = CommandCreatedEventTestFactory.create(SET_AKTENZEICHEN_COMMAND);
+
+		@BeforeEach
+		void init() {
+			doNothing().when(listener).onSetAktenzeichen(any());
+		}
+
+		@Test
+		void shouldCallOnSetAktenzeichen() {
+			publisher.publishEvent(SET_AKTENZEICHEN_EVENT);
+
+			verify(listener, timeout(500)).onSetAktenzeichen(SET_AKTENZEICHEN_EVENT);
+		}
+
+		@Test
+		void shouldNotCallOnSetAktenzeichen() {
+			publisher.publishEvent(CommandCreatedEventTestFactory.create(CommandTestFactory.createBuilder().order("NOT_SET_AKTENZEICHEN").build()));
+
+			verify(listener, never()).onSetAktenzeichen(any());
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c1aaf7702ef86a9504e276c59c0631dfaa48a799
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static de.ozgcloud.vorgang.vorgang.VorgangService.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.context.ApplicationEventPublisher;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandExecutedEvent;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.common.errorhandling.FunctionalException;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.status.StatusService;
+import de.ozgcloud.vorgang.vorgang.redirect.VorgangForwardFailedEventTestFactory;
+import de.ozgcloud.vorgang.vorgang.redirect.VorgangRedirectedEventTestFactory;
+
+class VorgangEventListenerTest {
+
+	@InjectMocks
+	private VorgangEventListener listener;
+
+	@Mock
+	private VorgangService service;
+	@Mock
+	private VorgangHeaderService vorgangHeaderService;
+	@Mock
+	private StatusService statusService;
+	@Mock
+	private FileService fileService;
+	@Mock
+	private CommandService commandService;
+
+	@Mock
+	private ApplicationEventPublisher publisher;
+
+	@Nested
+	class OnVorgangRedirectedEvent {
+
+		@Test
+		void shouldSetStatus() {
+			listener.updateStatus(VorgangRedirectedEventTestFactory.create());
+
+			verify(statusService).setStatusToWeitergeleitet(VorgangRedirectedEventTestFactory.SOURCE.getVorgangId(),
+					VorgangRedirectedEventTestFactory.SOURCE.getCreatedByCommand());
+		}
+	}
+
+	@Nested
+	class TestUpdateStatusOnVorgangForwardFailedEvent {
+
+		@Test
+		void shouldSetStatus() {
+			listener.updateStatus(VorgangForwardFailedEventTestFactory.create());
+
+			verify(statusService).setStatusToInBearbeitung(VorgangForwardFailedEventTestFactory.SOURCE.getVorgangId(),
+					VorgangForwardFailedEventTestFactory.SOURCE.getId());
+		}
+	}
+
+	@Nested
+	class TestDeleteVorgang {
+
+		@Test
+		void shouldDeleteVorgang() {
+			listener.onVorgangLoeschen(CommandCreatedEventTestFactory.create());
+
+			verify(service).deleteVorgang(VorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldPublishDoneEvent() {
+			listener.onVorgangLoeschen(CommandCreatedEventTestFactory.create());
+
+			verify(publisher).publishEvent(any(CommandExecutedEvent.class));
+		}
+
+		@Test
+		void shouldPublishFailedEvent() {
+			doThrow(new FunctionalException(() -> "test")).when(service).deleteVorgang(any());
+
+			listener.onVorgangLoeschen(CommandCreatedEventTestFactory.create());
+
+			verify(publisher).publishEvent(any(CommandFailedEvent.class));
+		}
+
+		@Test
+		void shouldDeleteFiles() {
+			listener.onVorgangLoeschen(CommandCreatedEventTestFactory.create());
+
+			verify(fileService).deleteAllByVorgang(VorgangTestFactory.ID);
+		}
+	}
+
+	@Nested
+	class TestSetAktenzeichen {
+
+		private static final Command SET_AKTENZEICHEN_COMMAND = CommandTestFactory.createBuilder().order(Order.SET_AKTENZEICHEN.name())
+				.bodyObject(Map.of(BODY_OBJECT_AKTENZEICHEN, VorgangTestFactory.AKTENZEICHEN)).build();
+		private static final String PREVIOUS_AKTENZEICHEN = VorgangTestFactory.ID + "-prev";
+
+		@BeforeEach
+		void init() {
+			when(vorgangHeaderService.getById(VorgangTestFactory.ID)).thenReturn(
+					VorgangHeaderTestFactory.createBuilder().aktenzeichen(PREVIOUS_AKTENZEICHEN).build());
+		}
+
+		@Test
+		void shouldCallGetById() {
+			callListener();
+
+			verify(vorgangHeaderService).getById(VorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldFailIfVorgangNotFound() {
+			when(vorgangHeaderService.getById(VorgangTestFactory.ID)).thenThrow(TechnicalException.class);
+
+			callListener();
+
+			verify(publisher).publishEvent(any(CommandFailedEvent.class));
+		}
+
+		@Test
+		void shouldSetPreviousAktenzeichen() {
+			callListener();
+
+			verify(commandService).setPreviousState(CommandTestFactory.ID,
+					Map.of(VorgangService.BODY_OBJECT_AKTENZEICHEN, PREVIOUS_AKTENZEICHEN));
+		}
+
+		@Test
+		@DisplayName("should store a null in previousState, if Aktenzeichen is null")
+		void shouldHandleNullAktenzeichen() {
+			when(vorgangHeaderService.getById(VorgangTestFactory.ID)).thenReturn(VorgangHeaderTestFactory.createBuilder().aktenzeichen(null).build());
+
+			callListener();
+
+			verify(commandService).setPreviousState(CommandTestFactory.ID, Collections.singletonMap(VorgangService.BODY_OBJECT_AKTENZEICHEN, null));
+		}
+
+		@Test
+		void shouldCallVorgangService() {
+			callListener();
+
+			verify(service).setAktenzeichen(SET_AKTENZEICHEN_COMMAND);
+		}
+
+		@Test
+		void shouldPublishEvent() {
+			callListener();
+
+			verify(publisher).publishEvent(any(SetAktenzeichenCompletedEvent.class));
+		}
+
+		@Nested
+		class TestFailedEvent {
+
+			private final String ERROR_MESSAGE = LoremIpsum.getInstance().getWords(3);
+
+			@Captor
+			private ArgumentCaptor<CommandFailedEvent> event;
+
+			@BeforeEach
+			void init() {
+				doThrow(new RuntimeException(ERROR_MESSAGE)).when(service).setAktenzeichen(any());
+			}
+
+			@Test
+			void shouldContainCommandId() {
+				callListener();
+
+				verify(publisher).publishEvent(event.capture());
+				assertThat(event.getValue().getSource()).isEqualTo(CommandTestFactory.ID);
+				assertThat(event.getValue().getErrorMessage()).isEqualTo(ERROR_MESSAGE);
+			}
+
+			@Test
+			void shouldContainMessage() {
+				callListener();
+
+				verify(publisher).publishEvent(event.capture());
+				assertThat(event.getValue().getErrorMessage()).isEqualTo(ERROR_MESSAGE);
+			}
+		}
+
+		private void callListener() {
+			listener.onSetAktenzeichen(CommandCreatedEventTestFactory.create(SET_AKTENZEICHEN_COMMAND));
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeadTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeadTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..4bc3eb87f7dcea3753459eb1f3d0ad3bb35bdef2
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeadTestFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoTestFactory;
+
+public class VorgangHeadTestFactory {
+
+	public static VorgangHead create() {
+		return createBuilder().build();
+	}
+
+	public static VorgangHead.VorgangHeadBuilder createBuilder() {
+		return VorgangHead.builder()
+				.serviceKonto(ServiceKontoTestFactory.create());
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryITCase.java
similarity index 51%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryITCase.java
index b411024dbbca72d5a00359ea7136adcf3a834e4c..026a430a05c552baa31ebb756921e022735611b1 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -46,19 +46,22 @@ import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.mongodb.core.MongoOperations;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.attached_item.VorgangAttachedItem;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttribute;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributeMap;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributeTestFactory;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributesMap;
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.vorgang.FindVorgangRequest.OrderCriteria;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeMap;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMapTestFactory;
+import de.ozgcloud.vorgang.common.GrpcQueryOperator;
+import de.ozgcloud.vorgang.common.db.CriteriaUtil;
+import de.ozgcloud.vorgang.common.operator.OperatorBuilder;
+import de.ozgcloud.vorgang.vorgang.FindVorgangQuery.LogicalOperator;
+import de.ozgcloud.vorgang.vorgang.FindVorgangRequest.OrderCriteria;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
 
 @DataITCase
 class VorgangHeaderRepositoryITCase {
-	static final String CLIENT_ATTRIBUTE_NEXT_WIEDERVORLAGE_FRIST = "nextWiedervorlageFrist";
 
 	@Autowired
 	private VorgangHeaderRepository repository;
@@ -78,35 +81,62 @@ class VorgangHeaderRepositoryITCase {
 				.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().build())
 				.searchBy(StringUtils.EMPTY).build();
 
+		@Test
+		void shouldSortExpiredWiedervorlagenByFrist() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(2, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(3, ChronoUnit.DAYS))).build());
+
+			var vorgaenge = repository.findAll(request).getContent();
+
+			assertThat(vorgaenge).hasSize(2).extracting(VorgangHeader::getId).containsExactly("1", "2");
+		}
+
+		// based on OZG-1991
+		@DisplayName("should sort vorgaenge with expired wiedervorlage by frist even if another wiedervorlage is done")
+		@Test
+		void shouldSortExpiredWiedervorlagenByFristWithDoneWidervorlage() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2").build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(3, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("3")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(2, ChronoUnit.DAYS))).build());
+
+			var vorgaenge = repository.findAll(request).getContent();
+
+			assertThat(vorgaenge).hasSize(3).extracting(VorgangHeader::getId).containsExactly("1", "3", "2");
+		}
+
 		@ParameterizedTest
-		@EnumSource(mode = Mode.EXCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG", "BESCHIEDEN", "WEITERGELEITET" })
-		void shouldContainRemainingStatus(Status status) {
-			mongoOperations.save(VorgangTestFactory.createBuilder().id(null).status(status).build());
+		@EnumSource(mode = Mode.INCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG" })
+		void shouldSortZuBearbeitenAfterExpiredWdvlg(Status status) {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2").status(status).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(2, ChronoUnit.DAYS))).build());
 
 			var vorgaenge = repository.findAll(request).getContent();
 
-			assertThat(vorgaenge).hasSize(1);
+			assertThat(vorgaenge).hasSize(2).extracting(VorgangHeader::getId).containsExactly("1", "2");
 		}
 
 		@Test
-		void shouldPageableResultByGivenLimit() {
-			mongoOperations.save(VorgangTestFactory.createBuilder().id(String.valueOf("1")).build());
-			mongoOperations.save(VorgangTestFactory.createBuilder().id(String.valueOf("2")).build());
+		void shouldSortOpenWdvlgAfterZuBearbeiten() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("3")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(3, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(2, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1").status(Status.NEU).build());
 
-			var request = FindVorgangRequestTestFactory.createBuilder()
-					.orderBy(OrderCriteria.PRIORITY)
-					.filterBy(null).searchBy(StringUtils.EMPTY)
-					.limit(1)
-					.offset(0)
-					.build();
 			var vorgaenge = repository.findAll(request).getContent();
 
-			assertThat(vorgaenge).hasSize(1);
+			assertThat(vorgaenge).hasSize(3).extracting(VorgangHeader::getId).containsExactly("1", "2", "3");
 		}
 
 		@Test
 		void shouldSortZurBearbeitungByCreatedAt() {
-			mongoOperations.save(VorgangTestFactory.createBuilder().id("2").status(Status.NEU).createdAt(ZonedDateTime.now()).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2").status(Status.NEU)
+					.createdAt(ZonedDateTime.now()).build());
 			mongoOperations.save(VorgangTestFactory.createBuilder().id("1").status(Status.IN_BEARBEITUNG)
 					.createdAt(ZonedDateTime.now().minus(1, ChronoUnit.DAYS)).build());
 
@@ -115,6 +145,33 @@ class VorgangHeaderRepositoryITCase {
 			assertThat(vorgaenge).hasSize(2).extracting(VorgangHeader::getId).containsExactly("1", "2");
 		}
 
+		@Test
+		void shouldSortOpendWdvlgIgnoringClosedWdvlg() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2").createdAt(ZonedDateTime.now().minus(2, ChronoUnit.DAYS))
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(4, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("3").createdAt(ZonedDateTime.now().minus(2, ChronoUnit.DAYS)).build());
+
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1").createdAt(ZonedDateTime.now().minus(1, ChronoUnit.DAYS))
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(3, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("4").createdAt(ZonedDateTime.now().minus(1, ChronoUnit.DAYS)).build());
+
+			var vorgaenge = repository.findAll(request).getContent();
+
+			assertThat(vorgaenge).hasSize(4).extracting(VorgangHeader::getId).containsExactly("3", "4", "1", "2");
+		}
+
+		@ParameterizedTest
+		@EnumSource(mode = Mode.INCLUDE, names = { "BESCHIEDEN", "WEITERGELEITET" })
+		void shouldSortBearbeitetAfterWdvlg(Status status) {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(2, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2").status(status).build());
+
+			var vorgaenge = repository.findAll(request).getContent();
+
+			assertThat(vorgaenge).hasSize(2).extracting(VorgangHeader::getId).containsExactly("1", "2");
+		}
+
 		@ParameterizedTest
 		@EnumSource(mode = Mode.INCLUDE, names = { "BESCHIEDEN", "WEITERGELEITET" })
 		void shouldReturnBearbeitetOnlyOnce(Status status) {
@@ -125,144 +182,187 @@ class VorgangHeaderRepositoryITCase {
 			assertThat(vorgaenge).hasSize(1);
 		}
 
-		@Nested
-		class sortOrder {
-			final FindVorgangRequest request = FindVorgangRequestTestFactory.createBuilder()
-					.orderBy(OrderCriteria.PRIORITY)
-					.filterBy(FilterCriteriaTestFactory.createBuilder().clearStatus().build())
-					.searchBy(StringUtils.EMPTY).build();
+		// Zeigt den Bug von OZG-3156
+		@ParameterizedTest
+		@EnumSource
+		void shouldReturnWithWdvlgOnlyOnce(Status status) {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1").status(status)
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(2, ChronoUnit.DAYS))).build());
 
-			@BeforeEach
-			void init() {
-				mongoOperations.dropCollection(Vorgang.COLLECTION_NAME);
-				mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME);
+			var vorgaenge = repository.findAll(request).getContent();
 
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("4").status(Status.ABGESCHLOSSEN)
-						.createdAt(ZonedDateTime.now().minusDays(2)).build());
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("3").status(Status.NEU)
-						.createdAt(ZonedDateTime.now().minusDays(2)).build());
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("2").status(Status.IN_BEARBEITUNG)
-						.createdAt(ZonedDateTime.now().minusDays(3)).build());
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("1").status(Status.IN_BEARBEITUNG)
-						.createdAt(ZonedDateTime.now().minusDays(4)).build());
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("9").createdAt(ZonedDateTime.now().minusDays(1))
-						.status(Status.BESCHIEDEN).build());
-
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("5").createdAt(ZonedDateTime.now().minusDays(1))
-						.clientAttributes(buildClientAttribute(30, false)).build()).getId();
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("6").createdAt(ZonedDateTime.now().minusDays(1))
-						.clientAttributes(buildClientAttribute(300, true)).build()).getId();
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("7").createdAt(ZonedDateTime.now().minusDays(1))
-						.clientAttributes(buildClientAttribute(5, false)).build()).getId();
-				mongoOperations.save(VorgangTestFactory.createBuilder().id("8").createdAt(ZonedDateTime.now().minusDays(1))
-						.clientAttributes(buildClientAttribute(10, true)).build()).getId();
+			assertThat(vorgaenge).hasSize(1);
+		}
 
-			}
+		@ParameterizedTest
+		@EnumSource(mode = Mode.EXCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG", "BESCHIEDEN", "WEITERGELEITET" })
+		void shouldContainRemainingStatus(Status status) {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id(null).status(status).build());
 
-			private ClientAttributesMap buildClientAttribute(int deltaDays, boolean isMinus) {
-				ClientAttribute attribute;
-				ClientAttribute.ClientAttributeBuilder builder = ClientAttributeTestFactory.createBuilder()
-						.clientName(VorgangHeaderRepositoryImpl.DEFAULT_CLIENT)
-						.attributeName(CLIENT_ATTRIBUTE_NEXT_WIEDERVORLAGE_FRIST);
-				if (isMinus) {
-					attribute = builder.stringValue(Optional.of(LocalDate.now().minusDays(deltaDays).toString())).build();
-				} else {
-					attribute = builder.stringValue(Optional.of(LocalDate.now().plusDays(deltaDays).toString())).build();
-				}
+			var vorgaenge = repository.findAll(request).getContent();
 
-				var attributeMap = new ClientAttributeMap();
-				List.of(attribute).stream().forEach(attrib -> attributeMap.put(attrib.getAttributeName(), attrib));
-				ClientAttributesMap attributesMap = new ClientAttributesMap();
-				attributesMap.put(attribute.getClientName(), attributeMap);
+			assertThat(vorgaenge).hasSize(1);
+		}
 
-				return attributesMap;
-			}
+		@Test
+		void shouldPageableResultByGivenLimit() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id(String.valueOf("1")).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id(String.valueOf("2")).build());
 
-			@Nested
-			class rang1 {
-				@Test
-				@DisplayName("Position 0: Vorgang von vor 1 Tagen mit Status 'NEU' und offener Wiedervorlage mit Frist vor 300 Tagen")
-				void vorgangWithStatusNeuAndOpenWiedervorlageAtPostion0() {
-					var vorgaenge = repository.findAll(request).getContent();
+			var request = FindVorgangRequestTestFactory.createBuilder()
+					.orderBy(OrderCriteria.PRIORITY)
+					.filterBy(null).searchBy(StringUtils.EMPTY)
+					.limit(1)
+					.offset(0)
+					.build();
+			var vorgaenge = repository.findAll(request).getContent();
 
-					assertThat(vorgaenge.get(0).getId()).isEqualTo("6");
-				}
+			assertThat(vorgaenge).hasSize(1);
+		}
 
-				@Test
-				@DisplayName("Position 1: Vorgang von vor 1 Tagen mit Status 'NEU' und offener Wiedervorlage mit Frist vor 10 Tagen")
-				void vorgangWithStatusNeuAndOpenWiedervorlageAtPostion1() {
-					var vorgaenge = repository.findAll(request).getContent();
+		@Test
+		void shouldConsiderWiedervorlageDone() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1").build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(2, ChronoUnit.DAYS))).build());
 
-					assertThat(vorgaenge.get(1).getId()).isEqualTo("8");
-				}
-			}
+			var vorgaenge = repository.findAll(request).getContent();
 
-			@Nested
-			class rang2 {
-				@Test
-				@DisplayName("Position 2: Vorgang von vor 5 Tagen mit Status 'IN_BEARBEITUNG' und ohne Wiedervorlage")
-				void vorgangWithStatusInBearbeitungWithoutWiedervorlageAtPostion4() {
-					var vorgaenge = repository.findAll(request).getContent();
+			assertThat(vorgaenge).hasSize(2);
+			assertThat(vorgaenge.get(0).getId()).isEqualTo("2");
+			assertThat(vorgaenge.get(1).getId()).isEqualTo("1");
+		}
 
-					assertThat(vorgaenge.get(2).getId()).isEqualTo("1");
-				}
+		// based on OZG-1822
+		@Test
+		void shouldShowVorgangWithDoneAndOpenWiedervorlage() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(1, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2").build());
 
-				@Test
-				@DisplayName("Position 3: Vorgang von vor 3 Tagen mit Status 'IN_BEARBEITUNG' und ohne Wiedervorlage")
-				void vorgangWithStatusInBearbeietungWithoutWiedervorlageAtPostion5() {
-					var vorgaenge = repository.findAll(request).getContent();
+			var vorgaenge = repository.findAll(request).getContent();
 
-					assertThat(vorgaenge.get(3).getId()).isEqualTo("2");
-				}
+			assertThat(vorgaenge).hasSize(2).extracting(VorgangHeader::getId).containsExactly("2", "1");
+		}
 
-				@Test
-				@DisplayName("Position 4: Vorgang von vor 2 Tagen mit Status 'NEU' und ohne Wiedervorlage")
-				void vorgangWithStatusNeuWithoutWiedervorlageAtPostion6() {
-					var vorgaenge = repository.findAll(request).getContent();
+		// based on OZG-1826, OZG-1885
+		@DisplayName("should show Vorgang with expired Wdvlg only once.")
+		@ParameterizedTest
+		@EnumSource
+		void shouldShowExpiredWdvlgOnlyOnce(Status status) {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id(null).status(Status.NEU).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id(null).status(status)
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(1, ChronoUnit.DAYS)))
+					.build());
 
-					assertThat(vorgaenge.get(4).getId()).isEqualTo("3");
-				}
+			var vorgaenge = repository.findAll(request).getContent();
 
-				@Test
-				@DisplayName("Position 5: Vorgang von vor 1 Tagen mit Status 'NEU' und offener Wiedervorlage mit Frist in 5 Tagen")
-				void vorgangWithStatusNeuAndOpenWiedervorlageAtPostion3() {
-					var vorgaenge = repository.findAll(request).getContent();
+			assertThat(vorgaenge).hasSize(2);
+		}
+	}
 
-					assertThat(vorgaenge.get(5).getId()).isEqualTo("7");
-				}
+	@DisplayName("Sort createdAt desc")
+	@Nested
+	class TestSortCreatedAtDesc {
 
-				@Test
-				@DisplayName("Position 6: Vorgang von vor 1 Tagen mit Status 'NEU' und offener Wiedervorlage mit Frist in 30 Tagen")
-				void vorgangWithStatusNeuAndOpenWiedervorlageAtPostion2() {
-					var vorgaenge = repository.findAll(request).getContent();
+		@DisplayName("with single status filter criteria")
+		@Nested
+		class TestWithSingleStatusCriteria {
 
-					assertThat(vorgaenge.get(6).getId()).isEqualTo("5");
-				}
+			@BeforeEach
+			void prepareDatabase() {
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("1").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(2, ChronoUnit.DAYS)).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("2").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(3, ChronoUnit.DAYS)).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("3").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(4, ChronoUnit.DAYS)).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("4").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(5, ChronoUnit.DAYS)).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("5").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(6, ChronoUnit.DAYS)).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("6").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(7, ChronoUnit.DAYS)).build());
 			}
 
-			@Nested
-			class rang3 {
-				@Test
-				@DisplayName("Position 7: Vorgang von vor 1 Tagen mit Status 'BESCHIEDEN'")
-				void vorgangWithStatusBeschiedenAtPostion7() {
-					var vorgaenge = repository.findAll(request).getContent();
+			@Test
+			void shouldReturnSortedVorgaenge() {
+				var request = buildRequestWithFilterCriteria(FilterCriteriaTestFactory.createBuilder().assignedTo(null).build());
 
-					assertThat(vorgaenge.get(7).getId()).isEqualTo("9");
-				}
+				var vorgaenge = repository.findAll(request).getContent();
+
+				assertThat(vorgaenge).hasSize(6).extracting(VorgangHeader::getId).containsExactly("1", "2", "3", "4", "5", "6");
 			}
+		}
 
-			@Nested
-			class rang4 {
-				@Test
-				@DisplayName("Position 8: Vorgang von vor 2 Tagen mit Status 'ABGESCHLOSSEN' ohne Wiedervorlage")
-				void vorgangWithStatusAbgeschlossenWithoutWiedervorlageAtPostion8() {
-					var vorgaenge = repository.findAll(request).getContent();
+		@DisplayName("with single status and assignedTo filter criteria")
+		@Nested
+		class TestWithSingleStatusAndAssignedToCriteria {
 
-					assertThat(vorgaenge.get(8).getId()).isEqualTo("4");
-				}
+			@BeforeEach
+			void prepareDatabase() {
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("1").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(2, ChronoUnit.DAYS)).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("2").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(3, ChronoUnit.DAYS)).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("3").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(4, ChronoUnit.DAYS))
+						.assignedTo(null)
+						.build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("4").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(5, ChronoUnit.DAYS)).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("5").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(6, ChronoUnit.DAYS))
+						.assignedTo(null)
+						.build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("6").status(Status.NEU)
+						.createdAt(ZonedDateTime.now().minus(7, ChronoUnit.DAYS)).build());
 			}
+
+			@Test
+			void shouldReturnSortedVorgaenge() {
+				var request = buildRequestWithFilterCriteria(FilterCriteriaTestFactory.create());
+
+				var vorgaenge = repository.findAll(request).getContent();
+
+				assertThat(vorgaenge).hasSize(4).extracting(VorgangHeader::getId).containsExactly("1", "2", "4", "6");
+			}
+		}
+
+		private FindVorgangRequest buildRequestWithFilterCriteria(FilterCriteria filterCriteria) {
+			return FindVorgangRequestTestFactory.createBuilder()
+					.orderBy(OrderCriteria.CREATED_AT_DESC)
+					.filterBy(filterCriteria)
+					.searchBy(StringUtils.EMPTY).build();
+		}
+	}
+
+	@DisplayName("Sort hasNextWiedervorlageFrist")
+	@Nested
+	class TestSortHasNextWiedervorlageFrist {
+
+		@Test
+		void shouldReturnSortedVorgaenge() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now())).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("3")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(1, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(1, ChronoUnit.DAYS))).build());
+
+			var request = buildRequestWithFilterCriteria(FilterCriteria.builder().build());
+
+			var vorgaenge = repository.findAll(request).getContent();
+
+			assertThat(vorgaenge).hasSize(3).extracting(VorgangHeader::getId).containsExactly("3", "2", "1");
 		}
 
+		private FindVorgangRequest buildRequestWithFilterCriteria(FilterCriteria filterCriteria) {
+			return FindVorgangRequestTestFactory.createBuilder()
+					.orderBy(OrderCriteria.NEXT_WIEDERVORLAGE_FRIST)
+					.filterBy(filterCriteria)
+					.searchBy(StringUtils.EMPTY).build();
+		}
 	}
 
 	@Nested
@@ -378,6 +478,24 @@ class VorgangHeaderRepositoryITCase {
 			assertThat(vorgaenge).hasSize(1);
 			assertThat(vorgaenge.get(0).getId()).isEqualTo("1");
 		}
+
+		@Test
+		void shouldHaveVorgaengeIgnoringWdvl() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(3, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("2")
+					.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().minus(3, ChronoUnit.DAYS))).build());
+			mongoOperations.save(VorgangTestFactory.createBuilder().id("3").build());
+
+			var request = FindVorgangRequestTestFactory.createBuilder()
+					.orderBy(OrderCriteria.EA_PRIORITY)
+					.filterBy(null)
+					.searchBy(StringUtils.EMPTY)
+					.build();
+			var vorgaenge = repository.findAll(request).getContent();
+
+			assertThat(vorgaenge).hasSize(3).extracting(VorgangHeader::getId).containsExactly("1", "2", "3");
+		}
 	}
 
 	@Nested
@@ -416,6 +534,47 @@ class VorgangHeaderRepositoryITCase {
 				assertThat(vorgangHeaderPage.getTotalPages()).isEqualTo(1);
 			}
 		}
+
+		@Nested
+		class TestVorgangWithWiedervorlagen {
+
+			@BeforeEach
+			void prepareDatabase() {
+				mongoOperations.dropCollection(Vorgang.class);
+
+				mongoOperations.save(buildWithOrganisationseinheitId(organisationseinheitenId));
+				mongoOperations.save(VorgangTestFactory.createBuilder().id(null)
+						.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(2, ChronoUnit.DAYS)))
+						.build());
+			}
+
+			@Test
+			void shouldFilterByDefaultId() {
+				var vorgangHeaderPage = repository.findAll(request);
+
+				assertThat(vorgangHeaderPage.getTotalElements()).isEqualTo(1);
+			}
+
+			@Test
+			void shouldFilterByGivenId() {
+				var filterCriteria = FilterCriteriaTestFactory.createBuilder().clearOrganisationseinheitIds()
+						.organisationseinheitId(organisationseinheitenId).build();
+				var vorgangHeaderPage = repository.findAll(createRequestWithFilterBy(filterCriteria));
+
+				assertThat(vorgangHeaderPage.getTotalElements()).isEqualTo(1);
+			}
+
+			@Test
+			void shouldHaveJustOneVorgangStatusNeu() {
+				mongoOperations.dropCollection(Vorgang.class);
+				mongoOperations.save(VorgangTestFactory.createBuilder()
+						.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(2, ChronoUnit.DAYS))).build());
+
+				var vorgangHeaderPage = repository.findAll(request);
+
+				assertThat(vorgangHeaderPage.getTotalElements()).isEqualTo(1);
+			}
+		}
 	}
 
 	@Nested
@@ -524,8 +683,10 @@ class VorgangHeaderRepositoryITCase {
 		@Nested
 		class TestAssignedTo {
 
-			private final FilterCriteria.FilterCriteriaBuilder filterCriteriaBuilder = FilterCriteria.builder()
-					.filterByOrganisationseinheitenId(false);
+			private final FilterCriteria.FilterCriteriaBuilder filterCriteriaBuilder = FilterCriteriaTestFactory.createBuilder()
+					.filterByOrganisationseinheitenId(false)
+					.clearStatus()
+					.clearOrganisationseinheitIds();
 
 			@BeforeEach
 			void initVorgaenge() {
@@ -556,7 +717,7 @@ class VorgangHeaderRepositoryITCase {
 			@DisplayName("should return an unfiltered list if there is an empty assignedTo string")
 			@Test
 			void shouldReturnUnfilteredListOnEmpty() {
-				var emptyFilterCriteria = filterCriteriaBuilder.assignedTo(StringUtils.EMPTY).build();
+				var emptyFilterCriteria = filterCriteriaBuilder.filterByAssignedTo(false).assignedTo(StringUtils.EMPTY).build();
 
 				var page = repository.findAll(createRequestWithFilterBy(emptyFilterCriteria));
 
@@ -572,6 +733,71 @@ class VorgangHeaderRepositoryITCase {
 
 				assertThat(page.getTotalElements()).isEqualTo(2);
 			}
+
+			@Test
+			void shouldReturnUnassignedVorgang() {
+				var filterCriteria = filterCriteriaBuilder.assignedTo(StringUtils.EMPTY).build();
+
+				var page = repository.findAll(createRequestWithFilterBy(filterCriteria));
+
+				assertThat(page.getTotalElements()).isEqualTo(1);
+			}
+		}
+
+		@DisplayName("Has next wiedervorlage frist")
+		@Nested
+		class TestHasNextWiedervorlageFrist {
+
+			@Test
+			void shouldHaveTotalElements() {
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+						.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(1, ChronoUnit.DAYS))).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("2").clientAttributes(null).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id(null).build());
+
+				var vorgaenge = repository.findAll(createRequestWithFilterBy(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(true).build()));
+
+				assertThat(vorgaenge.getTotalElements()).isEqualTo(1);
+			}
+
+			@Test
+			void shouldReturnWhereNextWiedervorlageExistsOnly() {
+				mongoOperations.save(VorgangTestFactory.createBuilder().id(null)
+						.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now())).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().clientAttributes(null).id(null).build());
+
+				var vorgaenge = repository.findAll(createRequestWithFilterBy(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(true).build()));
+
+				assertThat(vorgaenge.getContent()).hasSize(1);
+			}
+
+			@Nested
+			class TestWithFindVorgangQuery {
+
+				@Test
+				void shouldReturnWhereNextWiedervorlageExistsOnly() {
+					mongoOperations.save(VorgangTestFactory.createBuilder().id(null)
+							.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now())).build());
+					mongoOperations.save(VorgangTestFactory.createBuilder().clientAttributes(null).id(null).build());
+
+					var vorgaenge = repository.findAll(createFindVorgangRequest());
+
+					assertThat(vorgaenge.getContent()).hasSize(1);
+				}
+
+				private FindVorgangRequest createFindVorgangRequest() {
+					return FindVorgangRequestTestFactory.createBuilder()
+							.searchBy(StringUtils.EMPTY)
+							.findVorgangQuery(FindVorgangQuery.builder()
+									.logicalOperator(LogicalOperator.AND)
+									.operator(OperatorBuilder
+											.from(GrpcQueryOperator.EXISTS)
+											.fieldPath("ClientAttribute.Alfa.nextWiedervorlageFrist")
+											.build())
+									.build())
+							.build();
+				}
+			}
 		}
 
 		private Page<VorgangHeader> callRepositoryFindAll(FindVorgangRequest request) {
@@ -583,6 +809,17 @@ class VorgangHeaderRepositoryITCase {
 		return FindVorgangRequestTestFactory.createBuilder().searchBy(StringUtils.EMPTY).filterBy(filterBy).build();
 	}
 
+	private ClientAttributesMap createClientAttributesMapWithWiedervorlageNextFrist(LocalDate nextFrist) {
+		return ClientAttributesMapTestFactory.createWithAttribute(buildWiedervorlageNextFristClientAttribute(nextFrist));
+	}
+
+	private ClientAttribute buildWiedervorlageNextFristClientAttribute(LocalDate nextFrist) {
+		return ClientAttributeTestFactory.createBuilder()
+				.clientName(CriteriaUtil.DEFAULT_CLIENT)
+				.attributeName(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST)
+				.stringValue(Optional.of(nextFrist.toString())).build();
+	}
+
 	private Vorgang buildWithOrganisationseinheitId(String organisationseinheitenId) {
 		var eingang = buildEingangWithOrganisationseinheitenId(organisationseinheitenId);
 		return VorgangTestFactory.createBuilder().id(null).clearEingangs().eingang(eingang).build();
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImplITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImplITCase.java
similarity index 64%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImplITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImplITCase.java
index e49607b33e7a6d1b7e42b66ecf305282a8897b85..53ade4a5a69d2606c7d273d7c563db901beaa983 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImplITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImplITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+import java.util.Optional;
 import java.util.UUID;
 
 import org.apache.commons.lang3.StringUtils;
@@ -36,8 +39,13 @@ import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.Query;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.clientattribute.ClientAttribute;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeTestFactory;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMapTestFactory;
+import de.ozgcloud.vorgang.common.db.CriteriaUtil;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
 
 @DataITCase
 class VorgangHeaderRepositoryImplITCase {
@@ -68,6 +76,15 @@ class VorgangHeaderRepositoryImplITCase {
 			assertThat(countTotalVorgaenge(query)).isZero();
 		}
 
+		@Test
+		void shouldIgnoreDELETEDVorgang() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().status(Status.DELETED).build());
+
+			var query = buildFilterQuery(FilterCriteriaTestFactory.createBuilder().clearStatus().build());
+
+			assertThat(countTotalVorgaenge(query)).isZero();
+		}
+
 		@Nested
 		class TestWithOrganisationseinheitenIdFilter {
 
@@ -101,6 +118,9 @@ class VorgangHeaderRepositoryImplITCase {
 		@Nested
 		class TestWithAssignedToFilter {
 
+			private final FilterCriteria.FilterCriteriaBuilder filterCriteriaBuilder = FilterCriteriaTestFactory.createBuilder()
+					.clearStatus().clearOrganisationseinheitIds();
+
 			@BeforeEach
 			void initData() {
 				mongoOperations.save(VorgangTestFactory.createBuilder().id(null).assignedTo(USER_ID).status(Status.NEU).build());
@@ -109,14 +129,14 @@ class VorgangHeaderRepositoryImplITCase {
 
 			@Test
 			void shouldReturnTotalOnAssignedTo() {
-				var query = buildFilterQuery(FilterCriteria.builder().assignedTo(USER_ID).build());
+				var query = buildFilterQuery(filterCriteriaBuilder.assignedTo(USER_ID).build());
 
 				assertThat(countTotalVorgaenge(query)).isEqualTo(1);
 			}
 
 			@Test
 			void shouldReturnUnfilteredList() {
-				var query = buildFilterQuery(FilterCriteria.builder().assignedTo(StringUtils.EMPTY).build());
+				var query = buildFilterQuery(filterCriteriaBuilder.filterByAssignedTo(false).assignedTo(StringUtils.EMPTY).build());
 
 				assertThat(countTotalVorgaenge(query)).isEqualTo(2);
 			}
@@ -146,6 +166,42 @@ class VorgangHeaderRepositoryImplITCase {
 			}
 		}
 
+		@Nested
+		class TestWithHasNextWiedervorlageFristFilter {
+
+			@BeforeEach
+			void initData() {
+				mongoOperations.save(VorgangTestFactory.createBuilder().id("1")
+						.clientAttributes(createClientAttributesMapWithWiedervorlageNextFrist(LocalDate.now().plus(1, ChronoUnit.DAYS))).build());
+				mongoOperations.save(VorgangTestFactory.createBuilder().id(null).status(Status.NEU).build());
+			}
+
+			private ClientAttributesMap createClientAttributesMapWithWiedervorlageNextFrist(LocalDate nextFrist) {
+				return ClientAttributesMapTestFactory.createWithAttribute(buildWiedervorlageNextFristClientAttribute(nextFrist));
+			}
+
+			private ClientAttribute buildWiedervorlageNextFristClientAttribute(LocalDate nextFrist) {
+				return ClientAttributeTestFactory.createBuilder()
+						.clientName(CriteriaUtil.DEFAULT_CLIENT)
+						.attributeName(CriteriaUtil.CLIENT_ATTRIBUT_NEXT_WIEDERVORLAGE_FRIST)
+						.stringValue(Optional.of(nextFrist.toString())).build();
+			}
+
+			@Test
+			void shouldReturnTotalOnStatus() {
+				var query = buildFilterQuery(FilterCriteria.builder().hasNextWiedervorlageFrist(true).build());
+
+				assertThat(countTotalVorgaenge(query)).isEqualTo(1);
+			}
+
+			@Test
+			void shouldReturnUnfilteredList() {
+				var query = buildFilterQuery(FilterCriteria.builder().clearStatus().build());
+
+				assertThat(countTotalVorgaenge(query)).isEqualTo(2);
+			}
+		}
+
 		private Query buildFilterQuery(FilterCriteria filterCriteria) {
 			return repositoryImpl.buildFilterQuery(filterCriteria);
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImplTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImplTest.java
similarity index 94%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImplTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImplTest.java
index 9e72f011230c29d6eba836d83094d49a4e01f703..52775fb8bd843e20f741b87c0206b5821cabdf55 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderRepositoryImplTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderRepositoryImplTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderServiceTest.java
similarity index 65%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderServiceTest.java
index da5477edad404cca855baa9bebe15f2f54583b0c..67068a45ac6765952818f1aeb9346ffb72dbf5f3 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Collections;
+import java.util.Optional;
 
 import org.apache.commons.lang3.StringUtils;
 import org.junit.jupiter.api.BeforeEach;
@@ -38,12 +39,16 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 
+import de.ozgcloud.common.errorhandling.TechnicalException;
+
 class VorgangHeaderServiceTest {
 
 	@InjectMocks
+	@Spy
 	private VorgangHeaderService service;
 	@Mock
 	private VorgangHeaderRepository repository;
@@ -113,4 +118,58 @@ class VorgangHeaderServiceTest {
 					.build();
 		}
 	}
+
+	@Nested
+	class TestFindById {
+
+		@Test
+		void shouldCallRepository() {
+			service.findById(VorgangTestFactory.ID);
+
+			verify(repository).findById(VorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldReturnRepositoryResult() {
+			var repositoryResult = Optional.of(VorgangHeaderTestFactory.create());
+			when(repository.findById(VorgangTestFactory.ID)).thenReturn(repositoryResult);
+
+			var serviceResult = service.findById(VorgangTestFactory.ID);
+
+			assertThat(serviceResult).isEqualTo(repositoryResult);
+		}
+	}
+
+	@Nested
+	class TestGEtById {
+
+		@Test
+		void shouldCallFindById() {
+			doReturn(Optional.of(VorgangHeaderTestFactory.create())).when(service).findById(VorgangTestFactory.ID);
+
+			service.getById(VorgangTestFactory.ID);
+
+			verify(service).findById(VorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldReturnVorgangHeader() {
+			var expectedVorgangHeader = VorgangHeaderTestFactory.create();
+			doReturn(Optional.of(expectedVorgangHeader)).when(service).findById(VorgangTestFactory.ID);
+
+			var vorgangHeader = service.getById(VorgangTestFactory.ID);
+
+			assertThat(vorgangHeader).isEqualTo(expectedVorgangHeader);
+		}
+
+		@Test
+		@DisplayName("should throw exception if VorgangHeader could not be found")
+		void shouldThrowException() {
+			doReturn(Optional.empty()).when(service).findById(VorgangTestFactory.ID);
+
+			assertThatThrownBy(() -> service.getById(VorgangTestFactory.ID))
+					.isInstanceOf(TechnicalException.class)
+					.hasMessageContaining(VorgangTestFactory.ID + " could not be found");
+		}
+	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderTestFactory.java
similarity index 88%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderTestFactory.java
index 94bb2b3c994f305d4471d309a2f79961f3fc31aa..c3944735d2e6147d359b980cbe11e302fd15c2b9 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangHeaderTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangHeaderTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,9 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
-import static de.itvsh.ozg.pluto.vorgang.VorgangTestFactory.*;
+import static de.ozgcloud.vorgang.vorgang.VorgangTestFactory.*;
 
 public class VorgangHeaderTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangITCase.java
similarity index 62%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangITCase.java
index 76c21cafe7de674df0aafc5bad82349029926d2a..299c396a70c9c0e7e5cb27c9100928a9f2630983 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
-import java.util.List;
-
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -43,12 +41,14 @@ import org.springframework.context.annotation.Primary;
 import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.security.test.context.support.WithMockUser;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.PlutoServerApplication;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.VorgangManagerServerApplication;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoTestFactory;
 import io.grpc.stub.StreamObserver;
 
 @DataITCase
-@SpringBootTest(classes = { PlutoServerApplication.class, TestConfig.class })
+@SpringBootTest(classes = { VorgangManagerServerApplication.class, TestConfig.class })
 class VorgangITCase {
 
 	@Autowired
@@ -56,108 +56,168 @@ class VorgangITCase {
 	@Autowired
 	private MongoOperations mongoOperations;
 
+	@DisplayName("Create vorgang")
 	@Nested
 	class TestCreateVorgang {
 
-		@Mock
-		private StreamObserver<GrpcCreateVorgangResponse> responseObserver;
-		@Captor
-		private ArgumentCaptor<GrpcCreateVorgangResponse> responseCaptor;
+		@DisplayName("start creation")
+		@Nested
+		class TestStartCreation {
 
-		private final GrpcCreateVorgangRequest request = GrpcCreateVorgangRequestTestFactory.create();
+			@Mock
+			private StreamObserver<GrpcCreateVorgangResponse> responseObserver;
+			@Captor
+			private ArgumentCaptor<GrpcCreateVorgangResponse> responseCaptor;
 
-		@BeforeEach
-		void dropVorgangCollection() {
-			mongoOperations.dropCollection(Vorgang.class);
-		}
+			private final GrpcEingang eingangWithoutFiles = GrpcEingangTestFactory.createBuilder().clearAttachments().clearRepresentations().build();
+			private final GrpcCreateVorgangRequest request = GrpcCreateVorgangRequestTestFactory.createBuilder().clearEingang()
+					.setEingang(eingangWithoutFiles).build();
 
-		@Test
-		void verifyGrpcResponseMessage() {
-			var grpcResponse = doCreateVorgangServiceCall();
+			@BeforeEach
+			void dropVorgangCollection() {
+				mongoOperations.dropCollection(Vorgang.class);
+			}
 
-			assertThat(grpcResponse.getMessage()).isEqualTo("ok");
-		}
+			@Test
+			void verifyGrpcResponseMessage() {
+				var grpcResponse = doCreateVorgangServiceCall();
 
-		@Test
-		void shouldHaveEingang() {
-			doCreateVorgangServiceCall();
+				assertThat(grpcResponse.getMessage()).isEqualTo("ok");
+				assertThat(grpcResponse.getVorgangId()).isNotNull();
+			}
 
-			List<Vorgang> vorgangs = mongoOperations.findAll(Vorgang.class);
+			@Test
+			void shouldHaveEingang() {
+				doCreateVorgangServiceCall();
 
-			assertThat(vorgangs).hasSize(1);
-			assertThat(vorgangs.get(0).getEingangs()).hasSize(1);
-		}
+				var vorgaenge = mongoOperations.findAll(Vorgang.class);
 
-		@Nested
-		class TestAttachments {
+				assertThat(vorgaenge).hasSize(1).extracting(Vorgang::getEingangs).hasSize(1);
+			}
 
 			@Test
-			void numberOfAttachments() {
+			void shouldHaveNumberOfAttachments() {
 				doCreateVorgangServiceCall();
-				var eingang = getFirstEingang();
 
-				assertThat(eingang.getNumberOfAttachments()).isEqualTo(4);
+				assertThat(getFirstEingang().getNumberOfAttachments()).isEqualTo(4);
 			}
 
 			@Test
-			void numberOfAttachmentGroups() {
+			void shouldHaveNumerOfRepresentations() {
 				doCreateVorgangServiceCall();
-				var eingang = getFirstEingang();
 
-				assertThat(eingang.getAttachments()).hasSize(1);
+				assertThat(getFirstEingang().getNumberOfRepresentations()).isEqualTo(5);
 			}
 
-			@Test
-			void validateFirstAttachmentOfFirstGroup() {
-				doCreateVorgangServiceCall();
-				var eingang = getFirstEingang();
+			@DisplayName("With service konto")
+			@Nested
+			class TestWithServiceKonto {
+
+				@Test
+				void shouldHaveServiceKonto() {
+					doCreateVorgangServiceCall();
+
+					var serviceKonto = getVorgang().getHeader().getServiceKonto();
+					assertThat(serviceKonto).isNotNull();
+					assertThat(serviceKonto.getType()).isEqualTo(ServiceKontoTestFactory.TYPE);
+					assertThat(serviceKonto.getPostfachAddresses()).hasSize(1);
+				}
+
+			}
+
+			private GrpcCreateVorgangResponse doCreateVorgangServiceCall() {
+				service.startCreation(request, responseObserver);
+				verify(responseObserver).onNext(responseCaptor.capture());
 
-				assertThat(eingang.getAttachments().get(0).getFiles().get(0)).usingRecursiveComparison().isEqualTo(IncomingFileTestFactory.create());
+				return responseCaptor.getValue();
 			}
 		}
 
+		@DisplayName("finish creation")
 		@Nested
-		class TestRepresentations {
+		class TestFinishCreation {
 
-			private Eingang eingang;
+			@Mock
+			private StreamObserver<GrpcFinishCreationResponse> responseObserver;
+			@Captor
+			private ArgumentCaptor<GrpcFinishCreationResponse> responseCaptor;
 
-			@BeforeEach
-			void doCall() {
-				doCreateVorgangServiceCall();
-			}
+			private GrpcFinishCreationRequest request;
+
+			private String vorgangId;
+
+			private final Eingang eingangWithoutFiles = EingangTestFactory.createBuilder().clearAttachments().clearRepresentations().build();
+			private final Vorgang vorgang = VorgangTestFactory.createBuilder().clearEingangs().eingang(eingangWithoutFiles)
+					.clientAttributes(new ClientAttributesMap()).build();
 
 			@BeforeEach
-			void getEingang() {
-				eingang = getFirstEingang();
+			void init() {
+				mongoOperations.dropCollection(Vorgang.class);
+				vorgangId = mongoOperations.save(vorgang).getId();
+				request = GrpcFinishCreationRequestTestFactory.createBuilder().setVorgangId(vorgangId).build();
 			}
 
 			@Test
-			void shouldHaveRepresentations() {
-				assertThat(eingang.getRepresentations()).hasSize(1);
+			void verifyGrpcResponseMessage() {
+				var grpcResponse = doCreateVorgangServiceCall();
+
+				assertThat(grpcResponse.getMessage()).isEqualTo("ok");
 			}
 
-			@Test
-			void shouldHaveNumerOfRepresentations() {
-				assertThat(eingang.getNumberOfRepresentations()).isEqualTo(5);
+			@DisplayName("attachments")
+			@Nested
+			class TestAttachments {
+
+				@Test
+				void shouldExists() {
+					doCreateVorgangServiceCall();
+
+					assertThat(getFirstEingang().getAttachments()).hasSize(1);
+				}
+
+				@Test
+				void shouldHaveFile() {
+					doCreateVorgangServiceCall();
+
+					var attachment = getFirstEingang().getAttachments().get(0).getFiles().get(0);
+					assertThat(attachment).usingRecursiveComparison().isEqualTo(IncomingFileTestFactory.create());
+				}
 			}
 
-			@Test
-			void shouldHaveIncomingFile() {
-				IncomingFile incomingFile = eingang.getRepresentations().get(0);
+			@DisplayName("representations")
+			@Nested
+			class TestRepresentations {
+
+				@Test
+				void shouldExists() {
+					doCreateVorgangServiceCall();
 
-				assertThat(incomingFile).usingRecursiveComparison().isEqualTo(IncomingFileTestFactory.create());
+					assertThat(getFirstEingang().getRepresentations()).hasSize(1);
+				}
+
+				@Test
+				void shouldHaveFile() {
+					doCreateVorgangServiceCall();
+
+					var representation = getFirstEingang().getRepresentations().get(0);
+					assertThat(representation).usingRecursiveComparison().isEqualTo(IncomingFileTestFactory.create());
+				}
+			}
+
+			private GrpcFinishCreationResponse doCreateVorgangServiceCall() {
+				service.finishCreation(request, responseObserver);
+				verify(responseObserver).onNext(responseCaptor.capture());
+
+				return responseCaptor.getValue();
 			}
 		}
 
 		private Eingang getFirstEingang() {
-			return mongoOperations.findAll(Vorgang.class).get(0).getEingangs().get(0);
+			return getVorgang().getEingangs().get(0);
 		}
 
-		private GrpcCreateVorgangResponse doCreateVorgangServiceCall() {
-			service.createVorgang(request, responseObserver);
-			verify(responseObserver).onNext(responseCaptor.capture());
-
-			return responseCaptor.getValue();
+		private Vorgang getVorgang() {
+			return mongoOperations.findAll(Vorgang.class).get(0);
 		}
 	}
 
@@ -321,7 +381,7 @@ class VorgangITCase {
 class TestConfig {
 	@Bean
 	@Primary
-	public ApplicationEventPublisher mockEventPublisher() {
+	ApplicationEventPublisher mockEventPublisher() {
 		return mock(ApplicationEventPublisher.class);
 	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangRepositoryITCase.java
similarity index 62%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangRepositoryITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangRepositoryITCase.java
index 860719b9c5b1ec23428586ac9a0667c0e1efc12a..f1322372a8549d13f56ecf42e3e617665f45e37a 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangRepositoryITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
 
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.Collections;
+import java.util.ConcurrentModificationException;
 import java.util.List;
 import java.util.Map;
 import java.util.TimeZone;
@@ -39,8 +41,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.common.test.DataITCase;
 
 @DataITCase
 class VorgangRepositoryITCase {
@@ -109,7 +110,7 @@ class VorgangRepositoryITCase {
 		}
 
 		@Test
-		void shouldContainCorretTime() {
+		void shouldContainCorrectTime() {
 			var persisted = repository
 					.save(VorgangTestFactory.createBuilder().id(null).createdAt(ZonedDateTime.parse("2021-01-01T10:00:00+05:00")).build());
 
@@ -119,6 +120,13 @@ class VorgangRepositoryITCase {
 			assertThat(loaded.getCreatedAt().format(DateTimeFormatter.ISO_DATE_TIME)).hasToString("2021-01-01T05:00:00Z");
 		}
 
+		@Test
+		void shouldNotLoadDeletedVorgang() {
+			mongoOperations.save(VorgangStubTestFactory.create());
+
+			assertThat(repository.findById(VorgangTestFactory.ID)).isEmpty();
+		}
+
 		@Nested
 		class TestLoadVorgangWithEingangSubForm {
 
@@ -155,7 +163,7 @@ class VorgangRepositoryITCase {
 
 				assertThat(loaded).isPresent();
 				var fieldValue = loaded.get().getEingangs().get(0).getFormData().get(EingangTestFactory.SINGLE_FIELD_NAME);
-				assertThat(fieldValue).isEqualTo(EingangTestFactory.SINGLE_FIELD_VALUE);
+				assertThat(fieldValue).isEqualTo(EingangTestFactory.SINGLE_FIELD);
 			}
 
 			@Test
@@ -173,7 +181,6 @@ class VorgangRepositoryITCase {
 
 		@BeforeEach
 		void persistVorgang() {
-			mongoOperations.dropCollection(Vorgang.class);
 			mongoOperations.save(VorgangTestFactory.create());
 		}
 
@@ -191,8 +198,6 @@ class VorgangRepositoryITCase {
 
 		@BeforeEach
 		void init() {
-			mongoOperations.dropCollection(Vorgang.class);
-
 			repository.save(VorgangTestFactory.create());
 		}
 
@@ -206,20 +211,33 @@ class VorgangRepositoryITCase {
 	}
 
 	@Nested
-	class TestUpdateStatus {
-
-		@BeforeEach
-		void init() {
-			mongoOperations.dropCollection(Vorgang.class);
+	class TestFindAll {
 
+		@Test
+		void shouldFindVorgang() {
 			mongoOperations.save(VorgangTestFactory.create());
+
+			var all = repository.findAll();
+
+			assertThat(all).hasSize(1);
 		}
 
 		@Test
-		void shouldLoadVorgang() {
-			repository.updateStatus(VorgangTestFactory.ID, VorgangTestFactory.VERSION, Status.IN_BEARBEITUNG);
+		void shouldNotFindVorgangInCreation() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().inCreation(true).build());
+
+			var all = repository.findAll();
 
-			assertThat(mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class).getStatus()).isEqualTo(Status.IN_BEARBEITUNG);
+			assertThat(all).isEmpty();
+		}
+
+		@Test
+		void shouldNotFindDELETEDVorgang() {
+			mongoOperations.save(VorgangStubTestFactory.create());
+
+			var all = repository.findAll();
+
+			assertThat(all).isEmpty();
 		}
 	}
 
@@ -235,29 +253,111 @@ class VorgangRepositoryITCase {
 			mongoOperations.save(VorgangTestFactory.createBuilder().id(null).build());
 		}
 
+		@Test
+		void shouldNotExistsDELETEDVorgang() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().status(Vorgang.Status.DELETED).build());
+
+			var exists = repository.exists(VorgangTestFactory.ID, Collections.singleton(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+
+			assertThat(exists).isFalse();
+		}
+
 		@Nested
 		class ByOrganisationEinheitenId {
 
 			@Test
 			void shouldReturnTrueOnMatch() {
-				var isPermitted = repository.exists(VorgangTestFactory.ID, List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
+				var exists = repository.exists(VorgangTestFactory.ID, List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID));
 
-				assertThat(isPermitted).isTrue();
+				assertThat(exists).isTrue();
 			}
 
 			@Test
 			void shouldReturnFalseOnNoMatch() {
-				var isPermitted = repository.exists(VorgangTestFactory.ID, List.of("quatsch"));
+				var exists = repository.exists(VorgangTestFactory.ID, List.of("quatsch"));
 
-				assertThat(isPermitted).isFalse();
+				assertThat(exists).isFalse();
 			}
 
 			@Test
 			void shouldReturnFalseOnEmptyList() {
-				var isPermitted = repository.exists(VorgangTestFactory.ID, Collections.emptyList());
+				var exists = repository.exists(VorgangTestFactory.ID, Collections.emptyList());
 
-				assertThat(isPermitted).isFalse();
+				assertThat(exists).isFalse();
 			}
 		}
 	}
+
+	@Nested
+	class TestSaveStub {
+		@BeforeEach
+		void clearCollection() {
+			mongoOperations.dropCollection(Vorgang.COLLECTION_NAME);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Test
+		void shouldOverwriteVorgang() {
+			mongoOperations.save(VorgangTestFactory.create());
+
+			repository.saveStub(VorgangStubTestFactory.create());
+
+			Map<String, Object> loaded = mongoOperations.findById(VorgangTestFactory.ID, Map.class, Vorgang.COLLECTION_NAME);
+			assertThat(loaded).hasSize(7);
+		}
+
+	}
+
+	@Nested
+	class TestSetAktenzeichen {
+
+		@Test
+		void shouldSetAktenzeichen() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().aktenzeichen(null).build());
+
+			repository.setAktenzeichen(VorgangTestFactory.ID, VorgangTestFactory.VERSION, VorgangTestFactory.AKTENZEICHEN);
+
+			assertThat(getVorgang().getAktenzeichen()).isEqualTo(VorgangTestFactory.AKTENZEICHEN);
+		}
+
+		@Test
+		void shouldUpdateAktenzeichen() {
+			mongoOperations.save(VorgangTestFactory.create());
+			var newAktenzeichen = "newAktenzeichen";
+
+			repository.setAktenzeichen(VorgangTestFactory.ID, VorgangTestFactory.VERSION, newAktenzeichen);
+
+			assertThat(getVorgang().getAktenzeichen()).isEqualTo(newAktenzeichen);
+		}
+
+		@Test
+		void shouldResetAktenzeichen() {
+			mongoOperations.save(VorgangTestFactory.create());
+
+			repository.setAktenzeichen(VorgangTestFactory.ID, VorgangTestFactory.VERSION, null);
+
+			assertThat(getVorgang().getAktenzeichen()).isNull();
+		}
+
+		@Test
+		void  should() {
+			assertThat(mongoOperations.findAll(Vorgang.class)).isEmpty();
+
+			repository.setAktenzeichen(VorgangTestFactory.ID, VorgangTestFactory.VERSION, VorgangTestFactory.AKTENZEICHEN);
+
+			assertThat(getVorgang()).isNull();
+		}
+
+		@Test
+		void shouldThrowExceptionByCollision() {
+			mongoOperations.save(VorgangTestFactory.createBuilder().aktenzeichen(null).build());
+
+			assertThrows(ConcurrentModificationException.class,
+					() -> repository.setAktenzeichen(VorgangTestFactory.ID, VorgangTestFactory.VERSION + 1, VorgangTestFactory.AKTENZEICHEN));
+		}
+
+		private Vorgang getVorgang() {
+			return mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
+		}
+	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..d99e59163cd05d4b05ec62df0f31bff4c490f3a7
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceITCase.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.security.test.context.support.WithMockUser;
+
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.notification.antragsteller.AntragstellerNotificationEventListener;
+import de.ozgcloud.notification.user.UserNotificationEventListener;
+import de.ozgcloud.vorgang.command.CommandService;
+
+@DataITCase
+@WithMockUser
+class VorgangServiceITCase {
+
+	@Autowired
+	private VorgangService vorgangService;
+
+	@MockBean
+	private CommandService commandService;
+
+	@MockBean
+	private AntragstellerNotificationEventListener antragstellerNotificationEventListener;
+
+	@MockBean
+	private UserNotificationEventListener userNotificationEventListener;
+
+	@DisplayName("Test creating a new Vorgang")
+	@Nested
+	class TestVorgangCreation {
+		@Test
+		void shouldStartCreateVorgang() {
+			var vorgang = vorgangService.startCreation(EingangTestFactory.create());
+
+			assertThat(vorgang.getId()).isNotNull();
+			assertThat(vorgang.isInCreation()).isTrue();
+		}
+
+		@Test
+		void shouldFinishCreateVorgang() {
+			var vorgang = vorgangService.startCreation(EingangTestFactory.create());
+
+			vorgangService.finishCreation(vorgang.getId(), List.of(), List.of());
+
+			vorgang = vorgangService.getById(vorgang.getId());
+
+			assertThat(vorgang.isInCreation()).isFalse();
+			verify(antragstellerNotificationEventListener).onVorgangCreated(any());
+			verify(userNotificationEventListener).onVorgangCreated(any());
+		}
+	}
+}
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
similarity index 58%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
index 2e49d3d72b158337a2e737a0d1344dc88458fe82..f2e5e98764d519de54b606dc0598409fa839f7a2 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.*;
@@ -42,17 +42,15 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 import org.springframework.context.ApplicationEventPublisher;
-import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.security.access.AccessDeniedException;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributeReadPermitted;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.command.VorgangCreatedEvent;
-import de.itvsh.ozg.pluto.common.errorhandling.NotFoundException;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.redirect.ForwardingService;
-import de.itvsh.ozg.pluto.vorgang.redirect.ForwardingTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.VorgangCreatedEvent;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoTestFactory;
+import de.ozgcloud.vorgang.vorgang.redirect.ForwardingService;
 
 class VorgangServiceTest {
 
@@ -64,129 +62,102 @@ class VorgangServiceTest {
 	private VorgangRepository repository;
 	@Mock
 	private ForwardingService redirectService;
-	@Mock
-	private MongoOperations mongoOperations;
+
 	@Mock
 	private ApplicationEventPublisher publisher;
 	@Mock
 	private AktenzeichenProvider aktenzeichenProvider;
 	@Mock
 	private VorgangAuthorizationService vorgangAuthorizationService;
-
 	@Mock
 	private ClientAttributeReadPermitted readIsPermitted;
 
 	@Captor
 	private ArgumentCaptor<Vorgang> vorgangCaptor;
 
-	@Deprecated
-	@Nested
-	class TestCreateVorgang {
+	@Mock
+	private LabelProcessor kopControlDataMapper;
 
-		@Captor
-		private ArgumentCaptor<VorgangCreatedEvent> eventCaptor;
+	@Mock
+	private VorgangStubMapper stubMapper;
+
+	@DisplayName("Start creation")
+	@Nested
+	class TestStartCreation {
 
 		private final Eingang eingang = EingangTestFactory.create();
+		private static final String VORGANG_NUMMER = "TEST_VN";
 
 		@BeforeEach
-		void init() {
-			when(repository.save(any())).thenReturn(VorgangTestFactory.create());
-		}
-
-		@Test
-		void shouldFillVorgangData() {
-			callCreateVorgang();
+		void mockAktenzeichenProvider() {
+			when(aktenzeichenProvider.provideAktenzeichen(any())).thenReturn(VorgangTestFactory.AKTENZEICHEN);
 
-			verify(repository).save(vorgangCaptor.capture());
-			assertThat(vorgangCaptor.getValue().getName()).isEqualTo(EingangHeaderTestFactory.FORM_NAME);
-			assertThat(vorgangCaptor.getValue().getStatus()).isEqualTo(Vorgang.Status.NEU);
+			when(kopControlDataMapper.moveLabelsToControlData(any(Eingang.class))).then(v -> v.getArgument(0));
 		}
 
 		@Test
-		void shouldKeepEingangInVorgang() {
-			callCreateVorgang();
+		void shouldSetName() {
+			var created = callStartCreation();
 
-			verify(repository).save(vorgangCaptor.capture());
-			assertThat(vorgangCaptor.getValue().getEingangs().get(0).getId()).isEqualTo(EingangTestFactory.ID);
+			assertThat(created.getName()).isEqualTo(EingangHeaderTestFactory.FORM_NAME);
 		}
 
 		@Test
-		void shouldCallAktenzeichenProvider() {
-			callCreateVorgang();
+		void shouldSetStatus() {
+			var created = callStartCreation();
 
-			verify(aktenzeichenProvider).provideAktenzeichen(eingang);
+			assertThat(created.getStatus()).isEqualTo(Vorgang.Status.NEU);
 		}
 
 		@Test
 		void shouldSetVorgangNummer() {
-			callCreateVorgang();
+			doReturn(VORGANG_NUMMER).when(service).getVorgangNummer(any());
 
-			verify(repository).save(vorgangCaptor.capture());
-			assertThat(vorgangCaptor.getValue().getNummer()).isEqualTo(EingangHeaderTestFactory.REQUEST_ID);
-		}
-
-		@Test
-		void shouldSetInCreationFalse() {
-			callCreateVorgang();
+			var created = callStartCreation();
 
-			verify(repository).save(vorgangCaptor.capture());
-			assertThat(vorgangCaptor.getValue().isInCreation()).isFalse();
+			assertThat(created.getNummer()).isEqualTo(VORGANG_NUMMER);
 		}
 
+		@DisplayName("eingang on vorgang")
 		@Nested
-		class TestPublishVorgangCreateEvent {
+		class TestEingang {
 
 			@Test
-			void shouldPublishOnInCreationFalse() {
-				callCreateVorgang();
+			void shouldHaveFields() {
+				var created = callStartCreation();
 
-				verify(publisher).publishEvent(eventCaptor.capture());
-				assertThat(eventCaptor.getValue()).isInstanceOf(VorgangCreatedEvent.class)
-						.extracting(VorgangCreatedEvent::getSource).isEqualTo(VorgangTestFactory.ID);
+				assertThat(created.getEingangs().get(0)).usingRecursiveComparison().isEqualTo(eingang);
 			}
-		}
-
-		private void callCreateVorgang() {
-			service.createVorgang(eingang);
-		}
-	}
-
-	@Nested
-	class TestStartCreation {
-
-		private final Eingang eingang = EingangTestFactory.create();
-
-		@BeforeEach
-		void mockAktenzeichenProvider() {
-			when(aktenzeichenProvider.provideAktenzeichen(any())).thenReturn(VorgangTestFactory.AKTENZEICHEN);
-		}
 
-		@Test
-		void shouldSetName() {
-			var created = callStartCreation();
+			@DisplayName("with existing serviceKonto")
+			@Nested
+			class TestWithExistingServiceKonto {
 
-			assertThat(created.getName()).isEqualTo(EingangHeaderTestFactory.FORM_NAME);
-		}
+				@Test
+				void shouldHaveServiceKonto() {
+					var vorgang = callStartCreation();
 
-		@Test
-		void shouldSetStatus() {
-			var created = callStartCreation();
+					assertThat(vorgang.getHeader().getServiceKonto()).usingRecursiveComparison().isEqualTo(ServiceKontoTestFactory.create());
+				}
+			}
 
-			assertThat(created.getStatus()).isEqualTo(Vorgang.Status.NEU);
-		}
+			@DisplayName("without serviceKonto")
+			@Nested
+			class TestWithoutServiceKonto {
 
-		@Test
-		void shouldSetVorgangNummer() {
-			var created = callStartCreation();
+				private static final EingangHeader EINGANG_HEADER_WITHOUT_SERVICE_KONTO = EingangHeaderTestFactory.createBuilder().serviceKonto(null)
+						.build();
+				private static final Eingang EINGANG_WITHOUT_SERVICE_KONTO = EingangTestFactory.createBuilder()
+						.header(EINGANG_HEADER_WITHOUT_SERVICE_KONTO).build();
 
-			assertThat(created.getNummer()).isEqualTo(EingangHeaderTestFactory.REQUEST_ID);
-		}
+				@Test
+				void shouldNotHaveServiceKonto() {
+					var vorgang = callStartCreation(EINGANG_WITHOUT_SERVICE_KONTO);
 
-		@Test
-		void shouldSaveEingangOnVorgang() {
-			var created = callStartCreation();
+					assertThat(vorgang.getHeader().getServiceKonto()).isNull();
+				}
+			}
 
-			assertThat(created.getEingangs().get(0)).usingRecursiveComparison().isEqualTo(eingang);
 		}
 
 		@Test
@@ -218,6 +189,10 @@ class VorgangServiceTest {
 		}
 
 		private Vorgang callStartCreation() {
+			return callStartCreation(eingang);
+		}
+
+		private Vorgang callStartCreation(Eingang eingang) {
 			service.startCreation(eingang);
 
 			verify(repository).save(vorgangCaptor.capture());
@@ -226,6 +201,26 @@ class VorgangServiceTest {
 		}
 	}
 
+	@Nested
+	class getVorgangNummer {
+		@Test
+		void shouldReturnGivenNummer() {
+			var result = service.getVorgangNummer(EingangHeaderTestFactory.create());
+
+			assertThat(result).isEqualTo(EingangHeaderTestFactory.VORGANG_NUMMER);
+		}
+
+		@Test
+		void shouldReturnRequestId() {
+			var header = EingangHeaderTestFactory.createBuilder().vorgangNummer(null).build();
+
+			var result = service.getVorgangNummer(header);
+
+			assertThat(result).isEqualTo(EingangHeaderTestFactory.REQUEST_ID);
+		}
+	}
+
+	@DisplayName("Finish creation")
 	@Nested
 	class TestFinishCreation {
 
@@ -289,6 +284,21 @@ class VorgangServiceTest {
 		}
 	}
 
+	@Nested
+	class TestVorgangNotFound {
+		@BeforeEach
+		void mockRepository() {
+			when(repository.findById(anyString())).thenReturn(Optional.of(VorgangTestFactory.create()));
+		}
+
+		@Test
+		void shouldThrowException() {
+			when(repository.findById(anyString())).thenReturn(Optional.empty());
+
+			assertThrows(NotFoundException.class, () -> service.getById(VorgangTestFactory.ID));
+		}
+	}
+
 	@Nested
 	class TestGetById {
 
@@ -300,11 +310,18 @@ class VorgangServiceTest {
 		@BeforeEach
 		void mockRepository() {
 			when(repository.findById(anyString())).thenReturn(Optional.of(VorgangTestFactory.create()));
+
+			when(kopControlDataMapper.addLabels(any(Eingang.class))).then(v -> v.getArgument(0));
 		}
 
 		@Nested
 		class AndOrganisationseinheitenIds {
 
+			@BeforeEach
+			void mockAttributeUtilService() {
+				when(readIsPermitted.test(any())).thenReturn(true);
+			}
+
 			@Test
 			void shouldCallFindById() {
 				service.getById(VorgangTestFactory.ID);
@@ -341,14 +358,6 @@ class VorgangServiceTest {
 			assertThat(vorgang).isNotNull().usingRecursiveComparison().isEqualTo(VorgangTestFactory.create());
 		}
 
-		@Test
-		void shouldThrowException() {
-			lenient().when(readIsPermitted.test(any())).thenReturn(true);
-			when(repository.findById(anyString())).thenReturn(Optional.empty());
-
-			assertThrows(NotFoundException.class, () -> service.getById(VorgangTestFactory.ID));
-		}
-
 		@Test
 		void shouldRemoveClientAttributesWithoutReadPermission() {
 			when(readIsPermitted.test(any())).thenReturn(false);
@@ -360,8 +369,6 @@ class VorgangServiceTest {
 
 		@Test
 		void shouldContainClientAttributesWithReadPermission() {
-			when(readIsPermitted.test(any())).thenReturn(true);
-
 			var loaded = service.getById(VorgangTestFactory.ID);
 
 			assertThat(loaded.getClientAttributes()).isNotEmpty();
@@ -369,174 +376,93 @@ class VorgangServiceTest {
 	}
 
 	@Nested
-	class TestVorgangStatusChange {
-
-		private Command command = CommandTestFactory.create();
-
-		@BeforeEach
-		void mockRepository() {
-			when(repository.findById(any())).thenReturn(Optional.of(VorgangTestFactory.create()));
-		}
-
-		@Nested
-		class TestExecuteStatusChangeCommand {
-
-			@Captor
-			private ArgumentCaptor<StatusChangedEvent> eventCaptor;
-
-			@Test
-			void shouldUpdateStatus() {
-				doServiceCall();
-
-				verifyServiceCall(Status.ANGENOMMEN);
-			}
-
-			@Test
-			void shouldCallRepository() {
-				doServiceCall();
-
-				verify(repository).findById(CommandTestFactory.RELATION_ID);
-			}
-
-			@Test
-			void shouldPublishExecutedEvent() {
-				doServiceCall();
-
-				verify(publisher).publishEvent(eventCaptor.capture());
-				assertThat(eventCaptor.getValue()).isInstanceOf(StatusChangedEvent.class)
-						.extracting(StatusChangedEvent::getSource).isSameAs(CommandTestFactory.ID);
-			}
+	class TestAssignToUser {
 
-			private void doServiceCall() {
-				service.executeStatusChangeCommand(command, Status.ANGENOMMEN);
-			}
-		}
+		private Command command = CommandTestFactory.createBuilder().body(Map.of("assignedTo", "Klaus")).build();
 
-		@DisplayName("should update vorgang by the given status 'ANGENOMMEN")
 		@Test
-		void shouldUpdateByStatusAngenommen() {
-			service.annehmen(command);
+		void shouldCallRepository() {
+			service.assignToUser(command);
 
-			verifyServiceCall(Status.ANGENOMMEN);
+			verify(repository).patch(CommandTestFactory.RELATION_ID, VorgangTestFactory.VERSION, Map.of("assignedTo", "Klaus"));
 		}
 
-		@DisplayName("should update vorgang by the given status 'VERWORFEN")
 		@Test
-		void shouldUpdateByStatusVerworfen() {
-			service.verwerfen(command);
+		void shouldPublishEvent() {
+			service.assignToUser(command);
 
-			verifyServiceCall(Status.VERWORFEN);
+			verify(publisher).publishEvent(any(VorgangAssignedEvent.class));
 		}
+	}
 
-		@DisplayName("should update vorgang by the given status 'IN_BEARBEITUNG")
-		@Test
-		void shouldUpdateByStatusBearbeiten() {
-			service.bearbeiten(command);
+	@DisplayName("Exists")
+	@Nested
+	class TestExists {
 
-			verifyServiceCall(Status.IN_BEARBEITUNG);
-		}
+		private final List<String> organisationseinheitenIds = List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
 
-		@DisplayName("should update vorgang by the given status 'BESCHIEDEN")
 		@Test
-		void shouldUpdateByStatusBeschieden() {
-			service.bescheiden(command);
+		void shouldCallRepository() {
+			service.exists(VorgangTestFactory.ID, organisationseinheitenIds);
 
-			verifyServiceCall(Status.BESCHIEDEN);
+			verify(repository).exists(VorgangTestFactory.ID, organisationseinheitenIds);
 		}
+	}
 
-		@DisplayName("should update vorgang by the given status 'ABGESCHLOSSEN")
-		@Test
-		void shouldUpdateByStatusAbgeschlossen() {
-			service.abschliessen(command);
-
-			verifyServiceCall(Status.ABGESCHLOSSEN);
-		}
+	@Nested
+	class TestDeleteVorgang {
 
-		@DisplayName("should update status to 'WEITERGELEITET'")
-		@Test
-		void shouldUpdateToWeitergeleitet() {
-			service.setStatusToWeitergeleitet(ForwardingTestFactory.create());
+		private Vorgang vorgang = VorgangTestFactory.create();
+		private VorgangStub stub = VorgangStubTestFactory.create();
 
-			verify(repository).updateStatusWithoutVersionCheck(VorgangTestFactory.ID, Status.WEITERGELEITET);
+		@BeforeEach
+		void init() {
+			when(repository.findById(any())).thenReturn(Optional.of(vorgang));
+			when(stubMapper.fromVorgang(any())).thenReturn(stub);
 		}
 
-		@Nested
-		class TestSetStatusToInBearbeitung {
-
-			@Test
-			void shouldUpdateStatusWithoutVersionCheck() {
-				service.setStatusToInBearbeitung(CommandTestFactory.ID, VorgangTestFactory.ID);
-
-				verify(repository).updateStatusWithoutVersionCheck(VorgangTestFactory.ID, Status.IN_BEARBEITUNG);
-			}
-
-			@Test
-			void shouldPublishEvent() {
-				service.setStatusToInBearbeitung(CommandTestFactory.ID, VorgangTestFactory.ID);
-
-				verify(publisher).publishEvent(any(StatusChangedEvent.class));
-			}
-
-			@Test
-			void shouldCallFindById() {
-				service.setStatusToInBearbeitung(CommandTestFactory.ID, VorgangTestFactory.ID);
-
-				verify(repository).findById(VorgangTestFactory.ID);
-			}
-		}
+		@Test
+		void shouldLoadVorgang() {
+			service.deleteVorgang(VorgangTestFactory.ID);
 
-		private void verifyServiceCall(Status status) {
-			verify(service).executeStatusChangeCommand(command, status);
+			verify(service).loadById(VorgangTestFactory.ID);
 		}
-	}
 
-	@Nested
-	class TestRevokeStatusChange {
+		@Test
+		void shouldMapToStub() {
+			service.deleteVorgang(VorgangTestFactory.ID);
 
-		@BeforeEach
-		void mockRepository() {
-			when(repository.findById(any())).thenReturn(Optional.of(VorgangTestFactory.create()));
+			verify(stubMapper).fromVorgang(vorgang);
 		}
 
 		@Test
-		void shouldRevindToOldStatus() {
-			service.revokeStatusChange(CommandTestFactory.create());
+		void shouldPersistStub() {
+			service.deleteVorgang(VorgangTestFactory.ID);
 
-			verify(service).doUpdateStatus(CommandTestFactory.RELATION_ID, CommandTestFactory.RELATION_VERSION + 1, CommandTestFactory.PREV_STATUS);
+			verify(repository).saveStub(stub);
 		}
 	}
 
 	@Nested
-	class TestAssignToUser {
-
-		private Command command = CommandTestFactory.createBuilder().body(Map.of("assignedTo", "Klaus")).build();
+	class TestSetAktenzeichen {
 
 		@Test
 		void shouldCallRepository() {
-			service.assignToUser(command);
+			var command = CommandTestFactory.createBuilder()
+					.bodyObject(Map.of(VorgangService.BODY_OBJECT_AKTENZEICHEN, VorgangTestFactory.AKTENZEICHEN)).build();
 
-			verify(repository).patch(CommandTestFactory.RELATION_ID, VorgangTestFactory.VERSION, Map.of("assignedTo", "Klaus"));
-		}
-
-		@Test
-		void shouldPublishEvent() {
-			service.assignToUser(command);
+			service.setAktenzeichen(command);
 
-			verify(publisher).publishEvent(any(VorgangAssignedEvent.class));
+			verify(repository).setAktenzeichen(VorgangTestFactory.ID, CommandTestFactory.RELATION_VERSION, VorgangTestFactory.AKTENZEICHEN);
 		}
-	}
-
-	@DisplayName("Exists")
-	@Nested
-	class TestExists {
-
-		private final List<String> organisationseinheitenIds = List.of(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID);
 
 		@Test
-		void shouldCallRepository() {
-			service.exists(VorgangTestFactory.ID, organisationseinheitenIds);
+		void shouldTrimEmptyStringToNull() {
+			var command = CommandTestFactory.createBuilder().bodyObject(Map.of(VorgangService.BODY_OBJECT_AKTENZEICHEN, "")).build();
 
-			verify(repository).exists(VorgangTestFactory.ID, organisationseinheitenIds);
+			service.setAktenzeichen(command);
+
+			verify(repository).setAktenzeichen(VorgangTestFactory.ID, CommandTestFactory.RELATION_VERSION, null);
 		}
 	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangStubMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangStubMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..bcc9e1f95ceff8363dcbfcedd332371fffba4b8c
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangStubMapperTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.InjectMocks;
+
+class VorgangStubMapperTest {
+
+	@InjectMocks
+	private VorgangStubMapper mapper = Mappers.getMapper(VorgangStubMapper.class);
+
+	@Nested
+	class TestFormVorgang {
+		@Test
+		void shouldMapFields() {
+			var stub = mapper.fromVorgang(VorgangTestFactory.create());
+
+			assertThat(stub).usingRecursiveComparison()
+					.ignoringFields("deletedAt", "status")
+					.isEqualTo(VorgangStubTestFactory.create());
+		}
+
+		@Test
+		void shouldHaveStatusDELETED() {
+			var stub = mapper.fromVorgang(VorgangTestFactory.create());
+
+			assertThat(stub.getStatus()).isEqualTo(Vorgang.Status.DELETED);
+		}
+
+		@Test
+		void shouldHaveDeletedAtOnNow() {
+			var stub = mapper.fromVorgang(VorgangTestFactory.create());
+
+			assertThat(stub.getDeletedAt()).isCloseTo(ZonedDateTime.now(), byLessThan(500, ChronoUnit.MILLIS));
+		}
+	}
+
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangStubTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangStubTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..41fe721521e90fdeed58b7736c28a5a75e5467a9
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangStubTestFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+public class VorgangStubTestFactory {
+
+	public static VorgangStub create() {
+		return createBuilder().build();
+	}
+
+	public static VorgangStub.VorgangStubBuilder createBuilder() {
+		return VorgangStub.builder()
+				.id(VorgangTestFactory.ID)
+				.name(VorgangTestFactory.NAME)
+				.createdAt(VorgangTestFactory.CREATED_AT)
+				.header(VorgangHeadStub.builder().organisationsEinheitId(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID).build())
+				.eingangs(EingangStub.builder().zustaendigeStelle(ZustaendigeStelleStub.builder()
+						.organisationseinheitenId(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID).build()).build());
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangTestFactory.java
similarity index 81%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangTestFactory.java
index 310917a13291294e76eba485721b8a94138781d3..512d07542793571bd2d6506ef3259cd6ac77702b 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import java.time.ZonedDateTime;
 
@@ -29,10 +29,10 @@ import org.bson.types.ObjectId;
 
 import com.thedeanda.lorem.LoremIpsum;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributesMap;
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributesMapTestFactory;
-import de.itvsh.ozg.pluto.command.UserTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.callcontext.UserTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributesMapTestFactory;
 
 public class VorgangTestFactory {
 
@@ -40,8 +40,12 @@ public class VorgangTestFactory {
 	public static final String NAME = LoremIpsum.getInstance().getName();
 	public static final long VERSION = 42L;
 	public static final Status STATUS = Status.NEU;
-	public static final String INITIAL_DATE_STR = "2021-01-10T10:30:00Z";
+
+	public static final String INITIAL_DATE = "2021-01-10";
+	public static final String INITIAL_TIME = "10:30:00";
+	public static final String INITIAL_DATE_STR = "%sT%sZ".formatted(INITIAL_DATE, INITIAL_TIME);
 	public static final ZonedDateTime CREATED_AT = ZonedDateTime.parse(INITIAL_DATE_STR);
+
 	public static final String VORGANG_NUMMER = "VOR-GANG-NUMMER-1";
 	public static final String AKTENZEICHEN = LoremIpsum.getInstance().getWords(1);
 	public static final boolean IN_CREATION = false;
@@ -71,6 +75,7 @@ public class VorgangTestFactory {
 				.nummer(VORGANG_NUMMER)
 				.status(STATUS)
 				.createdAt(CREATED_AT)
+				.header(VorgangHeadTestFactory.create())
 				.eingang(EINGANG)
 				.version(VERSION)
 				.assignedTo(UserTestFactory.ID)
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangWithEingangMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangWithEingangMapperTest.java
similarity index 76%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangWithEingangMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangWithEingangMapperTest.java
index bbb333208821a7a03d57885580049383dcc4cb3b..70de3f8f3d1a9ed07fb25ac83979fa54d5512607 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangWithEingangMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangWithEingangMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -34,7 +34,9 @@ import org.mapstruct.factory.Mappers;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.ozg.pluto.clientattribute.ClientAttributeMapper;
+import de.ozgcloud.vorgang.clientattribute.ClientAttributeMapper;
+import de.ozgcloud.vorgang.servicekonto.GrpcServiceKontoTestFactory;
+import de.ozgcloud.vorgang.servicekonto.ServiceKontoMapper;
 
 class VorgangWithEingangMapperTest {
 
@@ -44,6 +46,8 @@ class VorgangWithEingangMapperTest {
 	private EingangMapper eingangMapper;
 	@Mock
 	private ClientAttributeMapper clientAttributeMapper;
+	@Mock
+	private ServiceKontoMapper serviceKontoMapper;
 
 	@Nested
 	class TestToVorgangWithEingang {
@@ -51,6 +55,7 @@ class VorgangWithEingangMapperTest {
 		@BeforeEach
 		void mockEingangMapper() {
 			when(eingangMapper.toGrpc(any(Eingang.class))).thenReturn(GrpcEingangTestFactory.create());
+			when(serviceKontoMapper.toServiceKonto(any())).thenReturn(GrpcServiceKontoTestFactory.create());
 		}
 
 		@Test
@@ -65,7 +70,7 @@ class VorgangWithEingangMapperTest {
 			var vorgangWithEingang = callMapper();
 
 			assertThat(vorgangWithEingang).usingRecursiveComparison()
-					.ignoringFields("eingang_", "eingang", "clientAttributes_", "memoizedHashCode")
+					.ignoringFields("eingang_", "clientAttributes_", "memoizedHashCode", "header_")
 					.isEqualTo(GrpcVorgangWithEingangTestFactory.create());
 		}
 
@@ -76,6 +81,13 @@ class VorgangWithEingangMapperTest {
 			assertThat(eingang).usingRecursiveComparison().isEqualTo(GrpcEingangTestFactory.create());
 		}
 
+		@Test
+		void shouldMapHeader() {
+			var header = callMapper().getHeader();
+
+			assertThat(header).usingRecursiveComparison().isEqualTo(GrpcVorgangHeadTestFactory.create());
+		}
+
 		private GrpcVorgangWithEingang callMapper() {
 			return mapper.toVorgangWithEingang(VorgangTestFactory.create());
 		}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleMapperTest.java
similarity index 95%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleMapperTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleMapperTest.java
index bf2e0cf9290d6f0f23ff1ee3e4e36f74ddd12c05..3eac366c31057f08cb0a828cda8acf8b7a133800 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleMapperTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleMapperTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 import static org.assertj.core.api.Assertions.*;
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleTestFactory.java
similarity index 66%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleTestFactory.java
index 3246c75173d03357c378369257f8dddaad56edc4..4a4cf2f0ab65014d32c5fbf3d6eb7b699fcdfe31 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/ZustaendigeStelleTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/ZustaendigeStelleTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,19 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang;
+package de.ozgcloud.vorgang.vorgang;
 
 public class ZustaendigeStelleTestFactory {
 
 	public static final String ORGANISATIONSEINHEIT_ID = GrpcZustaendigeStelleTestFactory.ORGANISATIONSEINHEIT_ID;
 	public static final String BEZEICHNUNG = "Amt für Kleintiere und Viehzeug";
 	public static final String EMAIL = GrpcZustaendigeStelleTestFactory.EMAIL;
+	public static final String GEMEINDE_SCHLUESSEL = "1029385858";
+	public static final String AMTLICHER_REGIONAL_SCHLUESSEL = "09876512";
+	public static final String HAUSANSCHRIFT_STRASSE = "Musterstraße 1";
+	public static final String HAUSANSCHRIFT_PLZ = "12345";
+	public static final String HAUSANSCHRIFT_ORT = "Musterhausen";
+	public static final String TELEFON = "0894578199358";
 
 	public static ZustaendigeStelle create() {
 		return createBuilder().build();
@@ -37,6 +43,12 @@ public class ZustaendigeStelleTestFactory {
 		return ZustaendigeStelle.builder() //
 				.organisationseinheitenId(ORGANISATIONSEINHEIT_ID)
 				.bezeichnung(BEZEICHNUNG)
-				.email(EMAIL);
+				.email(EMAIL)
+				.gemeindeSchluessel(GEMEINDE_SCHLUESSEL)
+				.amtlicherRegionalSchluessel(AMTLICHER_REGIONAL_SCHLUESSEL)
+				.hausanschriftStrasse(HAUSANSCHRIFT_STRASSE)
+				.hausanschriftPlz(HAUSANSCHRIFT_PLZ)
+				.hausanschriftOrt(HAUSANSCHRIFT_ORT)
+				.telefon(TELEFON);
 	}
 }
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardVorgangITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardVorgangITCase.java
similarity index 62%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardVorgangITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardVorgangITCase.java
index bcb4e2c9e6933721ac4fa702e1780ccb27777d3a..0375f79fb9f155d3eb01fbf9a88b582e54d29e93 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardVorgangITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardVorgangITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import static org.assertj.core.api.Assertions.*;
+import static org.awaitility.Awaitility.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 import org.bson.types.ObjectId;
@@ -44,29 +46,29 @@ import org.springframework.data.mongodb.core.MongoOperations;
 import org.springframework.data.mongodb.gridfs.GridFsTemplate;
 import org.springframework.security.test.context.support.WithMockUser;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.mail.email.MailSendErrorEventTestFactory;
-import de.itvsh.ozg.mail.email.MailSendRequest;
-import de.itvsh.ozg.mail.email.MailSentEventTestFactory;
-import de.itvsh.ozg.mail.email.MailService;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandStatus;
-import de.itvsh.ozg.pluto.command.GrpcCommandService;
-import de.itvsh.ozg.pluto.command.GrpcCreateCommandRequestTestFactory;
-import de.itvsh.ozg.pluto.command.PersistedCommand;
-import de.itvsh.ozg.pluto.files.FileId;
-import de.itvsh.ozg.pluto.files.GridFsTestFactory;
-import de.itvsh.ozg.pluto.files.OzgFileTestFactory;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCommandResponse;
-import de.itvsh.ozg.pluto.grpc.command.GrpcCreateCommandRequest;
-import de.itvsh.ozg.pluto.grpc.command.GrpcOrder;
-import de.itvsh.ozg.pluto.grpc.command.GrpcRedirectRequest;
-import de.itvsh.ozg.pluto.vorgang.EingangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileGroupTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.Vorgang.Status;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandStatus;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.nachrichten.email.MailSendErrorEventTestFactory;
+import de.ozgcloud.nachrichten.email.MailSendRequest;
+import de.ozgcloud.nachrichten.email.MailSentEventTestFactory;
+import de.ozgcloud.nachrichten.email.MailService;
+import de.ozgcloud.vorgang.command.GrpcCommandService;
+import de.ozgcloud.vorgang.command.GrpcCreateCommandRequestTestFactory;
+import de.ozgcloud.vorgang.command.PersistedCommand;
+import de.ozgcloud.vorgang.files.FileId;
+import de.ozgcloud.vorgang.files.GridFsTestFactory;
+import de.ozgcloud.vorgang.files.OzgFileTestFactory;
+import de.ozgcloud.vorgang.grpc.command.GrpcCommandResponse;
+import de.ozgcloud.vorgang.grpc.command.GrpcCreateCommandRequest;
+import de.ozgcloud.vorgang.grpc.command.GrpcOrder;
+import de.ozgcloud.vorgang.grpc.command.GrpcRedirectRequest;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroupTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.Vorgang.Status;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.stub.StreamObserver;
 
 @DataITCase
@@ -107,10 +109,13 @@ class ForwardVorgangITCase {
 		var attachment = IncomingFileGroupTestFactory.createBuilder().clearFiles().file(
 				IncomingFileTestFactory.createBuilder().id(storeNewFile()).build()).build();
 		var representation = IncomingFileTestFactory.createBuilder().id(storeNewFile()).build();
-		var vorgang = VorgangTestFactory.createBuilder().clearEingangs().eingang(EingangTestFactory.createBuilder()
-				.clearAttachments().attachment(attachment)
-				.clearRepresentations().representation(representation)
-				.build()).build();
+		var vorgang = VorgangTestFactory.createBuilder()
+				.status(Status.NEU)
+				.clearEingangs().eingang(EingangTestFactory.createBuilder()
+						.clearAttachments().attachment(attachment)
+						.clearRepresentations().representation(representation)
+						.build())
+				.build();
 
 		mongoOperations.save(vorgang);
 	}
@@ -135,10 +140,10 @@ class ForwardVorgangITCase {
 		void shouldHaveCommandWithFINISHEDState() {
 			callServiceCreateCommand();
 
-			var commands = mongoOperations.findAll(Command.class);
-			assertThat(commands).hasSize(1);
-			var redirectCommand = commands.get(0);
-			assertThat(redirectCommand.getStatus()).isEqualTo(CommandStatus.FINISHED);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var commands = mongoOperations.findAll(Command.class);
+				assertThat(commands).hasSize(1).first().extracting(Command::getStatus).isEqualTo(CommandStatus.FINISHED);
+			});
 		}
 
 		// TODO Forwarding status
@@ -159,28 +164,34 @@ class ForwardVorgangITCase {
 		void forwardCommandShouldBeWithError() {
 			callServiceCreateCommand();
 
-			var commands = mongoOperations.findAll(PersistedCommand.class);
-			assertThat(commands).hasSize(1);
-			var redirectCommand = commands.get(0);
-			assertThat(redirectCommand.getStatus()).isEqualTo(CommandStatus.ERROR);
-			assertThat(redirectCommand.getErrorMessage()).isEqualTo(MailSendErrorEventTestFactory.ERROR_MSG);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var commands = mongoOperations.findAll(PersistedCommand.class);
+				assertThat(commands).hasSize(1).first().satisfies(redirectCommand -> {
+					assertThat(redirectCommand.getStatus()).isEqualTo(CommandStatus.ERROR);
+					assertThat(redirectCommand.getErrorMessage()).isEqualTo(MailSendErrorEventTestFactory.ERROR_MSG);
+				});
+			});
 		}
 
 		@Test
 		void vorgangShouldHaveStatusIN_BEARBEITUNG() {
 			callServiceCreateCommand();
 
-			var loaded = mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
-			assertThat(loaded.getStatus()).isEqualTo(Status.IN_BEARBEITUNG);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var loaded = mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
+				assertThat(loaded.getStatus()).isEqualTo(Status.IN_BEARBEITUNG);
+			});
 		}
 
 		@Test
 		void forwardingShouldHaveStatusSEND_ERROR() {
 			callServiceCreateCommand();
 
-			var vorgang = mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
-			assertThat(vorgang.getForwardings()).hasSize(1);
-			assertThat(vorgang.getForwardings().get(0).getStatus()).isEqualTo(Forwarding.Status.SEND_ERROR);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
+				var vorgang = mongoOperations.findById(VorgangTestFactory.ID, Vorgang.class);
+				assertThat(vorgang.getForwardings()).hasSize(1);
+				assertThat(vorgang.getForwardings().get(0).getStatus()).isEqualTo(Forwarding.Status.SEND_ERROR);
+			});
 		}
 
 	}
@@ -196,6 +207,7 @@ class ForwardVorgangITCase {
 				.clearOrderString()
 				.clearOrder().setOrder(GrpcOrder.REDIRECT_VORGANG)
 				.clearRelationId().setRelationId(VorgangTestFactory.ID)
+				.setRelationVersion(VorgangTestFactory.VERSION)
 				.setRedirectRequest(buildRedirectRequest())
 				.build();
 	}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListenerITCase.java
similarity index 76%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListenerITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListenerITCase.java
index 3b0b678c4c0ef855f8a260d5bf1a0e0438420b43..818d433d71ecd1fa3d9940e2bf774629a03916ce 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListenerITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListenerITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
+import static org.awaitility.Awaitility.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.concurrent.TimeUnit;
+
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -36,13 +39,13 @@ import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.mail.javamail.JavaMailSender;
 
-import de.itvsh.kop.common.test.ITCase;
-import de.itvsh.ozg.mail.email.MailSentEventTestFactory;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEventTestFactory;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.command.Order;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.nachrichten.email.MailSentEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
 
 @ITCase
 class ForwardingEventListenerITCase {
@@ -59,13 +62,14 @@ class ForwardingEventListenerITCase {
 
 	@Nested
 	class TestForwardVorgang {
+
 		@Test
 		void shouldCallForwardingService() {
 			var command = CommandTestFactory.createBuilder().order(Order.REDIRECT_VORGANG.name()).build();
 
 			publisher.publishEvent(CommandCreatedEventTestFactory.create(command));
 
-			verify(service).forwardByCommand(command);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(service).forwardByCommand(command));
 		}
 
 	}
@@ -78,7 +82,7 @@ class ForwardingEventListenerITCase {
 
 			publisher.publishEvent(MailSentEventTestFactory.create(forwarding));
 
-			verify(service).onRedirectMailSent(forwarding);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(service).onRedirectMailSent(forwarding));
 		}
 
 		@ParameterizedTest
@@ -94,13 +98,14 @@ class ForwardingEventListenerITCase {
 
 	@Nested
 	class CommandCreatedEvent {
+
 		@Test
 		void shouldCallForwardingService() {
 			var command = CommandTestFactory.createBuilder().order(Order.FORWARD_SUCCESSFULL.name()).build();
 
 			publisher.publishEvent(CommandCreatedEventTestFactory.create(command));
 
-			verify(service).markAsSuccessfull(command);
+			await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> verify(service).markAsSuccessfull(command));
 		}
 	}
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListenerTest.java
similarity index 60%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListenerTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListenerTest.java
index 99aa071cb6ae8f388f0671d0ca4ae5e20f0613b4..eb74766eb9d9b418cd68c9616f799c0918202bb3 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingEventListenerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingEventListenerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,20 +21,25 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
+import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.ConcurrentModificationException;
+
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.springframework.context.ApplicationEventPublisher;
 
-import de.itvsh.ozg.mail.email.MailSentEventTestFactory;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandCreatedEventTestFactory;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.command.Order;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.command.CommandFailedEvent;
+import de.ozgcloud.nachrichten.email.MailSentEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.command.Order;
 
 class ForwardingEventListenerTest {
 
@@ -43,6 +48,28 @@ class ForwardingEventListenerTest {
 
 	@Mock
 	private ForwardingService forwardingService;
+	@Mock
+	private ApplicationEventPublisher publisher;
+
+	@Nested
+	class onForwardOrderCommand {
+
+		@Test
+		void shouldCallService() {
+			listener.onForwardOrder(CommandCreatedEventTestFactory.create());
+
+			verify(forwardingService).forwardByCommand(notNull());
+		}
+
+		@Test
+		void shouldPublishFailedEventOnError() {
+			when(forwardingService.forwardByCommand(any())).thenThrow(ConcurrentModificationException.class);
+			
+			listener.onForwardOrder(CommandCreatedEventTestFactory.create());
+			
+			verify(publisher).publishEvent(any(CommandFailedEvent.class));
+		}
+	}
 
 	@Nested
 	class onMailSentEvent {
@@ -55,6 +82,7 @@ class ForwardingEventListenerTest {
 
 			verify(forwardingService).onRedirectMailSent(forwarding);
 		}
+
 	}
 
 	@Nested
@@ -69,6 +97,15 @@ class ForwardingEventListenerTest {
 			verify(forwardingService).markAsSuccessfull(command);
 		}
 
+		@Test
+		void shouldPublishFailedEventOnError() {
+			doThrow(RuntimeException.class).when(forwardingService).markAsSuccessfull(any());
+
+			listener.markAsSuccessfull(CommandCreatedEventTestFactory.create());
+
+			verify(publisher).publishEvent(any(CommandFailedEvent.class));
+		}
+
 	}
 
 	@Nested
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingGrpcServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingGrpcServiceTest.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingGrpcServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingGrpcServiceTest.java
index c8c1dc72b0c239b34b236a4a8f38b1581b443b95..9bd78db5e19b53e26b59da2bfc1be27ad48075b7 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingGrpcServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingGrpcServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -37,9 +37,9 @@ import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
-import de.itvsh.ozg.pluto.forwarding.GrpcForwarding;
-import de.itvsh.ozg.pluto.forwarding.GrpcForwardingsResponse;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.forwarding.GrpcForwarding;
+import de.ozgcloud.vorgang.forwarding.GrpcForwardingsResponse;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 import io.grpc.stub.StreamObserver;
 
 class ForwardingGrpcServiceTest {
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..12a2ed35e946d8f04c42cf6e39f7d9e6466ebe8f
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingITCase.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang.redirect;
+
+import static org.mockito.ArgumentMatchers.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.security.test.context.support.WithMockUser;
+
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.nachrichten.email.MailSentEventTestFactory;
+import de.ozgcloud.nachrichten.email.MailService;
+import de.ozgcloud.vorgang.callcontext.CallContextTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+
+@DataITCase
+public class ForwardingITCase {
+
+	@Autowired
+	private ApplicationEventPublisher eventPublisher;
+	@Autowired
+	private MongoOperations mongoOperations;
+	@Autowired
+	private TaskExecutor taskExecutor;
+	@MockBean
+	private MailService mailService;
+
+	@Nested
+	class TestAcknowledgeForwarding {
+
+		private Vorgang vorgang;
+
+		@BeforeEach
+		void setup() {
+			vorgang = VorgangTestFactory.create();
+			mongoOperations.save(vorgang);
+		}
+
+		@Test
+		@WithMockUser(username = CallContextTestFactory.CLIENT)
+		void shouldCallMailService() {
+			var forwarding = ForwardingTestFactory.createBuilder().vorgangId(vorgang.getId()).build();
+
+			publishEventInNewThread(MailSentEventTestFactory.create(forwarding));
+
+			Mockito.verify(mailService, Mockito.timeout(1000)).sendMail(any());
+		}
+
+		private void publishEventInNewThread(ApplicationEvent event) {
+			taskExecutor.execute(() -> eventPublisher.publishEvent(event));
+		}
+	}
+}
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingRepositoryITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRepositoryITCase.java
similarity index 89%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingRepositoryITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRepositoryITCase.java
index 0ebcbe111092ac576e9b0a1d8cdb4ba80ab5f47a..79e287f6a101b4c8c5689e5418f222e27c6f58e7 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingRepositoryITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingRepositoryITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -33,10 +33,10 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 
-import de.itvsh.kop.common.test.DataITCase;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.redirect.Forwarding.Status;
+import de.ozgcloud.common.test.DataITCase;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.redirect.Forwarding.Status;
 
 @DataITCase
 class ForwardingRepositoryITCase {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceITCase.java
similarity index 89%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingServiceITCase.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceITCase.java
index 86dfdb45900668557be24d548ed44824ea18e9f1..40a4cfb1cb617d27bfeebda75b16a47ceda893dc 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceITCase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import static org.assertj.core.api.Assertions.*;
 
@@ -32,12 +32,12 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.test.util.ReflectionTestUtils;
 
-import de.itvsh.kop.common.test.ITCase;
-import de.itvsh.ozg.pluto.vorgang.AntragstellerTestFactory;
-import de.itvsh.ozg.pluto.vorgang.EingangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelleTestFactory;
+import de.ozgcloud.common.test.ITCase;
+import de.ozgcloud.vorgang.vorgang.AntragstellerTestFactory;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
 
 @ITCase
 class ForwardingServiceITCase {
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java
similarity index 87%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java
index e6583c63e0816cdbe5375ea09974528082cd3556..32313268d74c30225b45e0374ea17bb64a811d61 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,15 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
+import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 import java.util.Map;
 import java.util.Optional;
 
-import de.itvsh.ozg.mail.email.MailRecipient;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -42,24 +42,24 @@ import org.mockito.Spy;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.test.util.ReflectionTestUtils;
 
-import static org.assertj.core.api.Assertions.*;
-
-import de.itvsh.ozg.mail.email.MailSendRequest;
-import de.itvsh.ozg.mail.email.MailSendRequest.MailAttachment;
-import de.itvsh.ozg.mail.email.MailService;
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.vorgang.AntragstellerTestFactory;
-import de.itvsh.ozg.pluto.vorgang.EingangHeaderTestFactory;
-import de.itvsh.ozg.pluto.vorgang.EingangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.Vorgang;
-import de.itvsh.ozg.pluto.vorgang.VorgangService;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.ZustaendigeStelleTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.nachrichten.email.MailRecipient;
+import de.ozgcloud.nachrichten.email.MailSendRequest;
+import de.ozgcloud.nachrichten.email.MailSendRequest.MailAttachment;
+import de.ozgcloud.nachrichten.email.MailService;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.status.StatusService;
+import de.ozgcloud.vorgang.vorgang.AntragstellerTestFactory;
+import de.ozgcloud.vorgang.vorgang.EingangHeaderTestFactory;
+import de.ozgcloud.vorgang.vorgang.EingangTestFactory;
+import de.ozgcloud.vorgang.vorgang.Vorgang;
+import de.ozgcloud.vorgang.vorgang.VorgangService;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.ZustaendigeStelleTestFactory;
 
 class ForwardingServiceTest {
 
-	@Spy // NOSONAR
+	@Spy
 	@InjectMocks
 	private ForwardingService service;
 	@Mock
@@ -74,6 +74,9 @@ class ForwardingServiceTest {
 	@Mock
 	private VorgangService vorgangService;
 
+	@Mock
+	private StatusService statusService;
+
 	@Mock
 	private ApplicationEventPublisher publisher;
 
@@ -218,7 +221,7 @@ class ForwardingServiceTest {
 	@Nested
 	class TestOnRedirectMailSent {
 
-		@Captor // NOSONAR
+		@Captor
 		private ArgumentCaptor<VorgangRedirectedEvent> eventCaptor;
 
 		private Forwarding forwarding = ForwardingTestFactory.create();
@@ -551,32 +554,72 @@ class ForwardingServiceTest {
 		private Command command = CommandTestFactory.create();
 		private Vorgang vorgang = VorgangTestFactory.create();
 
-		@BeforeEach
-		void initTest() {
+		@Test
+		void shouldDoRedirect() {
 			when(vorgangService.getById(any())).thenReturn(vorgang);
-			doNothing().when(service).redirectVorgang(any(), any());
-		}
+			doNothing().when(service).doRedirect(any(), any());
 
-		@DisplayName("should update vorgang by the given status 'IN_BEARBEITUNG")
-		@Test
-		void shouldCallService() {
 			service.forwardByCommand(command);
 
-			verify(vorgangService).setStatusToInBearbeitung(CommandTestFactory.RELATION_ID, CommandTestFactory.RELATION_VERSION);
+			verify(service).doRedirect(command, vorgang);
 		}
 
-		@Test
-		void shouldForwardVorgang() {
-			service.forwardByCommand(command);
+		@DisplayName("on version missmatch")
+		@Nested
+		class VersionMissmatch {
+
+			@BeforeEach
+			void initTest() {
+				when(vorgangService.getById(any())).thenReturn(vorgang);
+			}
+
+			@Test
+			void shouldDoNothing() {
+				service.forwardByCommand(CommandTestFactory.createBuilder().relationVersion(5L).build());
+
+				verify(service, never()).doRedirect(any(), any());
+			}
 
-			verify(service).redirectVorgang(vorgang, command);
+			@Test
+			void shouldMarkAsFailed() {
+				var command = CommandTestFactory.createBuilder().relationVersion(5L).build();
+
+				service.forwardByCommand(command);
+
+				verify(service).markAsFailed(command);
+			}
 		}
 
-		@Test
-		void shouldNOTDispatchEvent() {
-			service.forwardByCommand(command);
+		@Nested
+		class doRedirect {
+
+			@BeforeEach
+			void initTest() {
+				doNothing().when(service).redirectVorgang(any(), any());
+			}
+
+			@DisplayName("should update vorgang by the given status 'IN_BEARBEITUNG")
+			@Test
+			void shouldCallService() {
+				service.doRedirect(command, vorgang);
+
+				verify(statusService).setStatusToInBearbeitung(CommandTestFactory.RELATION_ID, CommandTestFactory.RELATION_VERSION);
+			}
 
-			verifyNoInteractions(publisher);
+			@Test
+			void shouldForwardVorgang() {
+				service.doRedirect(command, vorgang);
+
+				verify(service).redirectVorgang(vorgang, command);
+			}
+
+			@Test
+			void shouldNOTDispatchEvent() {
+				service.doRedirect(command, vorgang);
+
+				verifyNoInteractions(publisher);
+			}
 		}
+
 	}
 }
\ No newline at end of file
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingTestFactory.java
similarity index 84%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingTestFactory.java
index 86f589cd06ab47d596c1f4291a43b027b082e712..d64043d44adcf2f2422f5b837b6489da61995364 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ForwardingTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ForwardingTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import java.util.UUID;
 
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.redirect.Forwarding.Status;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.redirect.Forwarding.Status;
 
 public class ForwardingTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/GrpcFindForwardingsRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcFindForwardingsRequestTestFactory.java
similarity index 79%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/GrpcFindForwardingsRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcFindForwardingsRequestTestFactory.java
index 409996454617ffadd32ee4dc946d6bd3d6b4cc12..a938c69173d95787bb226d5514bcfd4e0ab28d8c 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/GrpcFindForwardingsRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/GrpcFindForwardingsRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
-import de.itvsh.ozg.pluto.command.GrpcCallContextTestFactory;
-import de.itvsh.ozg.pluto.forwarding.GrpcFindForwardingsRequest;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.command.GrpcCallContextTestFactory;
+import de.ozgcloud.vorgang.forwarding.GrpcFindForwardingsRequest;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
 
 public class GrpcFindForwardingsRequestTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequestTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequestTestFactory.java
similarity index 88%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequestTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequestTestFactory.java
index b85ea787b433f603a65dc7a3b7fbcc36992fc1e1..f1f1fda442b2bf98594a03a103208ccfd386e55a 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/RedirectRequestTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/RedirectRequestTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 class RedirectRequestTestFactory {
 
 	static final String EMAIL = "test@ozg-sh.de";
-	static final String PASSWORD = "geheim";
+	static final String PASSWORD = "";
 
 	public static RedirectRequest create() {
 		return createBuilder().build();
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardFailedEventTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardFailedEventTestFactory.java
similarity index 84%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardFailedEventTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardFailedEventTestFactory.java
index 573375550b8705500639be9ca9695dfbbbf062ea..649ee0815d1ec6b1af518b194b6ed03f16559b0e 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangForwardFailedEventTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangForwardFailedEventTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
-import de.itvsh.ozg.pluto.command.Command;
-import de.itvsh.ozg.pluto.command.CommandTestFactory;
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
 
 public class VorgangForwardFailedEventTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectedEventTestFactory.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectedEventTestFactory.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectedEventTestFactory.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectedEventTestFactory.java
index fb0e7a821c4571c849d2c9a4b61c833953a6d3b5..26e1b8508f9d89bb62df5b51f73f9c32dc64ffcd 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/VorgangRedirectedEventTestFactory.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/VorgangRedirectedEventTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 public class VorgangRedirectedEventTestFactory {
 
diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ZipBuilderServiceTest.java
similarity index 91%
rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderServiceTest.java
rename to vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ZipBuilderServiceTest.java
index 9e14177fc4079d8239ae204b67efab59290cd4b4..91e9cc35f6a30ab4de77925cb936d7cc01b57829 100644
--- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/redirect/ZipBuilderServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/redirect/ZipBuilderServiceTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.ozg.pluto.vorgang.redirect;
+package de.ozgcloud.vorgang.vorgang.redirect;
 
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -44,12 +44,12 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.springframework.test.util.ReflectionTestUtils;
 
-import de.itvsh.ozg.pluto.files.FileId;
-import de.itvsh.ozg.pluto.files.FileService;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileGroupTestFactory;
-import de.itvsh.ozg.pluto.vorgang.IncomingFileTestFactory;
-import de.itvsh.ozg.pluto.vorgang.VorgangTestFactory;
-import de.itvsh.ozg.pluto.vorgang.redirect.ZipBuilderService.ZipBuilder;
+import de.ozgcloud.vorgang.files.FileId;
+import de.ozgcloud.vorgang.files.FileService;
+import de.ozgcloud.vorgang.vorgang.IncomingFileGroupTestFactory;
+import de.ozgcloud.vorgang.vorgang.IncomingFileTestFactory;
+import de.ozgcloud.vorgang.vorgang.VorgangTestFactory;
+import de.ozgcloud.vorgang.vorgang.redirect.ZipBuilderService.ZipBuilder;
 import net.lingala.zip4j.ZipFile;
 import net.lingala.zip4j.io.outputstream.ZipOutputStream;
 import net.lingala.zip4j.model.ZipParameters;
@@ -89,7 +89,7 @@ class ZipBuilderServiceTest {
 			builder.addFile("", IncomingFileTestFactory.create());
 
 			verify(zipOut).putNextEntry(parametersCaptor.capture());
-			assertThat(parametersCaptor.getValue().getFileNameInZip()).isEqualTo("/" + IncomingFileTestFactory.NAME);
+			assertThat(parametersCaptor.getValue().getFileNameInZip()).isEqualTo(IncomingFileTestFactory.NAME);
 		}
 
 		@Test
diff --git a/vorgang-manager-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/vorgang-manager-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 0000000000000000000000000000000000000000..79b126e6cdb86bec1f4f08c205de8961bde1934a
--- /dev/null
+++ b/vorgang-manager-server/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1 @@
+org.mockito.junit.jupiter.MockitoExtension
\ No newline at end of file
diff --git a/pluto-server/src/test/resources/TestDoc.docx b/vorgang-manager-server/src/test/resources/TestDoc.docx
similarity index 100%
rename from pluto-server/src/test/resources/TestDoc.docx
rename to vorgang-manager-server/src/test/resources/TestDoc.docx
diff --git a/vorgang-manager-server/src/test/resources/application-itcase.yml b/vorgang-manager-server/src/test/resources/application-itcase.yml
new file mode 100644
index 0000000000000000000000000000000000000000..96b714f6f813bab2e43f054df6147c89749a6dbf
--- /dev/null
+++ b/vorgang-manager-server/src/test/resources/application-itcase.yml
@@ -0,0 +1,17 @@
+logging:
+  level:
+    ROOT: ERROR,
+    '[org.springframework]': ERROR
+    '[org.springframework.data.mongodb.core]': WARN
+    '[de.ozgcloud]': WARN
+  config: classpath:log4j2-local.xml
+
+grpc:
+  server:
+    port: -1
+
+ozgcloud:
+  aktenzeichen: de.ozgcloud.vorgang.vorgang.AktenzeichenProviderEA
+
+mongock:
+  enabled: false
diff --git a/pluto-server/src/test/resources/application-with_db.yml b/vorgang-manager-server/src/test/resources/application-with_db.yml
similarity index 81%
rename from pluto-server/src/test/resources/application-with_db.yml
rename to vorgang-manager-server/src/test/resources/application-with_db.yml
index fa1211c29d84766d5838a7ef176a05267cf5ac67..9f1bcf29209d401941cd77bc381dce4b8f4e1d2e 100644
--- a/pluto-server/src/test/resources/application-with_db.yml
+++ b/vorgang-manager-server/src/test/resources/application-with_db.yml
@@ -6,4 +6,4 @@ spring:
   data:
     mongodb:
       host: localhost
-      database: embeded_db
\ No newline at end of file
+      database: embeded_db
diff --git a/vorgang-manager-server/src/test/resources/bayernid.p12 b/vorgang-manager-server/src/test/resources/bayernid.p12
new file mode 100644
index 0000000000000000000000000000000000000000..fa82ce9007cc50831496073cdb03d8b6a92b5ee4
Binary files /dev/null and b/vorgang-manager-server/src/test/resources/bayernid.p12 differ
diff --git a/vorgang-manager-server/src/test/resources/bayernid/bsp-nachricht b/vorgang-manager-server/src/test/resources/bayernid/bsp-nachricht
new file mode 100644
index 0000000000000000000000000000000000000000..531b80b0923fc7beb2dc147c62211019c539311f
--- /dev/null
+++ b/vorgang-manager-server/src/test/resources/bayernid/bsp-nachricht
@@ -0,0 +1 @@
+<ns4:sendBspNachrichtNative xmlns:ns3="http://www.akdb.de/egov/bsp/nachrichten" xmlns:ns4="urn:akdb:bsp:postkorb:komm:webservice"><bspNachricht>&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;&lt;ns2:BspNachricht xmlns:ns2="http://www.akdb.de/egov/bsp/nachrichten" xmlns:ns3="urn:akdb:bsp:postkorb:komm:webservice"&gt;&lt;ns2:NachrichtenKopf&gt;&lt;ns2:Identifikation.Nachricht&gt;&lt;ns2:Erstellungszeitpunkt&gt;2020-04-01T10:30:10.000Z&lt;/ns2:Erstellungszeitpunkt&gt;&lt;ns2:NachrichtenId&gt;1&lt;/ns2:NachrichtenId&gt;&lt;/ns2:Identifikation.Nachricht&gt;&lt;ns2:Absender&gt;&lt;ns2:Dienst&gt;Stadtverwaltung&lt;/ns2:Dienst&gt;&lt;ns2:Mandant&gt;Fürth&lt;/ns2:Mandant&gt;&lt;ns2:Gemeindeschluessel&gt;&lt;ns2:Tabelle&gt;36&lt;/ns2:Tabelle&gt;&lt;ns2:Schluessel&gt;09563000&lt;/ns2:Schluessel&gt;&lt;/ns2:Gemeindeschluessel&gt;&lt;/ns2:Absender&gt;&lt;ns2:Empfaenger&gt;&lt;ns2:PostkorbId&gt;1&lt;/ns2:PostkorbId&gt;&lt;/ns2:Empfaenger&gt;&lt;/ns2:NachrichtenKopf&gt;&lt;ns2:NachrichtenInhalt&gt;&lt;ns2:Betreff&gt;Test Subject&lt;/ns2:Betreff&gt;&lt;ns2:StorkQaaLevel&gt;LEVEL_1&lt;/ns2:StorkQaaLevel&gt;&lt;ns2:ZuVorgang&gt;&lt;ns2:VorgangsId&gt;1&lt;/ns2:VorgangsId&gt;&lt;/ns2:ZuVorgang&gt;&lt;ns2:FreiText&gt;&lt;ns2:Encoding&gt;&lt;ns2:Tabelle&gt;9004&lt;/ns2:Tabelle&gt;&lt;ns2:Schluessel&gt;text/plain&lt;/ns2:Schluessel&gt;&lt;/ns2:Encoding&gt;&lt;ns2:Text&gt;BodyString&lt;/ns2:Text&gt;&lt;/ns2:FreiText&gt;&lt;/ns2:NachrichtenInhalt&gt;&lt;/ns2:BspNachricht&gt;</bspNachricht></ns4:sendBspNachrichtNative>
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/resources/bayernid/test.txt b/vorgang-manager-server/src/test/resources/bayernid/test.txt
new file mode 100644
index 0000000000000000000000000000000000000000..814be41a4bbeee81df9c0f296e3fcc3a3cef33f0
--- /dev/null
+++ b/vorgang-manager-server/src/test/resources/bayernid/test.txt
@@ -0,0 +1 @@
+some simple text
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/resources/junit-platform.properties b/vorgang-manager-server/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1cebb76d5a58ac034b2627d12411d82d1e85821e
--- /dev/null
+++ b/vorgang-manager-server/src/test/resources/junit-platform.properties
@@ -0,0 +1 @@
+junit.jupiter.extensions.autodetection.enabled = true
\ No newline at end of file
diff --git a/pluto-utils/pom.xml b/vorgang-manager-utils/pom.xml
similarity index 66%
rename from pluto-utils/pom.xml
rename to vorgang-manager-utils/pom.xml
index 95d1f76337859d553663ebddb81e038715766123..e5c443537e78de8a2a22b694decdd4594ead5e2e 100644
--- a/pluto-utils/pom.xml
+++ b/vorgang-manager-utils/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
     Ministerpräsidenten des Landes Schleswig-Holstein
     Staatskanzlei
     Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -24,43 +24,40 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 
 	<parent>
-		<groupId>de.itvsh.kop.common</groupId>
-		<artifactId>kop-common-dependencies</artifactId>
-		<version>1.2.1</version>
-		<relativePath />
+		<groupId>de.ozgcloud.common</groupId>
+		<artifactId>ozgcloud-common-dependencies</artifactId>
+		<version>3.0.1</version>
+		<relativePath/>
 	</parent>
 
-	<groupId>de.itvsh.ozg.pluto</groupId>
-	<artifactId>pluto-utils</artifactId>
-	<name>Pluto Util Project</name>
-	<version>1.0.0</version>
+	<groupId>de.ozgcloud.vorgang</groupId>
+	<artifactId>vorgang-manager-utils</artifactId>
+	<name>OZG-Cloud Vorgang Manager Utils</name>
+	<version>2.4.0</version>
 
 	<properties>
-		<pluto.version>1.0.0</pluto.version>
-
 		<maven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>
 		<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
-
-		<maven-surefire-plugin.version>3.0.0-M7</maven-surefire-plugin.version>
-		<maven-failsafe-plugin.version>3.0.0-M7</maven-failsafe-plugin.version>
-		<jacoco.plugin.version>0.8.8</jacoco.plugin.version>
-
-		<lombok.version>1.18.24</lombok.version>
+		
+		<maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>
+		<maven-failsafe-plugin.version>3.2.2</maven-failsafe-plugin.version>
+		<lombok.version>1.18.28</lombok.version>
+		
 	</properties>
 
 	<dependencies>
 		<dependency>
-			<groupId>de.itvsh.kop.common</groupId>
-			<artifactId>kop-common-lib</artifactId>
+			<groupId>de.ozgcloud.common</groupId>
+			<artifactId>ozgcloud-common-lib</artifactId>
 		</dependency>
 		<dependency>
-			<groupId>de.itvsh.ozg.pluto</groupId>
-			<artifactId>pluto-interface</artifactId>
+			<groupId>de.ozgcloud.vorgang</groupId>
+			<artifactId>vorgang-manager-interface</artifactId>
+			<version>${project.version}</version>
 		</dependency>
 
 		<dependency>
@@ -99,6 +96,18 @@
 			<artifactId>assertj-core</artifactId>
 			<scope>test</scope>
 		</dependency>
+
+		<!-- commons -->
+		<dependency>
+			<groupId>commons-beanutils</groupId>
+			<artifactId>commons-beanutils</artifactId>
+			<exclusions>
+				<exclusion>
+					<groupId>commons-logging</groupId>
+					<artifactId>commons-logging</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
 	</dependencies>
 
 	<build>
@@ -120,8 +129,6 @@
 				<artifactId>maven-compiler-plugin</artifactId>
 				<version>${maven-compiler-plugin.version}</version>
 				<configuration>
-					<source>${java.version}</source>
-					<target>${java.version}</target>
 					<fork>true</fork>
 					<annotationProcessorPaths>
 						<path>
@@ -138,14 +145,18 @@
 
 					<showWarnings>true</showWarnings>
 					<compilerArgs>
-						<compilerArg> -Amapstruct.defaultComponentModel=spring
+						<compilerArg>
+							-Amapstruct.defaultComponentModel=spring
 						</compilerArg>
-						<compilerArg> -Amapstruct.unmappedTargetPolicy=WARN
+						<compilerArg>
+							-Amapstruct.unmappedTargetPolicy=WARN
 						</compilerArg>
-						<compilerArg> -Amapstruct.unmappedSourcePolicy=WARN
+						<compilerArg>
+							-Amapstruct.unmappedSourcePolicy=WARN
 						</compilerArg>
 					</compilerArgs>
 					<generatedSourcesDirectory>target/generated-sources</generatedSourcesDirectory>
+					<release>${java.version}</release>
 				</configuration>
 			</plugin>
 
@@ -155,7 +166,7 @@
 				<version>${maven-surefire-plugin.version}</version>
 				<configuration>
 					<argLine>
-							${surefire.jacoco.args}
+						${surefire.jacoco.args}
 					</argLine>
 				</configuration>
 			</plugin>
@@ -165,7 +176,7 @@
 				<version>${maven-failsafe-plugin.version}</version>
 				<configuration>
 					<argLine>
-							${surefire.jacoco.args}
+						${surefire.jacoco.args}
 					</argLine>
 					<classesDirectory>${project.build.outputDirectory}</classesDirectory>
 				</configuration>
@@ -181,7 +192,6 @@
 			<plugin>
 				<groupId>org.jacoco</groupId>
 				<artifactId>jacoco-maven-plugin</artifactId>
-				<version>${jacoco.plugin.version}</version>
 				<executions>
 					<execution>
 						<id>start-agent</id>
@@ -201,6 +211,32 @@
 					</execution>
 				</executions>
 			</plugin>
+			<plugin>
+				<groupId>com.mycila</groupId>
+				<artifactId>license-maven-plugin</artifactId>
+				<configuration>
+					<mapping>
+						<config>SCRIPT_STYLE</config>
+					</mapping>
+					<licenseSets>
+						<licenseSet>
+							<header>license/eupl_v1_2_de/header.txt</header>
+							<excludes>
+								<exclude>**/README</exclude>
+								<exclude>src/test/resources/**</exclude>
+								<exclude>src/main/resources/**</exclude>
+							</excludes>
+						</licenseSet>
+					</licenseSets>
+				</configuration>
+				<dependencies>
+					<dependency>
+						<groupId>de.ozgcloud.common</groupId>
+						<artifactId>ozgcloud-common-license</artifactId>
+						<version>${ozgcloud.license.version}</version>
+					</dependency>
+				</dependencies>
+			</plugin>
 		</plugins>
 	</build>
-</project>
\ No newline at end of file
+</project>
diff --git a/vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/FormDataMappingUtils.java b/vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/FormDataMappingUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e219075414b9bbce6837960b52e02b00761cae2
--- /dev/null
+++ b/vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/FormDataMappingUtils.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import static java.util.Objects.*;
+
+import java.time.LocalDate;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.tuple.Pair;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFormField;
+
+class FormDataMappingUtils {
+
+	static final String VALUE_KEY = "value";
+	static final String LABEL_KEY = "label";
+	static final String CONTROL_DATA_KEY = "controlData";
+
+	static final String META_DATA_KEY = "metadata";
+
+	private FormDataMappingUtils() {
+	}
+
+	static GrpcFormField buildFormField(String name, String value) {
+		return buildFormField(name, value, null);
+	}
+
+	static GrpcFormField buildFormField(String name, String value, String label) {
+		var formFieldBuilder = GrpcFormField.newBuilder().setName(name).setValue(value);
+		if (nonNull(label)) {
+			formFieldBuilder.setLabel(label);
+		}
+		return formFieldBuilder.build();
+	}
+
+	static Map<String, Object> pairAccumulator(Map<String, Object> map, Pair<String, Map<String, Object>> pair) {
+		return addToMap(map, pair.getLeft(), pair.getRight());
+	}
+
+	static Map<String, Object> combiner(Map<String, Object> map, Map<String, Object> toAddMap) {
+		toAddMap.forEach((key, value) -> addToMap(map, key, value));
+		return map;
+	}
+
+	static Map<String, Object> addToMap(Map<String, Object> map, String name, Object value) {
+		map.compute(name, (k, v) -> isNull(v) ? value : merge(v, value));
+		return map;
+	}
+
+	static Object merge(Object currentValue, Object newValue) {
+		var result = buildListFrom(currentValue);
+		result.addAll(buildListFrom(newValue));
+		return Collections.unmodifiableList(result);
+	}
+
+	private static List<Object> buildListFrom(Object value) {
+		if (value instanceof Collection<?> values) {
+			return new LinkedList<>(values);
+		} else {
+			return new LinkedList<>(List.of(value));
+		}
+	}
+
+	static boolean isSubForm(Object value) {
+		return (!isValue(value) && getValueObject(value) instanceof Map);
+	}
+
+	static boolean isValue(Object value) {
+		if (value instanceof Map<?, ?> valueMap) {
+			return valueMap.containsKey(VALUE_KEY) &&
+					(valueMap.get(VALUE_KEY) instanceof String
+							|| valueMap.get(VALUE_KEY) instanceof Number
+							|| valueMap.get(VALUE_KEY) instanceof LocalDate
+							|| valueMap.get(VALUE_KEY) instanceof Boolean);
+		} else {
+			return value instanceof String;
+		}
+	}
+
+	static Object getValueObject(Object valueContainer) {
+		if (valueContainer instanceof Map<?, ?> valueMap) {
+			if (valueMap.containsKey(VALUE_KEY)) {
+				return valueMap.get(VALUE_KEY);
+			}
+			return valueContainer;
+		} else {
+			return valueContainer;
+		}
+	}
+
+	static String getValue(Object valueContainer) {
+		return getValueObject(valueContainer).toString();
+	}
+
+	@SuppressWarnings("unchecked")
+	static Map<String, Object> getValueMap(Map<String, Object> valueContainer) {
+		if (valueContainer.containsKey(VALUE_KEY)) {
+			return (Map<String, Object>) valueContainer.get(VALUE_KEY);
+		}
+		return valueContainer;
+	}
+
+	static Optional<String> getLabel(Object valueContainer) {
+		if (valueContainer instanceof Map<?, ?> valueMap) {
+			return Optional.ofNullable((String) valueMap.get(LABEL_KEY));
+		}
+		return Optional.empty();
+	}
+
+	static boolean isMapWithLabel(Map<?, ?> map) {
+		return nonNull(map) && map.size() == 2
+				&& map.containsKey(LABEL_KEY) && map.containsKey(VALUE_KEY);
+	}
+
+	@SuppressWarnings("unchecked")
+	public static <A, B> Map<A, B> getMap(Map<String, Object> map, String key, Map<A, B> defaultMap) {
+		return MapUtils.getMap(map, key, defaultMap);
+	}
+}
diff --git a/pluto-utils/src/main/java/de/itvsh/kop/pluto/common/grpc/GrpcFormDataMapper.java b/vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataMapper.java
similarity index 53%
rename from pluto-utils/src/main/java/de/itvsh/kop/pluto/common/grpc/GrpcFormDataMapper.java
rename to vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataMapper.java
index 18c8eadd4bf712cc6e848997cbd168166f9245b4..d08694ae0d5b9162c21a418dfa73038101da182e 100644
--- a/pluto-utils/src/main/java/de/itvsh/kop/pluto/common/grpc/GrpcFormDataMapper.java
+++ b/vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataMapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,26 +21,28 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.pluto.common.grpc;
+package de.ozgcloud.vorgang.common.grpc;
+
+import static de.ozgcloud.vorgang.common.grpc.FormDataMappingUtils.*;
 
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
 
-import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.lang3.StringUtils;
 import org.mapstruct.CollectionMappingStrategy;
 import org.mapstruct.Mapper;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.NullValuePropertyMappingStrategy;
 import org.mapstruct.ReportingPolicy;
 
-import de.itvsh.ozg.pluto.vorgang.GrpcFormData;
-import de.itvsh.ozg.pluto.vorgang.GrpcFormField;
-import de.itvsh.ozg.pluto.vorgang.GrpcSubForm;
+import de.ozgcloud.vorgang.vorgang.GrpcFormData;
+import de.ozgcloud.vorgang.vorgang.GrpcFormField;
+import de.ozgcloud.vorgang.vorgang.GrpcSubForm;
 
 @Mapper(unmappedTargetPolicy = ReportingPolicy.WARN, //
 		unmappedSourcePolicy = ReportingPolicy.WARN, //
@@ -58,14 +60,15 @@ public interface GrpcFormDataMapper {
 	}
 
 	default List<GrpcFormField> mapToAllFields(Map<String, Object> formData) {
-		return formData.entrySet().stream().filter(entry -> entry.getValue() instanceof String)//
-				.map(entry -> mapToField(entry.getKey(), entry.getValue().toString()))//
+		return formData.entrySet().stream()
+				.filter(entry -> isValue(entry.getValue()))
+				.map(entry -> mapToField(entry.getKey(), entry.getValue()))
 				.toList();
 	}
 
 	default List<GrpcFormField> mapStringListsToFields(Map<String, Object> formData) {
 		return formData.entrySet().stream()
-				.filter(entry -> entry.getValue() instanceof List)
+				.filter(entry -> getValueObject(entry.getValue()) instanceof List)
 				.map(this::mapListStringElementsToFormFields)
 				.flatMap(List::stream)
 				.toList();
@@ -73,108 +76,132 @@ public interface GrpcFormDataMapper {
 
 	@SuppressWarnings("unchecked")
 	private List<GrpcFormField> mapListStringElementsToFormFields(Entry<String, Object> entry) {
-		return ((List<Object>) entry.getValue()).stream()
-				.filter(String.class::isInstance)
-				.map(String.class::cast)
-				.map(e -> mapToField(entry.getKey(), e))
+		return ((List<Object>) getValueObject(entry.getValue())).stream()
+				.filter(FormDataMappingUtils::isValue)
+				.map(valueContainer -> mapToField(entry.getKey(), valueContainer))
+				.map(field -> getLabel(entry.getValue()).map(label -> field.toBuilder().setLabel(label).build()).orElse(field))
 				.toList();
 	}
 
 	default List<GrpcSubForm> mapObjectListsToFields(Map<String, Object> formData) {
 		return formData.entrySet().stream()
-				.filter(entry -> entry.getValue() instanceof List)
+				.filter(entry -> getValueObject(entry.getValue()) instanceof List)
 				.map(this::mapListObjectElementsToFormFields)
 				.flatMap(List::stream)
 				.toList();
 	}
 
 	@SuppressWarnings("unchecked")
-	private List<GrpcSubForm> mapListObjectElementsToFormFields(Entry<String, Object> entry) {
-		return ((List<Object>) entry.getValue()).stream()
-				.filter(Map.class::isInstance)
+	default List<GrpcSubForm> mapListObjectElementsToFormFields(Entry<String, Object> entry) {
+		return ((List<Object>) getValueObject(entry.getValue())).stream()
+				.filter(FormDataMappingUtils::isSubForm)
 				.map(Map.class::cast)
-				.map(e -> buildSubForm(entry.getKey(), e))
+				.map(valueMap -> buildSubForm(entry.getKey(), valueMap))
 				.toList();
 	}
 
 	@SuppressWarnings("unchecked")
 	default List<GrpcSubForm> mapToSubForms(Map<String, Object> formData) {
 		return formData.entrySet().stream()
-				.filter(entry -> entry.getValue() instanceof Map)
+				.filter(entry -> isSubForm(entry.getValue()))
 				.map(entry -> buildSubForm(entry.getKey(), (Map<String, Object>) entry.getValue()))
 				.toList();
 	}
 
 	default GrpcSubForm buildSubForm(String name, Map<String, Object> map) {
+		Map<String, Object> formMap = getValueMap(map);
+
 		return GrpcSubForm.newBuilder().setTitle(name)
-				.addAllField(mapToAllFields(map))
-				.addAllSubForm(mapToSubForms(map))
-				.addAllField(mapStringListsToFields(map))
-				.addAllSubForm(mapObjectListsToFields(map)).build();
+				.setLabel(getLabel(map).orElse(StringUtils.EMPTY))
+				.addAllField(mapToAllFields(formMap))
+				.addAllSubForm(mapToSubForms(formMap))
+				.addAllField(mapStringListsToFields(formMap))
+				.addAllSubForm(mapObjectListsToFields(formMap)).build();
 	}
 
-	default GrpcFormField mapToField(String name, String value) {
-		return GrpcFormField.newBuilder().setName(name).setValue(value).build();
+	default GrpcFormField mapToField(String name, Object valueContainer) {
+		var fieldBuilder = GrpcFormField.newBuilder().setName(name).setValue(getValue(valueContainer));
+		getLabel(valueContainer).ifPresent(fieldBuilder::setLabel);
+		return fieldBuilder.build();
 	}
 
 	default Map<String, Object> mapFromFormData(GrpcFormData formData) {
-		Map<String, Object> result = new HashMap<>();
+		Map<String, Object> result = new LinkedHashMap<>();
 		result.putAll(mapSubFormFields(formData.getFieldList()));
 		result.putAll(mapFormData(formData.getFormList()));
 		return result;
 	}
 
 	default Map<String, Object> mapFormData(List<GrpcSubForm> subForms) {
-		return subForms.stream().map(subForm -> Pair.of(subForm.getTitle(), mapSubForm(subForm)))
-				.collect(HashMap<String, Object>::new, this::pairAccumulator, this::combiner);
+		var subFormMap = subForms.stream()
+				.map(subForm -> new FormDataContainer(subForm.getTitle(), subForm.getLabel(), mapSubForm(subForm)))
+				.collect(LinkedHashMap::new, this::formDataAccumulator, this::combiner);
+
+		return removeLeadingValueKey(subFormMap);
 	}
 
-	private Map<String, Object> pairAccumulator(Map<String, Object> map, Pair<String, Map<String, Object>> pair) {
-		return addToMap(map, pair.getLeft(), pair.getRight());
+	private Map<String, Object> formDataAccumulator(Map<String, Object> map, FormDataContainer container) {
+		return addToMap(map, container.name, container.formData, container.label);
 	}
 
 	default Map<String, Object> mapSubForm(GrpcSubForm subForm) {
-		Map<String, Object> result = new HashMap<>();
+		Map<String, Object> result = new LinkedHashMap<>();
 		result.putAll(mapSubFormFields(subForm.getFieldList()));
 		result.putAll(mapFormData(subForm.getSubFormList()));
+
 		return result;
 	}
 
 	default Map<String, Object> mapSubFormFields(List<GrpcFormField> fields) {
-		return fields.stream().collect(HashMap<String, Object>::new, this::accumulator, this::combiner);
+		var fieldMap = fields.stream().collect(LinkedHashMap::new, this::accumulator, this::combiner);
+
+		return removeLeadingValueKey(fieldMap);
+	}
+
+	@SuppressWarnings("unchecked")
+	private Map<String, Object> removeLeadingValueKey(Map<String, Object> formMap) {
+		if (formMap.containsKey(VALUE_KEY)) {
+			return (Map<String, Object>) formMap.get(VALUE_KEY);
+		}
+		return formMap;
 	}
 
 	private Map<String, Object> accumulator(Map<String, Object> map, GrpcFormField field) {
-		return addToMap(map, field.getName(), field.getValue());
+		return addToMap(map, field.getName(), field.getValue(), field.getLabel());
 	}
 
 	default Map<String, Object> combiner(Map<String, Object> map1, Map<String, Object> map2) {
 		for (Entry<String, Object> entry : map2.entrySet()) {
-			addToMap(map1, entry.getKey(), entry.getValue());
+			addToMap(map1, entry.getKey(), entry.getValue(), null);
 		}
 
 		return map1;
 	}
 
 	@SuppressWarnings("unchecked")
-	private Map<String, Object> addToMap(Map<String, Object> map, String name, Object value) {
+	private Map<String, Object> addToMap(Map<String, Object> map, String name, Object value, String label) {
 		var valueInMap = map.get(name);
 		if (Objects.isNull(valueInMap)) {
-			map.put(name, value);
+			map.put(name, buildFieldMap(value, label));
+		} else if (value instanceof Collection) {
+			addCollectionValue(map, name, (Collection<Object>) value, label);
 		} else {
-			if (value instanceof Collection) {
-				addCollectionValue(map, name, (Collection<Object>) value);
-			} else {
-				addNonCollectionValue(map, name, value);
-			}
+			addNonCollectionValue(map, name, value, label);
 		}
 
 		return map;
 	}
 
+	private Map<String, Object> buildFieldMap(Object value, String label) {
+		if (StringUtils.isNotBlank(label)) {
+			return Map.of(LABEL_KEY, label, VALUE_KEY, value);
+		}
+		return Map.of(VALUE_KEY, value);
+	}
+
 	@SuppressWarnings("unchecked")
-	private Map<String, Object> addCollectionValue(Map<String, Object> map, String name, Collection<Object> value) {
-		var valueInMap = map.get(name);
+	private Map<String, Object> addCollectionValue(Map<String, Object> map, String name, Collection<Object> value, String label) {
+		var valueInMap = getValueObject(map.get(name));
 
 		var newList = new LinkedList<Object>();
 		if (valueInMap instanceof Collection) {
@@ -184,22 +211,33 @@ public interface GrpcFormDataMapper {
 			newList.add(valueInMap);
 			newList.addAll(value);
 		}
-		map.put(name, newList);
+		map.put(name, buildWithLabel(newList, label));
 		return map;
 	}
 
 	@SuppressWarnings("unchecked")
-	private Map<String, Object> addNonCollectionValue(Map<String, Object> map, String name, Object value) {
-		var valueInMap = map.get(name);
+	private Map<String, Object> addNonCollectionValue(Map<String, Object> map, String name, Object value, String label) {
+		var valueInMap = getValueObject(map.get(name));
 
 		if (valueInMap instanceof Collection) {
 			var newList = new LinkedList<>((Collection<Object>) valueInMap);
 			newList.add(value);
-			map.put(name, newList);
+			map.put(name, buildWithLabel(newList, label));
 		} else {
-			map.put(name, new LinkedList<>(List.of(valueInMap, value)));
+			map.put(name, buildWithLabel(List.of(valueInMap, value), label));
 		}
 
 		return map;
 	}
+
+	private Map<String, Object> buildWithLabel(Object value, String label) {
+		if (StringUtils.isBlank(label)) {
+			return Map.of(VALUE_KEY, value);
+		}
+		return Map.of(LABEL_KEY, label, VALUE_KEY, value);
+	}
+
+	record FormDataContainer(String name, String label, Map<String, Object> formData) {
+
+	}
 }
diff --git a/vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectMapper.java b/vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd15c22770750f264cd831ced17263eb8b6f320f
--- /dev/null
+++ b/vorgang-manager-utils/src/main/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectMapper.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.function.Predicate;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.mapstruct.Mapper;
+
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.common.GrpcProperty;
+import de.ozgcloud.vorgang.common.GrpcSubObject;
+
+@Mapper
+public interface GrpcObjectMapper {
+
+	Predicate<Entry<String, Object>> IS_VALUE_INSTANCEOF_MAP = entry -> entry.getValue() instanceof Map;
+
+	default GrpcObject fromMap(Map<String, Object> map) {
+		return GrpcObject.newBuilder()
+				.addAllProperty(mapToAllProperties(map))
+				.addAllSubObject(mapToSubObjects(map))
+				.build();
+	}
+
+	@SuppressWarnings("unchecked")
+	default List<GrpcSubObject> mapToSubObjects(Map<String, Object> propertyMap) {
+		return propertyMap.entrySet().stream()
+				.filter(IS_VALUE_INSTANCEOF_MAP)
+				.map(entry -> buildSubObject(entry.getKey(), (Map<String, Object>) entry.getValue()))
+				.toList();
+	}
+
+	default GrpcSubObject buildSubObject(String name, Map<String, Object> map) {
+		return GrpcSubObject.newBuilder().setName(name)
+				.addAllProperty(mapToAllProperties(map))
+				.addAllSubObject(mapToSubObjects(map))
+				.build();
+	}
+
+	default List<GrpcProperty> mapToAllProperties(Map<String, Object> propertyMap) {
+		return propertyMap.entrySet().stream()
+				.filter(IS_VALUE_INSTANCEOF_MAP.negate())
+				.map(entry -> mapToProperty(entry.getKey(), entry.getValue()))
+				.toList();
+	}
+
+	default GrpcProperty mapToProperty(String name, Object value) {
+		if (value instanceof Collection<?> valueList) {
+			return buildPropertyForValueList(name, valueList);
+		}
+		return buildPropertyForValueObject(name, value);
+	}
+
+	private GrpcProperty buildPropertyForValueList(String name, Collection<?> valueList) {
+		return GrpcProperty.newBuilder().setName(name).addAllValue(valueList.stream().map(this::getStringValue).toList()).build();
+	}
+
+	private GrpcProperty buildPropertyForValueObject(String name, Object value) {
+		return GrpcProperty.newBuilder().setName(name).addValue(getStringValue(value)).build();
+	}
+
+	// TODO do null value handling externally configurable
+	private String getStringValue(Object value) {
+		return Optional.ofNullable(value).map(Object::toString).orElse(StringUtils.EMPTY);
+	}
+
+	default Map<String, Object> mapFromGrpc(GrpcObject bodyObject) {
+		var map = new HashMap<String, Object>();
+		bodyObject.getPropertyList().stream().map(this::mapProperty).forEach(entry -> map.put(entry.getKey(), entry.getValue()));
+		bodyObject.getSubObjectList().forEach(subObject -> map.put(subObject.getName(), mapSubObject(subObject)));
+
+		return map;
+	}
+
+	default Map<String, Object> mapSubObject(GrpcSubObject object) {
+		var map = new HashMap<String, Object>();
+		object.getPropertyList().stream().map(this::mapProperty).forEach(entry -> map.put(entry.getKey(), entry.getValue()));
+		object.getSubObjectList().forEach(subObject -> map.put(subObject.getName(), mapSubObject(subObject)));
+
+		return map;
+	}
+
+	default Pair<String, Object> mapProperty(GrpcProperty property) {
+		return switch (property.getValueCount()) {
+		case 0 -> Pair.of(property.getName(), null);
+		case 1 -> Pair.of(property.getName(), property.getValue(0));
+		default -> Pair.of(property.getName(), property.getValueList().stream().map(StringUtils::trimToNull).toList());
+		};
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/FormDataMappingUtilsTest.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/FormDataMappingUtilsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..77db24bd1bb629669dc3f0a0469e8d27711c9a5f
--- /dev/null
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/FormDataMappingUtilsTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import static de.ozgcloud.vorgang.common.grpc.FormDataMappingUtils.*;
+import static de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFormField;
+
+class FormDataMappingUtilsTest {
+
+	@Nested
+	class TestCombiner {
+
+		@Test
+		void missingInMap2ShouldContainValue() {
+			Map<String, Object> map1 = Map.of("TEST", "VALUE1");
+			Map<String, Object> map2 = Map.of();
+
+			var combined = FormDataMappingUtils.combiner(map1, map2);
+
+			assertThat(combined).containsEntry("TEST", "VALUE1");
+		}
+
+		@Test
+		void missingInMap1ShouldContainValue() {
+			Map<String, Object> map1 = new HashMap<>();
+			Map<String, Object> map2 = Map.of("TEST", "VALUE1");
+
+			var combined = FormDataMappingUtils.combiner(map1, map2);
+
+			assertThat(combined).containsEntry("TEST", "VALUE1");
+		}
+
+		@Test
+		void inBothMapShouldCombineToList() {
+			Map<String, Object> map1 = new HashMap<>(Map.of("TEST", "VALUE1"));
+			Map<String, Object> map2 = Map.of("TEST", "VALUE2");
+
+			var combined = FormDataMappingUtils.combiner(map1, map2);
+
+			assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2"));
+		}
+
+		@Test
+		void listInMap2ShouldStayAList() {
+			Map<String, Object> map1 = Map.of("TEST", List.of("VALUE1", "VALUE2"));
+			Map<String, Object> map2 = Map.of();
+
+			var combined = FormDataMappingUtils.combiner(map1, map2);
+
+			assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2"));
+		}
+
+		@Test
+		void valueInMap1ShouldBeAddedToList() {
+			Map<String, Object> map1 = new HashMap<>(Map.of("TEST", "VALUE1"));
+			Map<String, Object> map2 = Map.of("TEST", List.of("VALUE2", "VALUE3"));
+
+			var combined = FormDataMappingUtils.combiner(map1, map2);
+
+			assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2", "VALUE3"));
+		}
+
+		@Test
+		void valueInMap2ShouldBeAddedToList() {
+			Map<String, Object> map1 = new HashMap<>(Map.of("TEST", List.of("VALUE1", "VALUE2")));
+			Map<String, Object> map2 = Map.of("TEST", "VALUE3");
+
+			var combined = FormDataMappingUtils.combiner(map1, map2);
+
+			assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2", "VALUE3"));
+		}
+
+		@Test
+		void listInMap1ShouldStayAList() {
+			Map<String, Object> map1 = new HashMap<>();
+			Map<String, Object> map2 = Map.of("TEST", List.of("VALUE1", "VALUE2"));
+
+			var combined = FormDataMappingUtils.combiner(map1, map2);
+
+			assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2"));
+		}
+
+		@Test
+		void listInBothMapsShouldByCombined() {
+			Map<String, Object> map1 = new HashMap<>(Map.of("TEST", List.of("VALUE1", "VALUE2")));
+			Map<String, Object> map2 = Map.of("TEST", List.of("VALUE3", "VALUE4"));
+
+			var combined = FormDataMappingUtils.combiner(map1, map2);
+
+			assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2", "VALUE3", "VALUE4"));
+		}
+	}
+
+	@Nested
+	@DisplayName("Add value to map")
+	class TestAddValueToMap {
+
+		private static final String KEY = "key";
+
+		private Map<String, Object> map = new HashMap<>();
+
+		@Test
+		void shouldAddValue() {
+			FormDataMappingUtils.addToMap(map, KEY, "value");
+
+			assertThat(map).containsEntry("key", "value");
+		}
+
+		@Test
+		void shouldAddCollection() {
+			FormDataMappingUtils.addToMap(map, KEY, List.of("value1", "value2"));
+
+			assertThat(map).containsEntry("key", List.of("value1", "value2"));
+		}
+
+		@Test
+		void shouldAddCollection2() {
+			map.put(KEY, "value");
+
+			FormDataMappingUtils.addToMap(map, KEY, List.of("value1", "value2"));
+
+			assertThat(map).containsEntry("key", List.of("value", "value1", "value2"));
+		}
+
+		@Test
+		void shouldAddCollection3() {
+			map.put(KEY, List.of("value"));
+
+			FormDataMappingUtils.addToMap(map, KEY, List.of("value1", "value2"));
+
+			assertThat(map).containsEntry("key", List.of("value", "value1", "value2"));
+		}
+
+		@Test
+		void shouldAddToCollection() {
+			map.put(KEY, List.of("value"));
+
+			FormDataMappingUtils.addToMap(map, KEY, "value1");
+
+			assertThat(map).containsEntry("key", List.of("value", "value1"));
+		}
+
+		@Test
+		void shouldAddMap() {
+			var map2 = Map.of("key2", "value2");
+
+			FormDataMappingUtils.addToMap(map, KEY, map2);
+
+			assertThat(map).containsEntry("key", map2);
+		}
+	}
+
+	@Nested
+	@DisplayName("Build GrpcFormField")
+	class TestToGrpcFormField {
+
+		private static String NAME = "name";
+		private static String LABEL = "label value";
+		private static String VALUE = "value";
+
+		@Test
+		void shouldSetValue() {
+			var field = buildFormField();
+
+			assertThat(field.getValue()).isEqualTo(GrpcFormFieldTestFactory.VALUE);
+		}
+
+		@Test
+		void shouldMapName() {
+			var field = buildFormField();
+
+			assertThat(field.getName()).isEqualTo(GrpcFormFieldTestFactory.NAME);
+		}
+
+		@Test
+		void shouldMapLabel() {
+			var field = buildFormField();
+
+			assertThat(field.getLabel()).isEqualTo(LABEL);
+		}
+
+		@Test
+		void shouldMapWithoutLabel() {
+			var field = FormDataMappingUtils.buildFormField(NAME, VALUE);
+
+			assertThat(field).isEqualTo(GrpcFormFieldTestFactory.createBuilder().clearLabel().build());
+		}
+
+		private GrpcFormField buildFormField() {
+			return FormDataMappingUtils.buildFormField(NAME, VALUE, LABEL);
+		}
+
+	}
+
+	@Nested
+	class TestGetLabel {
+
+		@Test
+		void shouldReturnLabel() {
+			var label = FormDataMappingUtils.getLabel(Map.of(LABEL_KEY, FIELD_LABEL));
+
+			assertThat(label).contains(FIELD_LABEL);
+		}
+
+		@Test
+		void shouldHandleAtomicValue() {
+			var label = FormDataMappingUtils.getLabel(FIELD_VALUE);
+
+			assertThat(label).isEmpty();
+		}
+
+		@Test
+		void shouldHandleMissingLabel() {
+			var label = FormDataMappingUtils.getLabel(Map.of(VALUE_KEY, FIELD_VALUE));
+
+			assertThat(label).isEmpty();
+		}
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataMapperTest.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ced869a4271453d51d98d16aeb80053576b3718b
--- /dev/null
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataMapperTest.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import static de.ozgcloud.vorgang.common.grpc.FormDataMappingUtils.*;
+import static de.ozgcloud.vorgang.common.grpc.GrpcSubFormTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Spy;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFormData;
+import de.ozgcloud.vorgang.vorgang.GrpcFormField;
+import de.ozgcloud.vorgang.vorgang.GrpcSubForm;
+
+class GrpcFormDataMapperTest {
+
+	@Spy
+	@InjectMocks
+	private GrpcFormDataMapper mapper = Mappers.getMapper(GrpcFormDataMapper.class);
+
+	@Nested
+	class TestMapToAllFields {
+		@Test
+		void shouldMapFieldForStringValue() {
+			mapper.mapToAllFields(Map.of(FIELD_NAME, FIELD_VALUE));
+
+			verify(mapper).mapToField(FIELD_NAME, FIELD_VALUE);
+		}
+
+		@Test
+		void shouldMapFieldForValueMap() {
+			Map<String, Object> valueMap = Map.of(VALUE_KEY, FIELD_VALUE);
+
+			mapper.mapToAllFields(Map.of(FIELD_NAME, valueMap));
+
+			verify(mapper).mapToField(FIELD_NAME, valueMap);
+		}
+
+		@Test
+		void shouldNOTMapFieldForSubForm() {
+			Map<String, Object> subForm = Map.of(SUBFORM_TITLE, Map.of(FIELD_NAME, FIELD_VALUE));
+
+			mapper.mapToAllFields(Map.of(FIELD_NAME, subForm));
+
+			verify(mapper, never()).mapToField(any(), any());
+		}
+
+		@Test
+		void souldNOTMapFieldForSubFormValue() {
+			Map<String, Object> subForm = Map.of(SUBFORM_TITLE, Map.of(FIELD_NAME, FIELD_VALUE));
+
+			mapper.mapToAllFields(Map.of(FIELD_NAME, Map.of(VALUE_KEY, subForm)));
+
+			verify(mapper, never()).mapToField(any(), any());
+		}
+
+		@Nested
+		class MapToField {
+
+			private Map<String, Object> valueContainer = Map.of(VALUE_KEY, FIELD_VALUE, LABEL_KEY, FIELD_LABEL);
+
+			@Test
+			void shouldHaveName() {
+				var grpcField = mapper.mapToField(FIELD_NAME, valueContainer);
+
+				assertThat(grpcField.getName()).isEqualTo(FIELD_NAME);
+			}
+
+			@Test
+			void shouldHaveValue() {
+				var grpcField = mapper.mapToField(FIELD_NAME, valueContainer);
+
+				assertThat(grpcField.getValue()).isEqualTo(FIELD_VALUE);
+			}
+
+			@Test
+			void shouldHaveLabel() {
+				var grpcField = mapper.mapToField(FIELD_NAME, valueContainer);
+
+				assertThat(grpcField.getLabel()).isEqualTo(FIELD_LABEL);
+			}
+		}
+	}
+
+	@Nested
+	class TestSimpleValueMapping {
+
+		@Test
+		void shouldHaveField() {
+			GrpcFormData formData = mapper.mapToFormData(Map.of("key", "value"));
+
+			assertThat(formData.getFieldList()).hasSize(1);
+		}
+
+		@Test
+		void shouldNotHaveSubForms() {
+
+			GrpcFormData formData = mapper.mapToFormData(Map.of("key", "value"));
+
+			assertThat(formData.getFormList()).isEmpty();
+		}
+
+		@Test
+		void shouldHaveNameField() {
+
+			GrpcFormData formData = mapper.mapToFormData(Map.of("key", "value"));
+
+			assertThat(formData.getField(0).getName()).isEqualTo("key");
+			assertThat(formData.getField(0).getValue()).isEqualTo("value");
+		}
+	}
+
+	@Nested
+	class TestSubFormMapping {
+
+		@Test
+		void shouldHaveSubForm() {
+
+			GrpcFormData formData = mapper.mapToFormData(Map.of("key", Map.of("subKey", "value")));
+
+			assertThat(formData.getFormList()).hasSize(1);
+		}
+
+		@Test
+		void shouldNotHaveFields() {
+
+			GrpcFormData formData = mapper.mapToFormData(Map.of("key", Map.of("subKey", "value")));
+
+			assertThat(formData.getFieldList()).isEmpty();
+		}
+
+		@Test
+		void shouldHaveSubFormField() {
+
+			GrpcFormData formData = mapper.mapToFormData(Map.of("key", Map.of("subKey", "value")));
+
+			assertThat(formData.getForm(0).getFieldList()).hasSize(1);
+			assertThat(formData.getForm(0).getTitle()).isEqualTo("key");
+			assertThat(formData.getForm(0).getField(0).getName()).isEqualTo("subKey");
+			assertThat(formData.getForm(0).getField(0).getValue()).isEqualTo("value");
+		}
+	}
+
+	@DisplayName("Mapped SubFormField")
+	@Nested
+	class TestSubFormFieldMapping {
+
+		private final GrpcSubForm subForm = GrpcSubFormTestFactory.create();
+
+		@Test
+		void shouldContainField() {
+			var mapped = mapper.mapSubFormFields(subForm.getFieldList());
+
+			assertThat(mapped).containsKey(GrpcSubFormTestFactory.FIELD_NAME);
+		}
+
+		@Test
+		void shouldContainValue() {
+			var mapped = mapper.mapSubFormFields(subForm.getFieldList());
+
+			assertThat(mapped).containsEntry(GrpcSubFormTestFactory.FIELD_NAME, GrpcSubFormTestFactory.FIELD);
+		}
+
+		@Nested
+		class TestCombiner {
+			@Test
+			void missingInMap2ShouldContainValue() {
+				Map<String, Object> map1 = Map.of("TEST", "VALUE1");
+				Map<String, Object> map2 = Map.of();
+
+				var combined = mapper.combiner(map1, map2);
+
+				assertThat(combined).containsEntry("TEST", "VALUE1");
+			}
+
+			@Test
+			void missingInMap1ShouldContainValue() {
+				Map<String, Object> map1 = new HashMap<>();
+				Map<String, Object> map2 = Map.of("TEST", "VALUE1");
+
+				var combined = mapper.combiner(map1, map2);
+
+				assertThat(combined).containsEntry("TEST", Map.of(VALUE_KEY, "VALUE1"));
+			}
+
+			@Test
+			void inBothMapShouldCombineToList() {
+				Map<String, Object> map1 = new HashMap<>(Map.of("TEST", "VALUE1"));
+				Map<String, Object> map2 = Map.of("TEST", "VALUE2");
+
+				var combined = mapper.combiner(map1, map2);
+
+				assertThat(combined).containsEntry("TEST", Map.of(VALUE_KEY, List.of("VALUE1", "VALUE2")));
+			}
+
+			@Test
+			void listInMap2ShouldStayAList() {
+				Map<String, Object> map1 = Map.of("TEST", List.of("VALUE1", "VALUE2"));
+				Map<String, Object> map2 = Map.of();
+
+				var combined = mapper.combiner(map1, map2);
+
+				assertThat(combined).containsEntry("TEST", List.of("VALUE1", "VALUE2"));
+			}
+
+			@Test
+			void valueInMap1ShouldBeAddedToList() {
+				Map<String, Object> map1 = new HashMap<>(Map.of("TEST", "VALUE1"));
+				Map<String, Object> map2 = Map.of("TEST", List.of("VALUE2", "VALUE3"));
+
+				var combined = mapper.combiner(map1, map2);
+
+				assertThat(combined).containsEntry("TEST", Map.of(VALUE_KEY, List.of("VALUE1", "VALUE2", "VALUE3")));
+			}
+
+			@Test
+			void valueInMap2ShouldBeAddedToList() {
+				Map<String, Object> map1 = new HashMap<>(Map.of("TEST", List.of("VALUE1", "VALUE2")));
+				Map<String, Object> map2 = Map.of("TEST", "VALUE3");
+
+				var combined = mapper.combiner(map1, map2);
+
+				assertThat(combined).containsEntry("TEST", Map.of(VALUE_KEY, List.of("VALUE1", "VALUE2", "VALUE3")));
+			}
+
+			@Test
+			void listInMap1ShouldStayAList() {
+				Map<String, Object> map1 = new HashMap<>();
+				Map<String, Object> map2 = Map.of("TEST", List.of("VALUE1", "VALUE2"));
+
+				var combined = mapper.combiner(map1, map2);
+
+				assertThat(combined).containsEntry("TEST", Map.of(VALUE_KEY, List.of("VALUE1", "VALUE2")));
+			}
+
+			@Test
+			void listInBothMapsShouldByCombined() {
+				Map<String, Object> map1 = new HashMap<>(Map.of("TEST", List.of("VALUE1", "VALUE2")));
+				Map<String, Object> map2 = Map.of("TEST", List.of("VALUE3", "VALUE4"));
+
+				var combined = mapper.combiner(map1, map2);
+
+				assertThat(combined).containsEntry("TEST", Map.of(VALUE_KEY, List.of("VALUE1", "VALUE2", "VALUE3", "VALUE4")));
+			}
+		}
+	}
+
+	@Nested
+	class TestMapFormData {
+
+		@Test
+		void shouldHaveTitleAsKey() {
+			var mapped = mapper.mapFormData(List.of(GrpcSubFormTestFactory.create()));
+
+			assertThat(mapped).containsKey(TITLE);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Test
+		void shouldHaveLabel() {
+			var mapped = mapper.mapFormData(List.of(GrpcSubFormTestFactory.create()));
+
+			assertThat((Map<String, Object>) mapped.get(TITLE)).containsEntry(LABEL_KEY, LABEL);
+		}
+
+		@Test
+		void shouldHaveSubFormField() {
+			var mapped = mapKontaktSubForm();
+
+			assertThat(mapped).containsKey(FIELD_NAME);
+		}
+
+		@SuppressWarnings("unchecked")
+		private Map<String, Object> mapKontaktSubForm() {
+			var mapped = mapper.mapFormData(List.of(GrpcSubFormTestFactory.create()));
+
+			var formMap = (Map<String, Object>) mapped.get(TITLE);
+			return (Map<String, Object>) formMap.get(VALUE_KEY);
+		}
+
+		@SuppressWarnings("unchecked")
+		@Test
+		void shouldJoinIntoListInValue() {
+			var mapped = mapper.mapFormData(List.of(GrpcSubFormTestFactory.create(), GrpcSubFormTestFactory.create()));
+
+			var formList = (Map<String, Object>) mapped.get(TITLE);
+
+			assertThat(formList).containsKey(VALUE_KEY);
+			var value = (List<Map<String, Object>>) formList.get(VALUE_KEY);
+			assertThat(value).hasSize(2);
+		}
+	}
+
+	@Nested
+	class TestMapStringListsToFields {
+
+		@Test
+		void emptyMapShouldNotBeMapped() {
+			List<GrpcFormField> fields = mapper.mapStringListsToFields(Collections.emptyMap());
+
+			assertThat(fields).isEmpty();
+		}
+
+		@Test
+		void simpleValueShouldNotBeMapped() {
+			List<GrpcFormField> fields = mapper.mapStringListsToFields(Map.of("a", "b"));
+
+			assertThat(fields).isEmpty();
+		}
+
+		@Test
+		void listObjectValuesShouldBeMapped() {
+			List<GrpcFormField> fields = mapper.mapStringListsToFields(Map.of("key", List.of("value1", "value2")));
+
+			assertThat(fields).hasSize(2);
+			assertThat(fields.get(0).getName()).isEqualTo("key");
+			assertThat(fields.get(0).getValue()).isEqualTo("value1");
+
+			assertThat(fields.get(1).getName()).isEqualTo("key");
+			assertThat(fields.get(1).getValue()).isEqualTo("value2");
+		}
+
+		@Test
+		void shouldMapValueList() {
+			var fields = mapper.mapStringListsToFields(Map.of(FIELD_NAME, Map.of(LABEL_KEY, FIELD_LABEL, VALUE_KEY, List.of(FIELD_VALUE))));
+
+			assertThat(fields).hasSize(1).first().extracting(GrpcFormField::getValue).isEqualTo(FIELD_VALUE);
+		}
+
+		@Test
+		void shouldAddLabel() {
+			var fields = mapper.mapStringListsToFields(Map.of(FIELD_NAME, Map.of(LABEL_KEY, FIELD_LABEL, VALUE_KEY, List.of(FIELD_VALUE))));
+
+			assertThat(fields).hasSize(1).first().extracting(GrpcFormField::getLabel).isEqualTo(FIELD_LABEL);
+		}
+	}
+
+	@Nested
+	class TestMapObjectListsToFields {
+
+		@Captor
+		private ArgumentCaptor<Entry<String, Object>> entryCaptor;
+
+		@Test
+		void simpleValueShouldNotBeMapped() {
+			List<GrpcSubForm> fields = mapper.mapObjectListsToFields(Map.of("a", "b"));
+
+			assertThat(fields).isEmpty();
+		}
+
+		@Test
+		void listOfSimpleValueShouldNotBeMapped() {
+			List<GrpcSubForm> fields = mapper.mapObjectListsToFields(Map.of("a", List.of("l1", "l2")));
+
+			assertThat(fields).isEmpty();
+		}
+
+		@Test
+		void listOfObjectsShouldBeMappedToSubForms() {
+			List<GrpcSubForm> fields = mapper
+					.mapObjectListsToFields(Map.of("key", List.of(Collections.emptyMap(), Collections.emptyMap())));
+
+			assertThat(fields).hasSize(2);
+		}
+
+		@Test
+		void listOfObjectsShouldMappedToSubFormTitle() {
+			List<GrpcSubForm> fields = mapper.mapObjectListsToFields(Map.of("key", List.of(Collections.emptyMap(), Collections.emptyMap())));
+
+			assertThat(fields.get(0).getTitle()).isEqualTo("key");
+			assertThat(fields.get(1).getTitle()).isEqualTo("key");
+		}
+
+		@Test
+		void listOfObjectsShouldBeMapped() {
+			List<GrpcSubForm> fields = mapper.mapObjectListsToFields(Map.of("key", List.of(Map.of("a1", "a2"))));
+
+			assertThat(fields.get(0).getFieldCount()).isEqualTo(1);
+			assertThat(fields.get(0).getField(0).getName()).isEqualTo("a1");
+			assertThat(fields.get(0).getField(0).getValue()).isEqualTo("a2");
+		}
+
+		@Test
+		void shouldMapSubForm() {
+			List<GrpcSubForm> subForms = mapper.mapObjectListsToFields(Map.of(SUBFORM_TITLE, List.of(SUBFORM)));
+
+			assertThat(subForms).hasSize(1);
+
+			assertThat(subForms.get(0).getField(0).getName()).isEqualTo(SUBFORM_FIELD_NAME);
+			assertThat(subForms.get(0).getField(0).getValue()).isEqualTo(SUBFORM_FIELD_VALUE);
+		}
+
+		@Test
+		void shouldMapListOfObjectsWithLabel() {
+			List<GrpcSubForm> subForms = mapper.mapObjectListsToFields(Map.of(SUBFORM_TITLE, List.of(SUBFORM)));
+
+			assertThat(subForms).hasSize(1);
+			var subForm = subForms.get(0);
+
+			assertThat(subForm.getLabel()).isEqualTo(SUBFORM_LABEL);
+			assertThat(subForm.getField(0).getLabel()).isEqualTo(SUBFORM_FIELD_LABEL);
+		}
+
+		@Test
+		void doubleNestedListObjectValuesShouldBeMapped() {
+			GrpcFormData formData = mapper.mapToFormData(Map.of("key1", Map.of("key2", List.of("value1", "value2"))));
+
+			assertThat(formData.getForm(0).getFieldCount()).isEqualTo(2);
+		}
+
+		@Test
+		void multipleNestedListObjectValuesShouldBeMapped() {
+			GrpcFormData formData = mapper.mapToFormData(Map.of("key1", Map.of("key2", Map.of("key3", List.of("value1", "value2")))));
+
+			assertThat(formData.getForm(0).getSubForm(0).getFieldCount()).isEqualTo(2);
+		}
+
+		@Test
+		void shouldCallMappingMethodForValueList() {
+			mapper.mapObjectListsToFields(Map.of(FIELD_NAME, Map.of(LABEL_KEY, FIELD_LABEL, VALUE_KEY, List.of(SUBFORM))));
+
+			verify(mapper).mapListObjectElementsToFormFields(entryCaptor.capture());
+			assertThat(entryCaptor.getValue().getKey()).isEqualTo(FIELD_NAME);
+			assertThat(entryCaptor.getValue().getValue()).isInstanceOf(Map.class);
+		}
+
+		@Test
+		void shouldAddLabel() {
+			var subForms = mapper.mapObjectListsToFields(Map.of(FIELD_NAME, Map.of(LABEL_KEY, FIELD_LABEL, VALUE_KEY, List.of(SUBFORM))));
+
+			assertThat(subForms).hasSize(1).first().extracting(GrpcSubForm::getLabel).isEqualTo(SUBFORM_LABEL);
+		}
+	}
+
+	@Nested
+	class TestMapListOfMixedValuesInFormData {
+
+		@Test
+		void shouldMapListOfStrings() {
+			GrpcFormData formData = mapper
+					.mapToFormData(Map.of("key", List.of("value1", "value2", Map.of("internKey1", "internValue1"))));
+
+			assertThat(formData.getFieldCount()).isEqualTo(2);
+			assertThat(formData.getFormCount()).isEqualTo(1);
+		}
+	}
+
+	@Nested
+	class TestMapListObjectElementsToFormFields {
+		@Test
+		void shouldMapValueMap() {
+			Map<String, Object> formData = Map.of(FIELD_NAME, Map.of(LABEL_KEY, FIELD_LABEL, VALUE_KEY, List.of(SUBFORM)));
+
+			var result = mapper.mapListObjectElementsToFormFields(formData.entrySet().iterator().next());
+
+			assertThat(result).hasSize(1).first().extracting(GrpcSubForm::getTitle).isEqualTo(FIELD_NAME);
+		}
+
+		@Test
+		void shouldAddLabel() {
+			Map<String, Object> formData = Map.of(FIELD_NAME, Map.of(LABEL_KEY, FIELD_LABEL, VALUE_KEY, List.of(SUBFORM)));
+
+			var result = mapper.mapListObjectElementsToFormFields(formData.entrySet().iterator().next());
+
+			assertThat(result).hasSize(1).first().extracting(GrpcSubForm::getLabel).isEqualTo(SUBFORM_LABEL);
+		}
+	}
+
+	@Nested
+	class TestBuildSubForm {
+
+		@Test
+		void shouldHaveLabel() {
+			var grpc = mapper.buildSubForm(SUBFORM_TITLE, SUBFORM);
+
+			assertThat(grpc.getLabel()).isEqualTo(SUBFORM_LABEL);
+		}
+
+	}
+}
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataTestFactory.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..08e75094b0787c2ab7b7fcdb56a13d40647d740d
--- /dev/null
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormDataTestFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFormData;
+import de.ozgcloud.vorgang.vorgang.GrpcFormData.Builder;
+
+public class GrpcFormDataTestFactory {
+
+	public static GrpcFormData create() {
+		return createBuilder().build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcFormData.newBuilder()
+				.addField(GrpcFormFieldTestFactory.create());
+	}
+}
diff --git a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcFormFieldTestFactory.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormFieldTestFactory.java
similarity index 72%
rename from pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcFormFieldTestFactory.java
rename to vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormFieldTestFactory.java
index 7388b0035de568a9269f6d10f0a00b66c11f2245..a5e53a88ee181be803ca8b39b5ceb54d993de55b 100644
--- a/pluto-utils/src/test/java/de/itvsh/kop/pluto/common/grpc/GrpcFormFieldTestFactory.java
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcFormFieldTestFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
  * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
@@ -21,22 +21,24 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-package de.itvsh.kop.pluto.common.grpc;
+package de.ozgcloud.vorgang.common.grpc;
 
-import de.itvsh.ozg.pluto.vorgang.GrpcFormField;
+import de.ozgcloud.vorgang.vorgang.GrpcFormField;
 
 public class GrpcFormFieldTestFactory {
 
-	public static final String TEST_NAME = "name";
-	public static final String TEST_VALUE = "value";
+	public static final String NAME = "name";
+	public static final String VALUE = "value";
+	public static final String LABEL = "label";
 
 	public static GrpcFormField create() {
 		return createBuilder().build();
 	}
 
-	private static GrpcFormField.Builder createBuilder() {
+	public static GrpcFormField.Builder createBuilder() {
 		return GrpcFormField.newBuilder()
-				.setName(TEST_NAME)
-				.setValue(TEST_VALUE);
+				.setName(NAME)
+				.setValue(VALUE)
+				.setLabel(LABEL);
 	}
 }
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectMapperTest.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b891576ab691f11ba00ef852ad4a10030ce5b6aa
--- /dev/null
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectMapperTest.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import static de.ozgcloud.vorgang.common.grpc.GrpcObjectTestFactory.createAsMap;
+import static de.ozgcloud.vorgang.common.grpc.GrpcPropertyTestFactory.*;
+import static de.ozgcloud.vorgang.common.grpc.GrpcSubObjectTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.time.LocalDate;
+import java.time.ZonedDateTime;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mapstruct.factory.Mappers;
+import org.mockito.Spy;
+
+import de.ozgcloud.common.binaryfile.FileId;
+import de.ozgcloud.vorgang.common.GrpcObject;
+import de.ozgcloud.vorgang.common.GrpcProperty;
+import de.ozgcloud.vorgang.common.GrpcSubObject;
+
+class GrpcObjectMapperTest {
+
+	@Spy
+	private final GrpcObjectMapper mapper = Mappers.getMapper(GrpcObjectMapper.class);
+
+	@DisplayName("From map")
+	@Nested
+	class TestFromMap {
+
+		@Test
+		void shouldCallMapToAllProperties() {
+			var sourceMap = createAsMap();
+
+			mapper.fromMap(sourceMap);
+
+			verify(mapper).mapToAllProperties(sourceMap);
+		}
+
+		@Test
+		void shouldCallMapToSubObjects() {
+			var sourceMap = createAsMap();
+
+			mapper.fromMap(sourceMap);
+
+			verify(mapper).mapToSubObjects(sourceMap);
+		}
+
+		@Test
+		void shouldMapToGrpcObject() {
+			var sourceMap = createAsMap();
+
+			var grpcObject = mapper.fromMap(sourceMap);
+
+			assertThat(grpcObject).isEqualTo(GrpcObjectTestFactory.create());
+		}
+
+		@DisplayName("should map type")
+		@Nested
+		class TestByType {
+
+			@DisplayName("Long")
+			@Test
+			void shouldMapLongMapToGrpc() {
+				var value = 42L;
+				var expectedProperty = GrpcPropertyTestFactory.createWithValue(value);
+
+				var grpcObject = mapFromMap(value);
+
+				assertThat(grpcObject.getPropertyList()).hasSize(1).first().isEqualTo(expectedProperty);
+			}
+
+			@DisplayName("Integer")
+			@Test
+			void shouldMapIntegerMapToGrpc() {
+				var expectedProperty = GrpcPropertyTestFactory.createWithValue(Integer.MAX_VALUE);
+
+				var grpcObject = mapFromMap(Integer.MAX_VALUE);
+
+				assertThat(grpcObject.getPropertyList()).hasSize(1).first().isEqualTo(expectedProperty);
+			}
+
+			@DisplayName("Boolean")
+			@Test
+			void shouldMapBooleanMapToGrpc() {
+				var expectedProperty = GrpcPropertyTestFactory.createWithValue(Boolean.TRUE);
+
+				var grpcObject = mapFromMap(Boolean.TRUE);
+
+				assertThat(grpcObject.getPropertyList()).hasSize(1).first().isEqualTo(expectedProperty);
+			}
+
+			@DisplayName("LocalDate")
+			@Test
+			void shouldMapLocalDateMapToGrpc() {
+				var date = "2022-12-11";
+				var expectedProperty = GrpcPropertyTestFactory.createWithValue(date);
+
+				var grpcObject = mapFromMap(LocalDate.parse(date));
+
+				assertThat(grpcObject.getPropertyList()).hasSize(1).first().isEqualTo(expectedProperty);
+			}
+
+			@DisplayName("ZonedDateTime")
+			@Test
+			void shouldMapZonedDateTimeMapToGrpc() {
+				var zonedDateTime = "2007-12-03T10:15:30+01:00";
+				var expectedProperty = GrpcPropertyTestFactory.createWithValue(zonedDateTime);
+
+				var grpcObject = mapFromMap(ZonedDateTime.parse(zonedDateTime));
+
+				assertThat(grpcObject.getPropertyList()).hasSize(1).first().isEqualTo(expectedProperty);
+			}
+
+			@DisplayName("FileId")
+			@Test
+			void shouldMapFileIdMapToGrpc() {
+				var fileId = FileId.createNew();
+				var expectedProperty = GrpcPropertyTestFactory.createWithValue(fileId);
+
+				var grpcObject = mapFromMap(fileId);
+
+				assertThat(grpcObject.getPropertyList()).hasSize(1).first().isEqualTo(expectedProperty);
+			}
+
+			private GrpcObject mapFromMap(Object value) {
+				return mapper.fromMap(Map.of(PROPERTY_NAME, value));
+			}
+
+		}
+	}
+
+	@DisplayName("Map all properties")
+	@Nested
+	class TestMapAllProperties {
+
+		private Map<String, Object> propertyMap = Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE);
+
+		@Test
+		void shouldCallMapToProperty() {
+			mapper.mapToAllProperties(propertyMap);
+
+			verify(mapper, times(1)).mapToProperty(PROPERTY_NAME, PROPERTY_NAME_VALUE);
+		}
+
+		@Test
+		void shouldMapToProperty() {
+			var grpcProperties = mapper.mapToAllProperties(propertyMap);
+
+			assertThat(grpcProperties).isEqualTo(List.of(GrpcPropertyTestFactory.create()));
+		}
+
+		@Test
+		void shouldNotCallMapToPropertyOnMap() {
+			mapper.mapToAllProperties(Map.of(PROPERTY_NAME, propertyMap));
+
+			verify(mapper, never()).mapToProperty(any(), any());
+		}
+	}
+
+	@DisplayName("Map property")
+	@Nested
+	class TestMapProperty {
+
+		@DisplayName("should map null value of property to an empty string")
+		@Test
+		void shouldMapNullValueToEmptyString() {
+			var grpcProperty = mapper.mapToProperty(PROPERTY_NAME, null);
+
+			assertThat(grpcProperty.getValueList()).containsExactly(StringUtils.EMPTY);
+		}
+
+		@DisplayName("should map if value is a collection")
+		@Test
+		void shouldMapValueAsCollection() {
+			var grpcProperty = mapper.mapToProperty(PROPERTY_NAME, Set.of(PROPERTY_NAME_VALUE, "another_value"));
+
+			assertThat(grpcProperty.getValueList()).containsExactlyInAnyOrder(PROPERTY_NAME_VALUE, "another_value");
+		}
+
+		@DisplayName("should map if value is a collection containing null")
+		@Test
+		void shouldMapValueAsCollectionContainsNull() {
+			var listContainsNull = Collections.singletonList(null);
+
+			var grpcProperty = mapper.mapToProperty(PROPERTY_NAME, listContainsNull);
+
+			assertThat(grpcProperty.getValueList()).containsExactly(StringUtils.EMPTY);
+		}
+
+		@DisplayName("should map if value is a list considering the order of the values")
+		@Test
+		void shouldMapValueAsListConsideringOrder() {
+			var list = List.of("firstProperty", "secondProperty");
+
+			var grpcProperty = mapper.mapToProperty(PROPERTY_NAME, list);
+
+			assertThat(grpcProperty.getValueList()).containsExactly("firstProperty", "secondProperty");
+		}
+
+	}
+
+	@DisplayName("Map subObject")
+	@Nested
+	class TestMapSubObject {
+
+		@Test
+		void shouldCallBuildSubObject() {
+			var propertyValueAsMap = Map.<String, Object>of("additionalPropertName", "additionalPropertyNameValue");
+			mapper.mapToSubObjects(Map.of(PROPERTY_NAME, propertyValueAsMap));
+
+			verify(mapper).buildSubObject(PROPERTY_NAME, propertyValueAsMap);
+		}
+
+		@Test
+		void shouldNotCallBuildSubObjectOnNonMapValue() {
+			mapper.mapToSubObjects(Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE));
+
+			verify(mapper, never()).buildSubObject(any(), any());
+		}
+	}
+
+	@DisplayName("Build subObject")
+	@Nested
+	class TestBuildSubObject {
+
+		@Test
+		void shouldCallMapAllProperties() {
+			mapper.buildSubObject(PROPERTY_NAME, GrpcPropertyTestFactory.createAsMap());
+
+			verify(mapper).mapToAllProperties(GrpcPropertyTestFactory.createAsMap());
+		}
+
+		@Test
+		void shouldCallMapSubObject() {
+			mapper.buildSubObject(PROPERTY_NAME, GrpcPropertyTestFactory.createAsMap());
+
+			verify(mapper).mapToSubObjects(GrpcPropertyTestFactory.createAsMap());
+		}
+
+		@Test
+		void shouldAddPropertiesToSubObject() {
+			var wantedProperty = GrpcPropertyTestFactory.create();
+
+			var grpcSubObject = mapper.buildSubObject(GrpcSubObjectTestFactory.SUB_OBJECT_NAME, Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE));
+
+			assertThat(grpcSubObject.getPropertyList()).hasSize(1).first().isEqualTo(wantedProperty);
+		}
+	}
+
+	@Nested
+	class TestMapFromGrpcProperty {
+
+		@Test
+		@DisplayName("should map grpc property into map")
+		void shouldMapProperty() {
+			var targetMap = mapper.mapProperty(GrpcPropertyTestFactory.create());
+
+			assertThat(targetMap).isEqualTo(Pair.of(PROPERTY_NAME, PROPERTY_NAME_VALUE));
+		}
+
+		@Test
+		@DisplayName("should map property with collection as value to map")
+		void shouldMapAllPropertyValues() {
+			var anotherValue = "anotherPropertyValue";
+			var grpcProperty = GrpcPropertyTestFactory.createBuilder().addValue(anotherValue).build();
+
+			var targetMap = mapper.mapProperty(grpcProperty);
+
+			assertThat(targetMap).isEqualTo(Pair.of(PROPERTY_NAME, List.of(PROPERTY_NAME_VALUE, anotherValue)));
+		}
+
+		@Test
+		@DisplayName("should map property without value to map")
+		void shouldMapEmptyProperty() {
+			var targetMap = mapper.mapProperty(GrpcPropertyTestFactory.createWithoutValue());
+
+			assertThat(targetMap).isEqualTo(Pair.of(PROPERTY_NAME, null));
+		}
+
+		@Test
+		void shouldTrimToNull() {
+			GrpcProperty grpcProperty = GrpcPropertyTestFactory.createBuilder().addValue(StringUtils.EMPTY).build();
+
+			var resultEntry = mapper.mapProperty(grpcProperty);
+
+			assertThat(resultEntry).isEqualTo(Pair.of(PROPERTY_NAME, Arrays.asList(PROPERTY_NAME_VALUE, null)));
+		}
+
+	}
+
+	@Nested
+	class TestMapFromGrpcObject {
+
+		@Test
+		void shouldMapFromGrpcObject() {
+			Map<String, Object> wantedMap = Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE, SUB_OBJECT_NAME, createSubObjectMap());
+			var map = mapper.mapFromGrpc(GrpcObjectTestFactory.create());
+
+			assertThat(map).containsAllEntriesOf(wantedMap);
+		}
+	}
+
+	@Nested
+	class TestMapFromSubObject {
+
+		@Test
+		@DisplayName("should map subObject into a map")
+		void shouldMapSubObject() {
+			var resultMap = mapper.mapSubObject(GrpcSubObjectTestFactory.create());
+
+			assertThat(resultMap).containsAllEntriesOf(createSubObjectMap());
+		}
+
+		@Test
+		@DisplayName("should map empty property values of subObject to nulls")
+		void shouldMapSubObjectEmptyValues() {
+			var grpcSubObject = GrpcSubObject.newBuilder().setName(SUB_OBJECT_NAME).addProperty(createWithoutValue()).build();
+
+			var resultMap = mapper.mapSubObject(grpcSubObject);
+
+			assertThat(resultMap).containsEntry(PROPERTY_NAME, null);
+		}
+
+	}
+
+	private static Map<String, Object> createSubObjectMap() {
+		return Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE, SUB_SUB_OBJECT_NAME, Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE));
+	}
+}
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectTestFactory.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..47502cbcda0fe96f657c90e6e66fc6f9ddce4970
--- /dev/null
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcObjectTestFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import static de.ozgcloud.vorgang.common.grpc.GrpcPropertyTestFactory.*;
+import static de.ozgcloud.vorgang.common.grpc.GrpcSubObjectTestFactory.*;
+
+import java.util.Map;
+
+import de.ozgcloud.vorgang.common.GrpcObject;
+
+public class GrpcObjectTestFactory {
+
+	public static GrpcObject create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcObject.Builder createBuilder() {
+		return GrpcObject.newBuilder()
+				.addProperty(GrpcPropertyTestFactory.create())
+				.addSubObject(GrpcSubObjectTestFactory.create());
+	}
+
+	public static Map<String, Object> createAsMap() {
+		var subSubMap = Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE);
+		var subMap = Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE, SUB_SUB_OBJECT_NAME, subSubMap);
+		return Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE, SUB_OBJECT_NAME, subMap);
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcPropertyTestFactory.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcPropertyTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..f81643b9f084ae0c1f627c6f52441b9074d1e39b
--- /dev/null
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcPropertyTestFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import java.util.Map;
+
+import de.ozgcloud.vorgang.common.GrpcProperty;
+import de.ozgcloud.vorgang.common.GrpcProperty.Builder;
+
+public class GrpcPropertyTestFactory {
+
+	public static final String PROPERTY_NAME = "propertyName";
+	public static final String PROPERTY_NAME_VALUE = "propertyNameValue";
+
+	public static GrpcProperty create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcProperty createWithoutValue() {
+		return createBuilder().clearValue().build();
+	}
+	public static GrpcProperty createWithValue(Object value) {
+		return createBuilder().clearValue().addValue(String.valueOf(value)).build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcProperty.newBuilder()
+				.setName(PROPERTY_NAME)
+				.addValue(PROPERTY_NAME_VALUE);
+	}
+
+	public static Map<String, Object> createAsMap() {
+		return Map.of(PROPERTY_NAME, PROPERTY_NAME_VALUE);
+	}
+}
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcSubFormTestFactory.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcSubFormTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..875c6d2a8707ac9e6bf9b76f870cbfec8bf97dbb
--- /dev/null
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcSubFormTestFactory.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import static de.ozgcloud.vorgang.common.grpc.FormDataMappingUtils.*;
+
+import java.util.Map;
+
+import de.ozgcloud.vorgang.vorgang.GrpcFormField;
+import de.ozgcloud.vorgang.vorgang.GrpcSubForm;
+
+public class GrpcSubFormTestFactory {
+
+	public static final String TITLE = "kontakt";
+	public static final String LABEL = "Alternative kontakt Label";
+
+	public static final String FIELD_NAME = "vorname";
+	public static final String FIELD_VALUE = "Thea";
+	public static final String FIELD_LABEL = "Alternative name Label";
+	public static final Map<String, Object> FIELD = Map.of(LABEL_KEY, FIELD_LABEL, VALUE_KEY, FIELD_VALUE);
+
+	public static final String SUBFORM_TITLE = "otherData";
+	public static final String SUBFORM_LABEL = "Alternative otherData label";
+
+	public static final String SUBFORM_FIELD_NAME = "E-Mail";
+	public static final String SUBFORM_FIELD_VALUE = "thea@mailinator.de";
+	public static final String SUBFORM_FIELD_LABEL = "Alternative E-mail label";
+	public static final Map<String, Object> SUBFORM_FIELD = Map.of(VALUE_KEY, SUBFORM_FIELD_VALUE, LABEL_KEY, SUBFORM_FIELD_LABEL);
+
+	public static final Map<String, Object> SUBFORM = Map.of(VALUE_KEY, Map.of(SUBFORM_FIELD_NAME, SUBFORM_FIELD), LABEL_KEY, SUBFORM_LABEL);
+
+	public static GrpcSubForm create() {
+		return createBuilder().build();
+	}
+
+	public static GrpcSubForm.Builder createBuilder() {
+		return GrpcSubForm.newBuilder()
+				.setTitle(TITLE).setLabel(LABEL)
+				.addField(GrpcFormField.newBuilder().setName(FIELD_NAME).setValue(FIELD_VALUE).setLabel(FIELD_LABEL).build())
+				.addSubForm(GrpcSubForm.newBuilder().setTitle(SUBFORM_TITLE).setLabel(SUBFORM_LABEL)
+						.addField(GrpcFormField.newBuilder()
+								.setName(SUBFORM_FIELD_NAME)
+								.setLabel(SUBFORM_FIELD_LABEL)
+								.setValue(SUBFORM_FIELD_VALUE)
+								.build()));
+	}
+
+	public static GrpcSubForm createWithLabels() {
+		return createWithLabelsBuilder().build();
+	}
+
+	public static GrpcSubForm.Builder createWithLabelsBuilder() {
+		return GrpcSubForm.newBuilder()
+				.setTitle(TITLE)
+				.addField(GrpcFormField.newBuilder().setName(FIELD_NAME).setValue(FIELD_VALUE).setLabel(FIELD_LABEL))
+				.addSubForm(GrpcSubForm.newBuilder().setTitle(SUBFORM_TITLE).setLabel(SUBFORM_LABEL)
+						.addField(GrpcFormField.newBuilder()
+								.setName(SUBFORM_FIELD_NAME)
+								.setValue(SUBFORM_FIELD_VALUE)
+								.setLabel(SUBFORM_FIELD_LABEL)
+								.build()))
+				.setLabel(LABEL);
+	}
+}
\ No newline at end of file
diff --git a/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcSubObjectTestFactory.java b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcSubObjectTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec9751b89bac884e79fb3d7ae64045febcc71c87
--- /dev/null
+++ b/vorgang-manager-utils/src/test/java/de/ozgcloud/vorgang/common/grpc/GrpcSubObjectTestFactory.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.common.grpc;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.vorgang.common.GrpcSubObject;
+import de.ozgcloud.vorgang.common.GrpcSubObject.Builder;
+
+public class GrpcSubObjectTestFactory {
+
+	public static final String SUB_OBJECT_NAME = LoremIpsum.getInstance().getWords(1);
+	public static final String SUB_SUB_OBJECT_NAME = LoremIpsum.getInstance().getWords(1);
+
+	public static GrpcSubObject create() {
+		return createBuilder().build();
+	}
+
+	public static Builder createBuilder() {
+		return GrpcSubObject.newBuilder()
+				.setName(SUB_OBJECT_NAME)
+				.addProperty(GrpcPropertyTestFactory.create())
+				.addSubObject(GrpcSubObject.newBuilder()
+						.setName(SUB_SUB_OBJECT_NAME)
+						.addProperty(GrpcPropertyTestFactory.create()));
+	}
+}
diff --git a/vorgang-manager-utils/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/vorgang-manager-utils/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 0000000000000000000000000000000000000000..79b126e6cdb86bec1f4f08c205de8961bde1934a
--- /dev/null
+++ b/vorgang-manager-utils/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1 @@
+org.mockito.junit.jupiter.MockitoExtension
\ No newline at end of file
diff --git a/vorgang-manager-utils/src/test/resources/junit-platform.properties b/vorgang-manager-utils/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1cebb76d5a58ac034b2627d12411d82d1e85821e
--- /dev/null
+++ b/vorgang-manager-utils/src/test/resources/junit-platform.properties
@@ -0,0 +1 @@
+junit.jupiter.extensions.autodetection.enabled = true
\ No newline at end of file