diff --git a/admin-portal/src/lib/components/table/Filter.tsx b/admin-portal/src/lib/components/table/Filter.tsx
index 9a0bb201791f8d14c51a3ba018c66129cf489217..93d3c2eb50b965dcee02d3717875f642be14c136 100644
--- a/admin-portal/src/lib/components/table/Filter.tsx
+++ b/admin-portal/src/lib/components/table/Filter.tsx
@@ -35,6 +35,10 @@ import {
   HeaderButtons,
 } from "@/lib/components/table/addEditColumns";
 import { getActiveLabel } from "@/lib/components/table/cell/ActiveCell";
+import {
+  formatActorSelector,
+  isActorSelector,
+} from "@/lib/components/table/cell/StaticActorSelectorCell";
 import { Actor } from "@/lib/components/view/actors/ActorTable";
 import { UniqueEntity } from "@/lib/helpers/entities";
 import { entityToString } from "@/lib/helpers/entityToString";
@@ -140,7 +144,7 @@ export function Filter<TData extends UniqueEntity, TValue>({
 function getColumnValues<TData extends UniqueEntity, TValue>(
   column: Column<TData, TValue>,
   table: Table<TData>,
-) {
+): string[] {
   return unique(
     table
       .getCenterRows()
@@ -166,6 +170,9 @@ function getLabels(value: unknown): string[] {
   if (isEntity(value)) {
     return [entityToString(value, true)];
   }
+  if (isActorSelector(value)) {
+    return [formatActorSelector(value)];
+  }
   return [String(value)];
 }
 
@@ -299,10 +306,10 @@ export function getActorSelectorFilterFn(
     return thisOrParentOrChildApplies(
       row,
       (orig) =>
-        orig[columnId] !== undefined &&
-        Object.values(orig[columnId]).some((v: string) =>
-          v.toLowerCase().includes(lowerFilterValue),
-        ),
+        !isNullish(orig[columnId]) &&
+        formatActorSelector(orig[columnId])
+          .toLowerCase()
+          .includes(lowerFilterValue),
     );
   };
 }
diff --git a/admin-portal/src/lib/components/table/cell/ActorSelectorCell.tsx b/admin-portal/src/lib/components/table/cell/ActorSelectorCell.tsx
index 17c3c47248b6b9cea660cc13d38e3b8a5dc2a1fc..594c8ab937c36caafff807f03cb44be525a56674 100644
--- a/admin-portal/src/lib/components/table/cell/ActorSelectorCell.tsx
+++ b/admin-portal/src/lib/components/table/cell/ActorSelectorCell.tsx
@@ -173,7 +173,7 @@ function SingleSelect(
     );
   const color = serverError ? "danger" : undefined;
 
-  const value = props.value ? props.value : "*";
+  const value = props.value ?? "*";
   const selectProps: SelectProps<string, false> = {
     value,
     multiple: false,
diff --git a/admin-portal/src/lib/components/table/cell/StaticActorSelectorCell.tsx b/admin-portal/src/lib/components/table/cell/StaticActorSelectorCell.tsx
index 5d57497bb576ac0cd28c323c7f2262244080677c..b5aa354b14099d99eba5fb2b8031d514c7c7f498 100644
--- a/admin-portal/src/lib/components/table/cell/StaticActorSelectorCell.tsx
+++ b/admin-portal/src/lib/components/table/cell/StaticActorSelectorCell.tsx
@@ -47,6 +47,23 @@ export function formatActorSelector(s: ApiAdminActorSelector) {
   return `${format(s.federalState)}/${format(s.orgUnitType)}/${format(s.orgUnitName)}/${format(s.actorType)}/${format(s.actorName)}`;
 }
 
+export function isActorSelector(s: unknown): s is ApiAdminActorSelector {
+  return (
+    typeof s === "object" &&
+    s !== null &&
+    "federalState" in s &&
+    ["string", "undefined"].includes(typeof s.federalState) &&
+    "orgUnitType" in s &&
+    ["string", "undefined"].includes(typeof s.orgUnitType) &&
+    "orgUnitName" in s &&
+    ["string", "undefined"].includes(typeof s.orgUnitName) &&
+    "actorType" in s &&
+    ["string", "undefined"].includes(typeof s.actorType) &&
+    "actorName" in s &&
+    ["string", "undefined"].includes(typeof s.actorName)
+  );
+}
+
 function format(value: string | undefined): string {
   if (value == null) {
     return "*";
diff --git a/admin-portal/src/lib/components/table/cell/StringCell.tsx b/admin-portal/src/lib/components/table/cell/StringCell.tsx
index 2ac9d5e6ae9f76dbf42ab2c13472c815d1a0e158..8641f0227ccc17d79d1caff248a03a3afbc6ac8c 100644
--- a/admin-portal/src/lib/components/table/cell/StringCell.tsx
+++ b/admin-portal/src/lib/components/table/cell/StringCell.tsx
@@ -44,7 +44,7 @@ function EditableStringCell(
     [props.column.id, props.row, props.table.options.meta],
   );
 
-  const value = props.getValue();
+  const value = props.getValue() ?? "";
   const serverError =
     !!errorMessage?.ids.includes(props.row.original.id) &&
     !!errorMessage?.columns?.includes(props.column.id);
diff --git a/backend/api-commons/build.gradle b/backend/api-commons/build.gradle
index a611b99d75e66f13120296a7a81e1319cef5bfb1..1b1a36461d3c47338e57edb248b4d6e415a53d49 100644
--- a/backend/api-commons/build.gradle
+++ b/backend/api-commons/build.gradle
@@ -7,4 +7,9 @@ dependencies {
     api 'com.fasterxml.jackson.core:jackson-annotations'
     api 'io.swagger.core.v3:swagger-annotations-jakarta:latest.release'
     api 'org.springframework:spring-web'
+
+    testImplementation project(':test-commons')
+    testRuntimeOnly 'org.hibernate.validator:hibernate-validator'
+    testRuntimeOnly 'jakarta.el:jakarta.el-api:latest.release'
+    testRuntimeOnly 'org.glassfish:jakarta.el:latest.release'
 }
diff --git a/backend/api-commons/gradle.lockfile b/backend/api-commons/gradle.lockfile
index f7af9e94fd2830ba8c91f01f42aa78daf4970cac..b63032b0314f39f640cdcba969559c3c1cb7f75d 100644
--- a/backend/api-commons/gradle.lockfile
+++ b/backend/api-commons/gradle.lockfile
@@ -4,30 +4,70 @@
 ch.qos.logback:logback-classic:1.5.12=testCompileClasspath,testRuntimeClasspath
 ch.qos.logback:logback-core:1.5.12=testCompileClasspath,testRuntimeClasspath
 com.fasterxml.jackson.core:jackson-annotations:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+com.fasterxml.jackson.core:jackson-core:2.18.2=testRuntimeClasspath
+com.fasterxml.jackson.core:jackson-databind:2.18.2=testRuntimeClasspath
 com.fasterxml.jackson:jackson-bom:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+com.fasterxml:classmate:1.7.0=testRuntimeClasspath
+com.github.docker-java:docker-java-api:3.4.0=testRuntimeClasspath
+com.github.docker-java:docker-java-transport-zerodep:3.4.0=testRuntimeClasspath
+com.github.docker-java:docker-java-transport:3.4.0=testRuntimeClasspath
+com.github.gavlyukovskiy:datasource-decorator-spring-boot-autoconfigure:1.10.0=testRuntimeClasspath
+com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.10.0=testRuntimeClasspath
+com.google.code.findbugs:jsr305:3.0.2=testRuntimeClasspath
+com.google.errorprone:error_prone_annotations:2.28.0=testRuntimeClasspath
+com.google.guava:failureaccess:1.0.2=testRuntimeClasspath
+com.google.guava:guava:33.3.1-jre=testRuntimeClasspath
+com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=testRuntimeClasspath
+com.google.j2objc:j2objc-annotations:3.0.0=testRuntimeClasspath
+com.googlecode.java-diff-utils:diffutils:1.3.0=testCompileClasspath,testRuntimeClasspath
 com.jayway.jsonpath:json-path:2.9.0=testCompileClasspath,testRuntimeClasspath
+com.tngtech.archunit:archunit-junit5-api:1.3.0=testRuntimeClasspath
+com.tngtech.archunit:archunit-junit5-engine-api:1.3.0=testRuntimeClasspath
+com.tngtech.archunit:archunit-junit5-engine:1.3.0=testRuntimeClasspath
+com.tngtech.archunit:archunit-junit5:1.3.0=testRuntimeClasspath
+com.tngtech.archunit:archunit:1.3.0=testRuntimeClasspath
 com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath
+commons-io:commons-io:2.18.0=testRuntimeClasspath
+de.cronn:commons-lang:1.3=testCompileClasspath,testRuntimeClasspath
+de.cronn:postgres-snapshot-util:1.4=testRuntimeClasspath
+de.cronn:test-utils:1.1.1=testCompileClasspath,testRuntimeClasspath
+de.cronn:validation-file-assertions:0.8.0=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
+jakarta.el:jakarta.el-api:6.0.1=testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=testCompileClasspath,testRuntimeClasspath
+junit:junit:4.13.2=testRuntimeClasspath
 net.bytebuddy:byte-buddy-agent:1.15.11=testCompileClasspath,testRuntimeClasspath
 net.bytebuddy:byte-buddy:1.15.11=testCompileClasspath,testRuntimeClasspath
+net.java.dev.jna:jna:5.13.0=testRuntimeClasspath
 net.minidev:accessors-smart:2.5.1=testCompileClasspath,testRuntimeClasspath
 net.minidev:json-smart:2.5.1=testCompileClasspath,testRuntimeClasspath
+net.ttddyy:datasource-proxy:1.10=testRuntimeClasspath
+org.apache.commons:commons-compress:1.24.0=testRuntimeClasspath
+org.apache.commons:commons-lang3:3.17.0=testRuntimeClasspath
 org.apache.logging.log4j:log4j-api:2.24.3=testCompileClasspath,testRuntimeClasspath
 org.apache.logging.log4j:log4j-to-slf4j:2.24.3=testCompileClasspath,testRuntimeClasspath
 org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
+org.bouncycastle:bcpkix-jdk18on:1.80=testRuntimeClasspath
+org.bouncycastle:bcprov-jdk18on:1.80=testRuntimeClasspath
+org.bouncycastle:bcutil-jdk18on:1.80=testRuntimeClasspath
+org.checkerframework:checker-qual:3.43.0=testRuntimeClasspath
+org.glassfish:jakarta.el:4.0.2=testRuntimeClasspath
+org.hamcrest:hamcrest-core:2.2=testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.hibernate.validator:hibernate-validator:8.0.2.Final=testRuntimeClasspath
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
+org.jboss.logging:jboss-logging:3.6.1.Final=testRuntimeClasspath
+org.jetbrains:annotations:17.0.0=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -40,19 +80,24 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
+org.postgresql:postgresql:42.7.4=testRuntimeClasspath
+org.rnorth.duct-tape:duct-tape:1.0.8=testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=testCompileClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-dependencies:3.3.5=testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-test-autoconfigure:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-test:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot:3.4.1=testCompileClasspath,testRuntimeClasspath
+org.springframework.data:spring-data-commons:3.4.1=testRuntimeClasspath
 org.springframework:spring-aop:6.2.1=testCompileClasspath,testRuntimeClasspath
 org.springframework:spring-beans:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework:spring-context:6.2.1=testCompileClasspath,testRuntimeClasspath
@@ -61,6 +106,8 @@ org.springframework:spring-expression:6.2.1=testCompileClasspath,testRuntimeClas
 org.springframework:spring-jcl:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework:spring-test:6.2.1=testCompileClasspath,testRuntimeClasspath
 org.springframework:spring-web:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springframework:spring-webmvc:6.2.1=testRuntimeClasspath
+org.testcontainers:testcontainers:1.20.4=testRuntimeClasspath
 org.xmlunit:xmlunit-core:2.10.0=testCompileClasspath,testRuntimeClasspath
 org.yaml:snakeyaml:2.3=testCompileClasspath,testRuntimeClasspath
 empty=annotationProcessor,developmentOnly,testAndDevelopmentOnly,testAnnotationProcessor,testFixturesCompileClasspath,testFixturesRuntimeClasspath
diff --git a/backend/api-commons/src/main/java/de/eshg/validation/constraints/DateOfBirth.java b/backend/api-commons/src/main/java/de/eshg/validation/constraints/DateOfBirth.java
new file mode 100644
index 0000000000000000000000000000000000000000..402ca0039bb44bc51e94488248e75cefdf6a588b
--- /dev/null
+++ b/backend/api-commons/src/main/java/de/eshg/validation/constraints/DateOfBirth.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.validation.constraints;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Constraint(validatedBy = {DateOfBirthValidator.class})
+public @interface DateOfBirth {
+
+  String message() default "Age must be between {minAgeInclusive} and {maxAgeInclusive} years";
+
+  int minAgeInclusive() default -1;
+
+  int maxAgeInclusive() default 150;
+
+  Class<?>[] groups() default {};
+
+  Class<? extends Payload>[] payload() default {};
+}
diff --git a/backend/api-commons/src/main/java/de/eshg/validation/constraints/DateOfBirthValidator.java b/backend/api-commons/src/main/java/de/eshg/validation/constraints/DateOfBirthValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1a434188beaef41ffaf00d104f330279fe4f4ab
--- /dev/null
+++ b/backend/api-commons/src/main/java/de/eshg/validation/constraints/DateOfBirthValidator.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.validation.constraints;
+
+import jakarta.validation.ClockProvider;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import java.time.Clock;
+import java.time.LocalDate;
+import java.time.Period;
+
+public class DateOfBirthValidator implements ConstraintValidator<DateOfBirth, LocalDate> {
+
+  private Period minAge;
+  private Period maxAge;
+
+  @Override
+  public void initialize(DateOfBirth dateOfBirthAnnotation) {
+    minAge = Period.ofYears(dateOfBirthAnnotation.minAgeInclusive());
+    maxAge = Period.ofYears(dateOfBirthAnnotation.maxAgeInclusive());
+  }
+
+  @Override
+  public boolean isValid(LocalDate date, ConstraintValidatorContext context) {
+    if (date == null) {
+      return true;
+    }
+    ClockProvider clockProvider = context.getClockProvider();
+    Clock clock = clockProvider.getClock();
+    LocalDate today = LocalDate.now(clock);
+    LocalDate latestAllowedDate = today.minus(minAge);
+    LocalDate earliestAllowedDate = today.minus(maxAge);
+    return !latestAllowedDate.isBefore(date) && !date.isBefore(earliestAllowedDate);
+  }
+}
diff --git a/backend/api-commons/src/main/java/de/eshg/CustomValidations/EmailAddressConstraint.java b/backend/api-commons/src/main/java/de/eshg/validation/constraints/EmailAddressConstraint.java
similarity index 95%
rename from backend/api-commons/src/main/java/de/eshg/CustomValidations/EmailAddressConstraint.java
rename to backend/api-commons/src/main/java/de/eshg/validation/constraints/EmailAddressConstraint.java
index 1c358b787458614090e498c64d7b6d6dfc85089d..cda7b9129c4e08afa132ac4fe75b0ff4c0d20c90 100644
--- a/backend/api-commons/src/main/java/de/eshg/CustomValidations/EmailAddressConstraint.java
+++ b/backend/api-commons/src/main/java/de/eshg/validation/constraints/EmailAddressConstraint.java
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-package de.eshg.CustomValidations;
+package de.eshg.validation.constraints;
 
 import jakarta.validation.Constraint;
 import jakarta.validation.Payload;
diff --git a/backend/api-commons/src/main/java/de/eshg/CustomValidations/MandatoryEmailAddressConstraint.java b/backend/api-commons/src/main/java/de/eshg/validation/constraints/MandatoryEmailAddressConstraint.java
similarity index 93%
rename from backend/api-commons/src/main/java/de/eshg/CustomValidations/MandatoryEmailAddressConstraint.java
rename to backend/api-commons/src/main/java/de/eshg/validation/constraints/MandatoryEmailAddressConstraint.java
index b7358b246a9a0fe21ab9dc440310742cb5340893..4a3d891f0f148c8b9ff391c5638fb2bbd7b42e13 100644
--- a/backend/api-commons/src/main/java/de/eshg/CustomValidations/MandatoryEmailAddressConstraint.java
+++ b/backend/api-commons/src/main/java/de/eshg/validation/constraints/MandatoryEmailAddressConstraint.java
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-package de.eshg.CustomValidations;
+package de.eshg.validation.constraints;
 
 import jakarta.validation.Constraint;
 import jakarta.validation.Payload;
diff --git a/backend/auditlog-api/gradle.lockfile b/backend/auditlog-api/gradle.lockfile
index 76b87c3eff62475d07c6742acdf9500446c55c6b..77ac307ea762d83c1180438c5ce0194486dec04c 100644
--- a/backend/auditlog-api/gradle.lockfile
+++ b/backend/auditlog-api/gradle.lockfile
@@ -14,10 +14,10 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -33,10 +33,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -49,13 +49,14 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogClientTestHelperApi.java b/backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogClientTestHelperApi.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7eef56875b0dd96339303719c2266c3cda74fac
--- /dev/null
+++ b/backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogClientTestHelperApi.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.auditlog;
+
+import static de.eshg.auditlog.AuditLogClientTestHelperApi.BASE_URL;
+
+import org.springframework.web.service.annotation.HttpExchange;
+import org.springframework.web.service.annotation.PostExchange;
+
+@HttpExchange(BASE_URL)
+public interface AuditLogClientTestHelperApi {
+
+  String BASE_URL = "/test-helper";
+
+  @PostExchange("archiving-job")
+  void runAuditLogArchivingJob();
+}
diff --git a/backend/auditlog-api/src/main/java/de/eshg/auditlog/SharedAuditLogTestHelperApi.java b/backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogServiceTestHelperApi.java
similarity index 64%
rename from backend/auditlog-api/src/main/java/de/eshg/auditlog/SharedAuditLogTestHelperApi.java
rename to backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogServiceTestHelperApi.java
index c422e0c4d8d0b0d87c30caedd5225f73b8a886a1..7f57bf49f99eb9e180b82cb3c892f06d30a5921c 100644
--- a/backend/auditlog-api/src/main/java/de/eshg/auditlog/SharedAuditLogTestHelperApi.java
+++ b/backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogServiceTestHelperApi.java
@@ -5,21 +5,17 @@
 
 package de.eshg.auditlog;
 
-import static de.eshg.auditlog.SharedAuditLogTestHelperApi.BASE_URL;
+import static de.eshg.auditlog.AuditLogClientTestHelperApi.BASE_URL;
 
 import java.io.IOException;
 import org.springframework.web.service.annotation.DeleteExchange;
 import org.springframework.web.service.annotation.HttpExchange;
-import org.springframework.web.service.annotation.PostExchange;
 
 @HttpExchange(BASE_URL)
-public interface SharedAuditLogTestHelperApi {
+public interface AuditLogServiceTestHelperApi {
 
   String BASE_URL = "/test-helper";
 
   @DeleteExchange("audit-log-storage")
   void clearAuditLogStorageDirectory() throws IOException;
-
-  @PostExchange("archiving-job")
-  void runArchivingJob();
 }
diff --git a/backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogTestHelperApi.java b/backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogTestHelperApi.java
deleted file mode 100644
index 8db01d03fbd317dfa4bbe6fd9b198e2e3ac3aa62..0000000000000000000000000000000000000000
--- a/backend/auditlog-api/src/main/java/de/eshg/auditlog/AuditLogTestHelperApi.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package de.eshg.auditlog;
-
-import static de.eshg.auditlog.SharedAuditLogTestHelperApi.BASE_URL;
-
-import org.springframework.web.service.annotation.HttpExchange;
-
-@HttpExchange(BASE_URL)
-public interface AuditLogTestHelperApi extends SharedAuditLogTestHelperApi {
-
-  String BASE_URL = "/test-helper";
-}
diff --git a/backend/auditlog/build.gradle b/backend/auditlog/build.gradle
index fd79517ce6d940c4634da817e7dd0ebbea343992..200cc826434390969f4564dfb793ca49c17109f6 100644
--- a/backend/auditlog/build.gradle
+++ b/backend/auditlog/build.gradle
@@ -20,6 +20,7 @@ dependencies {
     testImplementation project(':test-commons')
     testImplementation testFixtures(project(':business-module-commons'))
     testImplementation testFixtures(project(':business-module-persistence-commons'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 
     testImplementation 'org.springdoc:springdoc-openapi-starter-common:latest.release'
 }
diff --git a/backend/auditlog/gradle.lockfile b/backend/auditlog/gradle.lockfile
index 5a0bee602df8a48bd2afd45f6117d37487c79c70..ae8bbefda1f6216f3dab17899d8d25323209df35 100644
--- a/backend/auditlog/gradle.lockfile
+++ b/backend/auditlog/gradle.lockfile
@@ -63,10 +63,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -89,7 +89,7 @@ org.antlr:antlr4-runtime:4.13.0=compileClasspath,productionRuntimeClasspath,runt
 org.apache.commons:commons-collections4:4.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.apache.commons:commons-compress:1.24.0=testCompileClasspath,testRuntimeClasspath
 org.apache.commons:commons-lang3:3.17.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.apache.commons:commons-text:1.12.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.apache.commons:commons-text:1.13.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.apache.httpcomponents.client5:httpclient5:5.4.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.apache.httpcomponents.core5:httpcore5-h2:5.3.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.apache.httpcomponents.core5:httpcore5:5.3.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -119,10 +119,10 @@ org.hibernate.common:hibernate-commons-annotations:7.0.3.Final=productionRuntime
 org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -141,16 +141,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/auditlog/openApi.json b/backend/auditlog/openApi.json
index 7f33ad0a4beb31d2f3fc0881c50ef5bbfa04ac31..32950d94a6295f81a07b8dfdd55dd0f930e0b0e0 100644
--- a/backend/auditlog/openApi.json
+++ b/backend/auditlog/openApi.json
@@ -302,7 +302,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
diff --git a/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogController.java b/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogController.java
index b51269e5ca383d3ffcae4b1f7cf2f0cdf0a11854..df2d3d57348898569f91e9fbae30782fcd146d3a 100644
--- a/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogController.java
+++ b/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogController.java
@@ -28,6 +28,7 @@ import de.eshg.base.user.api.GetUsersResponse;
 import de.eshg.base.user.api.UserDto;
 import de.eshg.base.user.api.UserFilterParameters;
 import de.eshg.lib.auditlog.AuditLogger;
+import de.eshg.rest.service.error.AlreadyExistsException;
 import de.eshg.rest.service.error.BadRequestException;
 import de.eshg.rest.service.error.ErrorCode;
 import de.eshg.rest.service.error.ErrorResponse;
@@ -146,6 +147,7 @@ public class AuditLogController implements AuditLogApi, AuditLogArchivingApi {
   }
 
   @Override
+  @Transactional
   public ResponseEntity<Resource> readAuditLogFile(
       String key, ReadAuditLogFileRequest readAuditLogFileRequest) {
     UserDto selfUser = userApi.getSelfUser();
@@ -784,7 +786,7 @@ public class AuditLogController implements AuditLogApi, AuditLogArchivingApi {
 
   private void throwBadRequestExceptionBecauseFileAlreadyExists(
       AddAuditLogFileRequest addAuditLogFileRequest) {
-    throw new BadRequestException(
+    throw new AlreadyExistsException(
         "Audit log for %s of %s already exists"
             .formatted(
                 addAuditLogFileRequest.date().format(DateTimeFormatter.ISO_LOCAL_DATE),
diff --git a/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogInternalSecurityConfiguration.java b/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogInternalSecurityConfiguration.java
index 62ec05c5e28c9d82a579e00eb72055ce461e744d..226af543d0ccba3a255564e8614d0e6680f87967 100644
--- a/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogInternalSecurityConfiguration.java
+++ b/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogInternalSecurityConfiguration.java
@@ -39,6 +39,7 @@ public class AuditLogInternalSecurityConfiguration {
   @ConditionalOnTestHelperEnabled
   public AuthorizationCustomizer testHelperAuthorizationCustomizer() {
     return auth ->
-        auth.requestMatchers(HttpMethod.DELETE, AuditLogTestHelperApi.BASE_URL + "/**").permitAll();
+        auth.requestMatchers(HttpMethod.DELETE, AuditLogServiceTestHelperApi.BASE_URL + "/**")
+            .permitAll();
   }
 }
diff --git a/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogTestHelperController.java b/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogServiceTestHelperController.java
similarity index 59%
rename from backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogTestHelperController.java
rename to backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogServiceTestHelperController.java
index b85d403eb561dd4666f886d99c148e3f59d73101..6d5646551d3834cce9f536a95561e6c1066ba764 100644
--- a/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogTestHelperController.java
+++ b/backend/auditlog/src/main/java/de/eshg/auditlog/AuditLogServiceTestHelperController.java
@@ -6,9 +6,10 @@
 package de.eshg.auditlog;
 
 import de.eshg.lib.auditlog.AuditLogArchiving;
-import de.eshg.lib.auditlog.AuditLogTestHelperService;
 import de.eshg.testhelper.ConditionalOnTestHelperEnabled;
-import io.swagger.v3.oas.annotations.tags.Tag;
+import de.eshg.testhelper.TestHelperController;
+import de.eshg.testhelper.TestHelperWithDatabaseService;
+import de.eshg.testhelper.environment.EnvironmentConfig;
 import java.io.IOException;
 import java.nio.file.Files;
 import org.apache.commons.io.FileUtils;
@@ -18,22 +19,23 @@ import org.springframework.web.bind.annotation.RestController;
 
 @RestController
 @ConditionalOnTestHelperEnabled
-@Tag(name = "TestHelper")
-public class AuditLogTestHelperController implements AuditLogTestHelperApi {
+public class AuditLogServiceTestHelperController extends TestHelperController
+    implements AuditLogServiceTestHelperApi, AuditLogClientTestHelperApi {
 
-  private static final Logger log = LoggerFactory.getLogger(AuditLogTestHelperController.class);
+  private static final Logger log =
+      LoggerFactory.getLogger(AuditLogServiceTestHelperController.class);
 
   private final AuditLogArchiving auditLogArchiving;
   private final AuditLogServiceConfig auditLogServiceConfig;
-  private final AuditLogTestHelperService auditLogTestHelperService;
 
-  public AuditLogTestHelperController(
+  public AuditLogServiceTestHelperController(
+      TestHelperWithDatabaseService testHelperWithDatabaseService,
+      EnvironmentConfig environmentConfig,
       AuditLogArchiving auditLogArchiving,
-      AuditLogServiceConfig auditLogServiceConfig,
-      AuditLogTestHelperService auditLogTestHelperService) {
+      AuditLogServiceConfig auditLogServiceConfig) {
+    super(testHelperWithDatabaseService, environmentConfig);
     this.auditLogArchiving = auditLogArchiving;
     this.auditLogServiceConfig = auditLogServiceConfig;
-    this.auditLogTestHelperService = auditLogTestHelperService;
   }
 
   @Override
@@ -42,11 +44,10 @@ public class AuditLogTestHelperController implements AuditLogTestHelperApi {
     if (Files.exists(auditLogServiceConfig.getLogStorageDir())) {
       FileUtils.cleanDirectory(auditLogServiceConfig.getLogStorageDir().toFile());
     }
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
   }
 
   @Override
-  public void runArchivingJob() {
+  public void runAuditLogArchivingJob() {
     auditLogArchiving.runArchivingJob();
   }
 }
diff --git a/backend/auditlog/src/main/resources/migrations/0008_add_auditlog_entry.xml b/backend/auditlog/src/main/resources/migrations/0008_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e739070adf17b73038c4a8057204230a0aa615e5
--- /dev/null
+++ b/backend/auditlog/src/main/resources/migrations/0008_add_auditlog_entry.xml
@@ -0,0 +1,54 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: Apache-2.0
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/auditlog/src/main/resources/migrations/changelog.xml b/backend/auditlog/src/main/resources/migrations/changelog.xml
index 2a4da4847c33634f678e0cc7ac5665eca5f92d2f..c1b070c84744a91c9ab5f984447582ec9f5764e5 100644
--- a/backend/auditlog/src/main/resources/migrations/changelog.xml
+++ b/backend/auditlog/src/main/resources/migrations/changelog.xml
@@ -15,5 +15,6 @@
   <include file="migrations/0005_drop_default_revision_entity_created_by_not_null_contraint.xml"/>
   <include file="migrations/0006_add_dental_as_audit_log_source.xml"/>
   <include file="migrations/0007_add_official_medical_service_audit_log_source.xml"/>
+  <include file="migrations/0008_add_auditlog_entry.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/auth/gradle.lockfile b/backend/auth/gradle.lockfile
index 6bb1340a10e0f846f6a36ffeec35aeaa1a5b1063..ab5aa92201dbd84104352c149f6503685a68aea1 100644
--- a/backend/auth/gradle.lockfile
+++ b/backend/auth/gradle.lockfile
@@ -57,10 +57,10 @@ io.netty:netty-resolver:4.1.116.Final=compileClasspath,productionRuntimeClasspat
 io.netty:netty-transport-native-unix-common:4.1.116.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.netty:netty-transport:4.1.116.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.projectreactor:reactor-core:3.7.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -96,10 +96,10 @@ org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.jsoup:jsoup:1.18.3=testCompileClasspath,testRuntimeClasspath
@@ -116,16 +116,17 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.4=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=compileClasspath,jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.reactivestreams:reactive-streams:1.0.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/auth/src/main/java/de/eshg/security/auth/AuthProperties.java b/backend/auth/src/main/java/de/eshg/security/auth/AuthProperties.java
index d4906afe8bbf120f9d6c6f5fda362c00805f539c..88b2ada4819588dd2ffbd7043c069221d97a7b19 100644
--- a/backend/auth/src/main/java/de/eshg/security/auth/AuthProperties.java
+++ b/backend/auth/src/main/java/de/eshg/security/auth/AuthProperties.java
@@ -5,12 +5,14 @@
 
 package de.eshg.security.auth;
 
+import de.eshg.security.auth.login.AccessCodeLoginType;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
 import java.net.URI;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.regex.Pattern;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -37,8 +39,8 @@ public record AuthProperties(
     }
   }
 
-  public List<String> getAccessCodeUrlPatterns() {
-    return auth().accessCodeUrlPatterns();
+  public Map<AccessCodeLoginType, List<String>> getAccessCodeLoginProperties() {
+    return Optional.ofNullable(auth().accessCodeUrlPatterns()).orElseGet(Map::of);
   }
 
   public List<String> getMukUrlPatterns() {
@@ -55,7 +57,7 @@ public record AuthProperties(
 
   record Auth(
       List<String> languagePathPrefixes,
-      List<String> accessCodeUrlPatterns,
+      Map<AccessCodeLoginType, @NotEmpty List<String>> accessCodeUrlPatterns,
       List<String> mukUrlPatterns,
       List<String> bundIdUrlPatterns,
       @Valid UserAgentFilter userAgentFilter) {}
diff --git a/backend/auth/src/main/java/de/eshg/security/auth/UserAgentFilter.java b/backend/auth/src/main/java/de/eshg/security/auth/UserAgentFilter.java
index 0d8ba26ba13d6245c1dae651fdc855f24c3fcb65..a5c1eb62e272e4d7b7514b8493a08cc23b444d5d 100644
--- a/backend/auth/src/main/java/de/eshg/security/auth/UserAgentFilter.java
+++ b/backend/auth/src/main/java/de/eshg/security/auth/UserAgentFilter.java
@@ -20,7 +20,6 @@ import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.web.DefaultRedirectStrategy;
 import org.springframework.security.web.RedirectStrategy;
-import org.springframework.util.AntPathMatcher;
 import org.springframework.util.Assert;
 import org.springframework.web.filter.OncePerRequestFilter;
 
@@ -30,7 +29,6 @@ public class UserAgentFilter extends OncePerRequestFilter {
 
   private final AuthProperties authProperties;
   private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
-  private final AntPathMatcher antPathMatcher = new AntPathMatcher();
 
   public UserAgentFilter(AuthProperties authProperties) {
     this.authProperties = authProperties;
diff --git a/backend/auth/src/main/java/de/eshg/security/auth/login/AccessCodeLoginMethod.java b/backend/auth/src/main/java/de/eshg/security/auth/login/AccessCodeLoginMethod.java
index 4ad9baa297304e05ae569e4a6d560bff4052ddc7..3b722f3b6833019584829e69122485ed11f8ada5 100644
--- a/backend/auth/src/main/java/de/eshg/security/auth/login/AccessCodeLoginMethod.java
+++ b/backend/auth/src/main/java/de/eshg/security/auth/login/AccessCodeLoginMethod.java
@@ -8,6 +8,7 @@ package de.eshg.security.auth.login;
 import com.google.common.annotations.VisibleForTesting;
 import de.cronn.commons.lang.StreamUtil;
 import de.eshg.security.auth.AuthProperties;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -18,7 +19,7 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.util.UriComponentsBuilder;
 
 @Component
-public final class AccessCodeLoginMethod extends LoginMethod {
+public class AccessCodeLoginMethod extends LoginMethod {
   private static final Logger log = LoggerFactory.getLogger(AccessCodeLoginMethod.class);
 
   public static final String ACCESS_CODE_QUERY_PARAMETER = "access_code";
@@ -29,13 +30,21 @@ public final class AccessCodeLoginMethod extends LoginMethod {
   }
 
   @Override
-  public List<String> getPathPatterns() {
-    return authProperties.getAccessCodeUrlPatterns();
+  protected List<String> getPathPatterns() {
+    return authProperties.getAccessCodeLoginProperties().values().stream()
+        .flatMap(Collection::stream)
+        .toList();
   }
 
   @Override
   protected void applyParameters(Map<String, Object> params, String redirectUrl) {
-    params.put("prompt", "access_code");
+    AccessCodeLoginType accessCodeLoginType = getAccessCodeLoginType(redirectUrl);
+    params.put("prompt", determineCredentialProviderId(accessCodeLoginType));
+
+    // See de.eshg.keycloak.authenticator.DateOfBirthAccessCodeForm
+    determineContextInfoKey(accessCodeLoginType)
+        .ifPresent(contextInfoKey -> params.put("context_info", contextInfoKey));
+
     getAndValidateAccessCode(redirectUrl)
         .ifPresent(
             validAccessCode -> {
@@ -44,6 +53,29 @@ public final class AccessCodeLoginMethod extends LoginMethod {
             });
   }
 
+  private AccessCodeLoginType getAccessCodeLoginType(String redirectUrl) {
+    return authProperties.getAccessCodeLoginProperties().entrySet().stream()
+        .filter(entry -> isApplicable(redirectUrl, entry.getValue()))
+        .map(Map.Entry::getKey)
+        .collect(StreamUtil.toSingleElement());
+  }
+
+  private static String determineCredentialProviderId(AccessCodeLoginType variant) {
+    return switch (variant) {
+      case SCHOOL_ENTRY, TRAVEL_MEDICINE -> "date-of-birth"; // DateOfBirthCredentialProvider
+      case STI_PROTECTION -> "pin"; // PinCredentialProvider
+    };
+  }
+
+  private static Optional<String> determineContextInfoKey(AccessCodeLoginType variant) {
+    return Optional.ofNullable(
+        switch (variant) {
+          case SCHOOL_ENTRY -> "esu";
+          case TRAVEL_MEDICINE -> "tm";
+          case STI_PROTECTION -> null;
+        });
+  }
+
   private static Optional<String> getAndValidateAccessCode(String url) {
     return UriComponentsBuilder.fromUriString(url)
         .build()
diff --git a/backend/auth/src/main/java/de/eshg/security/auth/login/AccessCodeLoginType.java b/backend/auth/src/main/java/de/eshg/security/auth/login/AccessCodeLoginType.java
new file mode 100644
index 0000000000000000000000000000000000000000..4241be594902aed8c11f80e2fa9f1bc3c6912de4
--- /dev/null
+++ b/backend/auth/src/main/java/de/eshg/security/auth/login/AccessCodeLoginType.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.security.auth.login;
+
+public enum AccessCodeLoginType {
+  SCHOOL_ENTRY,
+  TRAVEL_MEDICINE,
+  STI_PROTECTION
+}
diff --git a/backend/auth/src/main/java/de/eshg/security/auth/login/LoginMethod.java b/backend/auth/src/main/java/de/eshg/security/auth/login/LoginMethod.java
index be7dc0453c3dd31c6fc930a4a2e8ceac50b014fc..6b8e15239690171094f773ca902e492c679e8d98 100644
--- a/backend/auth/src/main/java/de/eshg/security/auth/login/LoginMethod.java
+++ b/backend/auth/src/main/java/de/eshg/security/auth/login/LoginMethod.java
@@ -42,7 +42,10 @@ public abstract class LoginMethod {
   }
 
   public final boolean isApplicable(String url) {
-    List<String> patterns = getPathPatterns();
+    return isApplicable(url, getPathPatterns());
+  }
+
+  protected final boolean isApplicable(String url, List<String> patterns) {
     if (patterns == null) {
       return false;
     }
diff --git a/backend/auth/src/main/resources/application-citizen-portal.properties b/backend/auth/src/main/resources/application-citizen-portal.properties
index 44fb9e53277f89e9e1a717fb5a713edb533c45fa..5616d82c7655e25e687f3eb14c4231da06678cc6 100644
--- a/backend/auth/src/main/resources/application-citizen-portal.properties
+++ b/backend/auth/src/main/resources/application-citizen-portal.properties
@@ -5,6 +5,10 @@ eshg.reverse-proxy.url=http://localhost:4001
 spring.security.oauth2.client.registration.keycloak.client-secret=tstj3RgLtqF4Kbh3hVNRRXTwxLkhmq
 
 eshg.auth.language-path-prefixes=/de, /en
-eshg.auth.access-code-url-patterns=/einschulungsuntersuchung/termin, /impfberatung/meine-termine
+
+eshg.auth.access-code-url-patterns[SCHOOL_ENTRY]=/einschulungsuntersuchung/termin
+eshg.auth.access-code-url-patterns[TRAVEL_MEDICINE]=/impfberatung/meine-termine
+eshg.auth.access-code-url-patterns[STI_PROTECTION]=/sexuellegesundheit/hiv-sti-beratung/termin
+
 eshg.auth.muk-url-patterns=/unternehmen/**
 eshg.auth.bund-id-url-patterns=/mein-bereich/**
diff --git a/backend/base-api/gradle.lockfile b/backend/base-api/gradle.lockfile
index 4c898172acea2745e4d04f2d429a1900ea7b5af9..481c9ef951daabfadc02f3d5f78095e70a1aecc1 100644
--- a/backend/base-api/gradle.lockfile
+++ b/backend/base-api/gradle.lockfile
@@ -14,10 +14,10 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -33,10 +33,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -49,13 +49,14 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/AddFacilityFileStateRequest.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/AddFacilityFileStateRequest.java
index 7de4e9992b90c784562a0d62a402509ac9e23dcf..9db3b3ea5ef0d22d9bc5a58d97081054dc405df7 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/AddFacilityFileStateRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/AddFacilityFileStateRequest.java
@@ -5,9 +5,9 @@
 
 package de.eshg.base.centralfile.api.facility;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.DataOriginDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/AddFacilityFileStateResponse.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/AddFacilityFileStateResponse.java
index 3a5b82ba1184f9fb3b40895fa11979b83042eaff..bd8602dc1fd9733f6feec7cb08f4c47056d51921 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/AddFacilityFileStateResponse.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/AddFacilityFileStateResponse.java
@@ -5,9 +5,9 @@
 
 package de.eshg.base.centralfile.api.facility;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.DataOriginDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/ExternalAddFacilityFileStateRequest.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/ExternalAddFacilityFileStateRequest.java
index 34f33c9f2c881a1c3e2946df4a92634ca50a20d2..3a17fa40938f189c04d6a4510f88cb467dbadf75 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/ExternalAddFacilityFileStateRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/ExternalAddFacilityFileStateRequest.java
@@ -5,8 +5,8 @@
 
 package de.eshg.base.centralfile.api.facility;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/FacilityDetailsDto.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/FacilityDetailsDto.java
index bce13382614e924879167cf200e4aa21e35c18c6..1fdf5e3e2252765c1ac98a37ae8bcd4f341f1356 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/FacilityDetailsDto.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/FacilityDetailsDto.java
@@ -5,8 +5,8 @@
 
 package de.eshg.base.centralfile.api.facility;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/GetFacilityFileStateResponse.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/GetFacilityFileStateResponse.java
index bbf6bb0a9a1d27470b4eb27b6b13969eb7e963fd..1be53b17f461fea6c14bd22fa1ca7044a193ef45 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/GetFacilityFileStateResponse.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/GetFacilityFileStateResponse.java
@@ -5,9 +5,9 @@
 
 package de.eshg.base.centralfile.api.facility;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.DataOriginDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/GetReferenceFacilityResponse.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/GetReferenceFacilityResponse.java
index 98e4e8a7bb5e090b9cf4000704167d6261c245ea..c5ae6727670634b88ef58a36b82f1d7941e379de 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/GetReferenceFacilityResponse.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/facility/GetReferenceFacilityResponse.java
@@ -5,9 +5,9 @@
 
 package de.eshg.base.centralfile.api.facility;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.DataOriginDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/AddPersonFileStateRequest.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/AddPersonFileStateRequest.java
index 47e312cca6b4224c8d80ea8ef41f4905f1fc9a66..c3a7d7af61fc20b0a2ae3df2d9768c21baf4afd4 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/AddPersonFileStateRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/AddPersonFileStateRequest.java
@@ -5,12 +5,13 @@
 
 package de.eshg.base.centralfile.api.person;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.DataOriginDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.DateOfBirth;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
@@ -31,7 +32,7 @@ public record AddPersonFileStateRequest(
     GenderDto gender,
     @NotNull @Size(min = 1, max = 80) String firstName,
     @NotNull @Size(min = 1, max = 120) String lastName,
-    @NotNull LocalDate dateOfBirth,
+    @NotNull @DateOfBirth LocalDate dateOfBirth,
     @Size(min = 1, max = 40) String nameAtBirth,
     @Size(min = 1, max = 50) String placeOfBirth,
     CountryCode countryOfBirth,
@@ -47,42 +48,42 @@ public record AddPersonFileStateRequest(
     this(new PersonDetailsDto(firstName, lastName, dateOfBirth), dataOrigin);
   }
 
-  public AddPersonFileStateRequest(PersonDetailsDto personDetailsDto, DataOriginDto dataOrigin) {
+  public AddPersonFileStateRequest(PersonDetails personDetails, DataOriginDto dataOrigin) {
     this(
         null,
-        personDetailsDto.title(),
-        personDetailsDto.salutation(),
-        personDetailsDto.gender(),
-        personDetailsDto.firstName(),
-        personDetailsDto.lastName(),
-        personDetailsDto.dateOfBirth(),
-        personDetailsDto.nameAtBirth(),
-        personDetailsDto.placeOfBirth(),
-        personDetailsDto.countryOfBirth(),
-        personDetailsDto.emailAddresses(),
-        personDetailsDto.phoneNumbers(),
-        personDetailsDto.contactAddress(),
-        personDetailsDto.differentBillingAddress(),
+        personDetails.title(),
+        personDetails.salutation(),
+        personDetails.gender(),
+        personDetails.firstName(),
+        personDetails.lastName(),
+        personDetails.dateOfBirth(),
+        personDetails.nameAtBirth(),
+        personDetails.placeOfBirth(),
+        personDetails.countryOfBirth(),
+        personDetails.emailAddresses(),
+        personDetails.phoneNumbers(),
+        personDetails.contactAddress(),
+        personDetails.differentBillingAddress(),
         dataOrigin);
   }
 
   public AddPersonFileStateRequest(
-      UUID referencePersonId, PersonDetailsDto personDetailsDto, DataOriginDto dataOrigin) {
+      UUID referencePersonId, PersonDetails personDetails, DataOriginDto dataOrigin) {
     this(
         referencePersonId,
-        personDetailsDto.title(),
-        personDetailsDto.salutation(),
-        personDetailsDto.gender(),
-        personDetailsDto.firstName(),
-        personDetailsDto.lastName(),
-        personDetailsDto.dateOfBirth(),
-        personDetailsDto.nameAtBirth(),
-        personDetailsDto.placeOfBirth(),
-        personDetailsDto.countryOfBirth(),
-        personDetailsDto.emailAddresses(),
-        personDetailsDto.phoneNumbers(),
-        personDetailsDto.contactAddress(),
-        personDetailsDto.differentBillingAddress(),
+        personDetails.title(),
+        personDetails.salutation(),
+        personDetails.gender(),
+        personDetails.firstName(),
+        personDetails.lastName(),
+        personDetails.dateOfBirth(),
+        personDetails.nameAtBirth(),
+        personDetails.placeOfBirth(),
+        personDetails.countryOfBirth(),
+        personDetails.emailAddresses(),
+        personDetails.phoneNumbers(),
+        personDetails.contactAddress(),
+        personDetails.differentBillingAddress(),
         dataOrigin);
   }
 }
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/AddPersonFileStateResponse.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/AddPersonFileStateResponse.java
index 582f68297ddcaba67091a4abb0fd7664cc204dd0..2cd8575c2f619f5bc21ad44ee5ed7c90e54a074e 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/AddPersonFileStateResponse.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/AddPersonFileStateResponse.java
@@ -5,12 +5,12 @@
 
 package de.eshg.base.centralfile.api.person;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.DataOriginDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/ExternalAddPersonFileStateRequest.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/ExternalAddPersonFileStateRequest.java
index e2c93e9c5d0dc0d13bb9b243df6d43f2050fbd92..ea3a31493602087ed789f3992a0306fcd20eeaf3 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/ExternalAddPersonFileStateRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/ExternalAddPersonFileStateRequest.java
@@ -5,11 +5,12 @@
 
 package de.eshg.base.centralfile.api.person;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.DateOfBirth;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
@@ -24,7 +25,7 @@ public record ExternalAddPersonFileStateRequest(
     GenderDto gender,
     @NotNull @Size(min = 1, max = 80) String firstName,
     @NotNull @Size(min = 1, max = 120) String lastName,
-    @NotNull LocalDate dateOfBirth,
+    @NotNull @DateOfBirth LocalDate dateOfBirth,
     @Size(min = 1, max = 40) String nameAtBirth,
     @Size(min = 1, max = 50) String placeOfBirth,
     CountryCode countryOfBirth,
@@ -34,20 +35,20 @@ public record ExternalAddPersonFileStateRequest(
     @Valid AddressDto differentBillingAddress)
     implements PersonDetails {
 
-  public ExternalAddPersonFileStateRequest(PersonDetailsDto personDetailsDto) {
+  public ExternalAddPersonFileStateRequest(PersonDetails personDetails) {
     this(
-        personDetailsDto.title(),
-        personDetailsDto.salutation(),
-        personDetailsDto.gender(),
-        personDetailsDto.firstName(),
-        personDetailsDto.lastName(),
-        personDetailsDto.dateOfBirth(),
-        personDetailsDto.nameAtBirth(),
-        personDetailsDto.placeOfBirth(),
-        personDetailsDto.countryOfBirth(),
-        personDetailsDto.emailAddresses(),
-        personDetailsDto.phoneNumbers(),
-        personDetailsDto.contactAddress(),
-        personDetailsDto.differentBillingAddress());
+        personDetails.title(),
+        personDetails.salutation(),
+        personDetails.gender(),
+        personDetails.firstName(),
+        personDetails.lastName(),
+        personDetails.dateOfBirth(),
+        personDetails.nameAtBirth(),
+        personDetails.placeOfBirth(),
+        personDetails.countryOfBirth(),
+        personDetails.emailAddresses(),
+        personDetails.phoneNumbers(),
+        personDetails.contactAddress(),
+        personDetails.differentBillingAddress());
   }
 }
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/GetPersonFileStateResponse.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/GetPersonFileStateResponse.java
index 26ce7cf59286c073fd53bd04a41648bbe46d0900..133a75c4e719389431831ce6ce04795d34a08406 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/GetPersonFileStateResponse.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/GetPersonFileStateResponse.java
@@ -5,12 +5,12 @@
 
 package de.eshg.base.centralfile.api.person;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.DataOriginDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/GetReferencePersonResponse.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/GetReferencePersonResponse.java
index 0957e9948947026283bdeeec02917b3fe6888ef0..9fa7bac70a5cd483b7a6ad744b34b867ee367ba8 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/GetReferencePersonResponse.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/GetReferencePersonResponse.java
@@ -5,12 +5,12 @@
 
 package de.eshg.base.centralfile.api.person;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.DataOriginDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/PersonDetailsDto.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/PersonDetailsDto.java
index 4bf62afd05f69c93e7c0dbf2b013d7bc899d36ac..1dea796b747d2b17ef77de803ed83c0b125cfd3e 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/PersonDetailsDto.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/PersonDetailsDto.java
@@ -5,11 +5,11 @@
 
 package de.eshg.base.centralfile.api.person;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdatePersonInBulkRequest.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdatePersonInBulkRequest.java
index 3fddd966e4e7211c72b8be1af98dfa0dd365ddc3..809cfbc003d19c8ce7f1198a973921b321113ade 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdatePersonInBulkRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdatePersonInBulkRequest.java
@@ -16,4 +16,8 @@ public record UpdatePersonInBulkRequest(
             example = "be9831d4-dc25-48d8-9bfe-4c0b54bfb2c1")
         @NotNull
         UUID fileStateId,
-    @NotNull @Valid PersonDetailsDto updatedPerson) {}
+    @NotNull @Valid UpdatePersonRequest updatedPerson) {
+  public UpdatePersonInBulkRequest(UUID fileStateId, PersonDetails personDetails) {
+    this(fileStateId, new UpdatePersonRequest(personDetails));
+  }
+}
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdatePersonRequest.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdatePersonRequest.java
index 767c13338985d06d3822f3c6a277a376d3597077..c5a3b965db878af1cc25e7abdf74cf0e51b52da7 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdatePersonRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdatePersonRequest.java
@@ -5,11 +5,52 @@
 
 package de.eshg.base.centralfile.api.person;
 
+import de.eshg.base.GenderDto;
+import de.eshg.base.SalutationDto;
+import de.eshg.base.address.AddressDto;
+import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.DateOfBirth;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.time.LocalDate;
+import java.util.List;
 
 @Schema(
     description =
         "Request used for performing a consistent update of a person file state and its associated reference person")
-public record UpdatePersonRequest(@NotNull @Valid PersonDetailsDto updatedPerson) {}
+public record UpdatePersonRequest(
+    @Size(min = 1, max = 119) String title,
+    SalutationDto salutation,
+    GenderDto gender,
+    @NotNull @Size(min = 1, max = 80) String firstName,
+    @NotNull @Size(min = 1, max = 120) String lastName,
+    @NotNull @DateOfBirth LocalDate dateOfBirth,
+    @Size(min = 1, max = 40) String nameAtBirth,
+    @Size(min = 1, max = 50) String placeOfBirth,
+    CountryCode countryOfBirth,
+    List<@MandatoryEmailAddressConstraint String> emailAddresses,
+    List<@NotNull @Size(min = 1, max = 23) String> phoneNumbers,
+    @Valid AddressDto contactAddress,
+    @Valid AddressDto differentBillingAddress)
+    implements PersonDetails {
+
+  public UpdatePersonRequest(PersonDetails personDetails) {
+    this(
+        personDetails.title(),
+        personDetails.salutation(),
+        personDetails.gender(),
+        personDetails.firstName(),
+        personDetails.lastName(),
+        personDetails.dateOfBirth(),
+        personDetails.nameAtBirth(),
+        personDetails.placeOfBirth(),
+        personDetails.countryOfBirth(),
+        personDetails.emailAddresses(),
+        personDetails.phoneNumbers(),
+        personDetails.contactAddress(),
+        personDetails.differentBillingAddress());
+  }
+}
diff --git a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdateReferencePersonRequest.java b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdateReferencePersonRequest.java
index 2f923937732f7fb2db4af53ae4595e6fb27217f0..8ebf3dec58b6158ccf2bec99d48b229e0c02dde6 100644
--- a/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdateReferencePersonRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/centralfile/api/person/UpdateReferencePersonRequest.java
@@ -16,4 +16,8 @@ import jakarta.validation.constraints.NotNull;
         and the expected current version number.
         """)
 public record UpdateReferencePersonRequest(
-    @NotNull @Valid PersonDetailsDto personDetails, @NotNull long version) {}
+    @NotNull @Valid UpdatePersonRequest personDetails, @NotNull long version) {
+  public UpdateReferencePersonRequest(PersonDetails personDetails, long version) {
+    this(new UpdatePersonRequest(personDetails), version);
+  }
+}
diff --git a/backend/base-api/src/main/java/de/eshg/base/contact/api/AddInstitutionContactRequest.java b/backend/base-api/src/main/java/de/eshg/base/contact/api/AddInstitutionContactRequest.java
index 2d6b7aed2dd2aa3ed0da1f3bd0d5414c579d011f..d83e1ee37021ede3d9c9cb4a59b511c1c3b57733 100644
--- a/backend/base-api/src/main/java/de/eshg/base/contact/api/AddInstitutionContactRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/contact/api/AddInstitutionContactRequest.java
@@ -5,8 +5,8 @@
 
 package de.eshg.base.contact.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/contact/api/AddPersonContactRequest.java b/backend/base-api/src/main/java/de/eshg/base/contact/api/AddPersonContactRequest.java
index d525035f7054b1e66a83ff53415d6c3d295b6dd9..130de3e51e9f89a83ca39c8b8b92fba6923bfdd8 100644
--- a/backend/base-api/src/main/java/de/eshg/base/contact/api/AddPersonContactRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/contact/api/AddPersonContactRequest.java
@@ -5,10 +5,10 @@
 
 package de.eshg.base.contact.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/contact/api/InstitutionContactDto.java b/backend/base-api/src/main/java/de/eshg/base/contact/api/InstitutionContactDto.java
index e767818284173e366bde9a81a6b4d8957e3b9dd9..a90523986abbb443e4883ccdb27d56e2c1651da5 100644
--- a/backend/base-api/src/main/java/de/eshg/base/contact/api/InstitutionContactDto.java
+++ b/backend/base-api/src/main/java/de/eshg/base/contact/api/InstitutionContactDto.java
@@ -5,8 +5,8 @@
 
 package de.eshg.base.contact.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
diff --git a/backend/base-api/src/main/java/de/eshg/base/contact/api/PersonContactDto.java b/backend/base-api/src/main/java/de/eshg/base/contact/api/PersonContactDto.java
index 93f1184319c4afead76eeae19dce4ac12864fd62..08d2ee8ff55c9a246e1fd62fe5fa88b4908e74dd 100644
--- a/backend/base-api/src/main/java/de/eshg/base/contact/api/PersonContactDto.java
+++ b/backend/base-api/src/main/java/de/eshg/base/contact/api/PersonContactDto.java
@@ -5,10 +5,10 @@
 
 package de.eshg.base.contact.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
diff --git a/backend/base-api/src/main/java/de/eshg/base/contact/api/UpdateInstitutionContactRequest.java b/backend/base-api/src/main/java/de/eshg/base/contact/api/UpdateInstitutionContactRequest.java
index 1734d091db04a8089c682954ea09bc47867de6a4..6c96d55340a07f07470955e80cc5d7b1e41448c9 100644
--- a/backend/base-api/src/main/java/de/eshg/base/contact/api/UpdateInstitutionContactRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/contact/api/UpdateInstitutionContactRequest.java
@@ -5,8 +5,8 @@
 
 package de.eshg.base.contact.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.ArraySchema;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
diff --git a/backend/base-api/src/main/java/de/eshg/base/contact/api/UpdatePersonContactRequest.java b/backend/base-api/src/main/java/de/eshg/base/contact/api/UpdatePersonContactRequest.java
index 079f5fc4cf6cab9771aa9d7f27ca38945bf8c719..8bf1d326b28aa4c13a6a8579d70788b1d3ec1c31 100644
--- a/backend/base-api/src/main/java/de/eshg/base/contact/api/UpdatePersonContactRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/contact/api/UpdatePersonContactRequest.java
@@ -5,10 +5,10 @@
 
 package de.eshg.base.contact.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.ArraySchema;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
diff --git a/backend/base-api/src/main/java/de/eshg/base/gdpr/GdprProcedureApi.java b/backend/base-api/src/main/java/de/eshg/base/gdpr/GdprProcedureApi.java
index 6eb9ef77a105b0f890170a031939e28510083720..3edf26f007b72a9fcbc052ca958cb32a024e2dec 100644
--- a/backend/base-api/src/main/java/de/eshg/base/gdpr/GdprProcedureApi.java
+++ b/backend/base-api/src/main/java/de/eshg/base/gdpr/GdprProcedureApi.java
@@ -11,6 +11,7 @@ import de.eshg.base.gdpr.api.AddGdprDownloadsRequest;
 import de.eshg.base.gdpr.api.AddGdprProcedureFromCitizenPortalRequest;
 import de.eshg.base.gdpr.api.AddGdprProcedureRequest;
 import de.eshg.base.gdpr.api.CancelGdprProcedureRequest;
+import de.eshg.base.gdpr.api.CitizenUsersGdprProcedureDto;
 import de.eshg.base.gdpr.api.CloseGdprProcedureRequest;
 import de.eshg.base.gdpr.api.DeleteGdprDownloadsRequest;
 import de.eshg.base.gdpr.api.GdprProcedureFilterParameters;
@@ -42,6 +43,7 @@ public interface GdprProcedureApi {
   String SELF_LINKED_GDPR_PROCEDURES = "/self/linked-gdpr-procedures";
   String CITIZEN_PORTAL_URL = Base.GDPR_PROCEDURE_CITIZEN_PORTAL_URL;
   String DOWNLOADS = Base.Gdpr.DOWNLOADS;
+  String DELETE_DOWNLOADS = Base.Gdpr.DELETE_DOWNLOADS;
   String FILE_STATE_IDS = Base.Gdpr.FILE_STATE_IDS;
   String BY_ID = Base.Gdpr.BY_ID;
   String DETAILS_PAGE = Base.Gdpr.DETAILS_PAGE;
@@ -64,10 +66,10 @@ public interface GdprProcedureApi {
       summary =
           """
   This endpoint allows authenticated MUK and BundID users to initiate a GDPR
-  procedure via the citizen portal initiate a GDPR procedure. A matter of
-  concern can be added to the request if desired.
+  procedure via the citizen portal. A matter of concern can be added to the
+  request if desired.
   """)
-  GetGdprProcedureResponse addGdprProcedureFromCitizenPortal(
+  CitizenUsersGdprProcedureDto addGdprProcedureFromCitizenPortal(
       @RequestBody @Valid AddGdprProcedureFromCitizenPortalRequest request);
 
   @GetExchange(CITIZEN_PORTAL_URL + SELF_LINKED_GDPR_PROCEDURES)
@@ -163,7 +165,7 @@ public interface GdprProcedureApi {
           "Get list of download ids of GDPR-related documents or data of this GDPR procedure.")
   GetGdprDownloadsResponse getDownloads(@PathVariable("id") UUID id);
 
-  @DeleteExchange(DOWNLOADS)
+  @PostExchange(DELETE_DOWNLOADS)
   @ApiResponse(responseCode = "200")
   @Operation(
       summary =
diff --git a/backend/base-api/src/main/java/de/eshg/base/gdpr/api/GdprProcedureStatusDto.java b/backend/base-api/src/main/java/de/eshg/base/gdpr/api/GdprProcedureStatusDto.java
index 0961e6db6e0ab747d49e8ba9e426072f324f7ff7..5a6d962a08734e4438bab305be226bcd05868d39 100644
--- a/backend/base-api/src/main/java/de/eshg/base/gdpr/api/GdprProcedureStatusDto.java
+++ b/backend/base-api/src/main/java/de/eshg/base/gdpr/api/GdprProcedureStatusDto.java
@@ -10,7 +10,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
 @Schema(name = "GdprProcedureStatus", description = "A list of statuses a GDPR procedure can have.")
 public enum GdprProcedureStatusDto {
   DRAFT,
-  OPEN,
   IN_PROGRESS,
   CLOSED,
   ABORTED;
diff --git a/backend/base-api/src/main/java/de/eshg/base/statistics/api/BaseAttribute.java b/backend/base-api/src/main/java/de/eshg/base/statistics/api/BaseAttribute.java
index e960e27a34b8e8e3a8229a0f776d2139eb8aaf7b..83d7462673104ea22b10f79979e28189e3df6ce7 100644
--- a/backend/base-api/src/main/java/de/eshg/base/statistics/api/BaseAttribute.java
+++ b/backend/base-api/src/main/java/de/eshg/base/statistics/api/BaseAttribute.java
@@ -5,6 +5,7 @@
 
 package de.eshg.base.statistics.api;
 
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import de.eshg.lib.statistics.api.ValueOptionInternal;
 import de.eshg.lib.statistics.api.ValueType;
 import jakarta.validation.Valid;
@@ -19,4 +20,5 @@ public record BaseAttribute(
     @NotNull ValueType valueType,
     String unit,
     @Size(min = 1) @Valid List<ValueOptionInternal> valueOptions,
-    @NotNull boolean mandatory) {}
+    @NotNull boolean mandatory,
+    @NotNull DataPrivacyCategory dataPrivacyCategory) {}
diff --git a/backend/base-api/src/main/java/de/eshg/base/testhelper/BaseTestHelperApi.java b/backend/base-api/src/main/java/de/eshg/base/testhelper/BaseTestHelperApi.java
index 8ed73105632a44dfac6d5eed4f55231dab89ba13..c35be37ff4ab3a3e800cc3b1a2b7a413d1cee650 100644
--- a/backend/base-api/src/main/java/de/eshg/base/testhelper/BaseTestHelperApi.java
+++ b/backend/base-api/src/main/java/de/eshg/base/testhelper/BaseTestHelperApi.java
@@ -83,6 +83,9 @@ public interface BaseTestHelperApi extends TestHelperApi, LoginProvider {
   void disableBusinessModule(
       @PathVariable("businessModuleToDisable") BusinessModule businessModuleToDisable);
 
+  @PostExchange("/business-modules/reset")
+  void resetActivatedBusinessModules();
+
   @PostExchange("/setup-admin")
   void createSetupAdmin(@Valid @RequestBody CreateSetupAdminRequest request);
 
@@ -92,6 +95,9 @@ public interface BaseTestHelperApi extends TestHelperApi, LoginProvider {
   @GetExchange("/idp-user/{nameId}")
   CitizenUserDto getIdpUser(@PathVariable("nameId") String nameId);
 
-  @PostExchange("auditlog-notification-job")
+  @PostExchange("/auditlog-notification-job")
   void runAuditlogNotificationJob();
+
+  @PostExchange("/gdpr-cleanup-job")
+  void runGdprCleanupJob();
 }
diff --git a/backend/base-api/src/main/java/de/eshg/base/user/api/AddUserRequest.java b/backend/base-api/src/main/java/de/eshg/base/user/api/AddUserRequest.java
index 7d3bd9a21221a24157942cba1a9088a7003a81b6..fb5fc7cee9338c4d64286784b8bb7a57b49fb397 100644
--- a/backend/base-api/src/main/java/de/eshg/base/user/api/AddUserRequest.java
+++ b/backend/base-api/src/main/java/de/eshg/base/user/api/AddUserRequest.java
@@ -5,8 +5,8 @@
 
 package de.eshg.base.user.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.SalutationDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base-api/src/main/java/de/eshg/base/user/api/UserDto.java b/backend/base-api/src/main/java/de/eshg/base/user/api/UserDto.java
index db63a97fc0f922e164b04e5d588339c96a59fd28..0947d8ed60527b4e4d5771da2256ad40e4f97a9a 100644
--- a/backend/base-api/src/main/java/de/eshg/base/user/api/UserDto.java
+++ b/backend/base-api/src/main/java/de/eshg/base/user/api/UserDto.java
@@ -5,7 +5,7 @@
 
 package de.eshg.base.user.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/base/build.gradle b/backend/base/build.gradle
index a41040d8793263838a0038e75828234a62e0dd55..96fb03446cdee2e3c28cccb45620d7df1ba8f950 100644
--- a/backend/base/build.gradle
+++ b/backend/base/build.gradle
@@ -48,6 +48,7 @@ dependencies {
     testImplementation testFixtures(project(':lib-service-directory-admin-api'))
     testImplementation testFixtures(project(":base-api"))
     testImplementation testFixtures(project(':lib-document-generator'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 
     testImplementation 'org.apache.commons:commons-csv:latest.release'
     testImplementation 'com.tngtech.archunit:archunit-junit5:latest.release'
diff --git a/backend/base/gradle.lockfile b/backend/base/gradle.lockfile
index d55933112e901db5cf001f6426e556037549ba94..c6b27207d069781b65dcb633557e212e563e2734 100644
--- a/backend/base/gradle.lockfile
+++ b/backend/base/gradle.lockfile
@@ -88,12 +88,12 @@ io.prometheus:prometheus-metrics-exposition-formats:1.3.5=productionRuntimeClass
 io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.quarkus:quarkus-junit4-mock:3.17.7=testCompileClasspath,testRuntimeClasspath
+io.quarkus:quarkus-junit4-mock:3.18.0=testCompileClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.swagger:swagger-annotations:1.6.15=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -198,10 +198,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:commons-logging-jboss-logging:1.0.0.Final=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jboss.resteasy:resteasy-client-api:6.2.9.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -230,24 +230,25 @@ org.keycloak:keycloak-admin-client:26.0.3=compileClasspath,productionRuntimeClas
 org.keycloak:keycloak-client-common-synced:26.0.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.latencyutils:LatencyUtils:2.0.3=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.liquibase:liquibase-core:4.29.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.mnode.ical4j:ical4j:4.0.8=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.mnode.ical4j:ical4j:4.1.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.reactivestreams:reactive-streams:1.0.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/base/openApi.json b/backend/base/openApi.json
index ebcab2c9593cdad603b91082dc6b37ae3b53dce1..af097e1032c90b4e9f0945e55be943655ceb7e29 100644
--- a/backend/base/openApi.json
+++ b/backend/base/openApi.json
@@ -1893,14 +1893,14 @@
             "content" : {
               "*/*" : {
                 "schema" : {
-                  "$ref" : "#/components/schemas/GetGdprProcedureResponse"
+                  "$ref" : "#/components/schemas/CitizenUsersGdprProcedure"
                 }
               }
             },
             "description" : "OK"
           }
         },
-        "summary" : "This endpoint allows authenticated MUK and BundID users to initiate a GDPR\nprocedure via the citizen portal initiate a GDPR procedure. A matter of\nconcern can be added to the request if desired.\n",
+        "summary" : "This endpoint allows authenticated MUK and BundID users to initiate a GDPR\nprocedure via the citizen portal. A matter of concern can be added to the\nrequest if desired.\n",
         "tags" : [ "GdprProcedure" ]
       }
     },
@@ -2080,11 +2080,10 @@
         "tags" : [ "GdprProcedure" ]
       }
     },
-    "/gdpr-procedures/{id}/details-page" : {
-      "get" : {
-        "operationId" : "getGdprProcedureDetailsPage",
+    "/gdpr-procedures/{id}/delete-downloads" : {
+      "post" : {
+        "operationId" : "deleteDownloads",
         "parameters" : [ {
-          "description" : "The Id of the GDPR procedure.",
           "in" : "path",
           "name" : "id",
           "required" : true,
@@ -2093,26 +2092,30 @@
             "format" : "uuid"
           }
         } ],
+        "requestBody" : {
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/DeleteGdprDownloadsRequest"
+              }
+            }
+          },
+          "required" : true
+        },
         "responses" : {
           "200" : {
-            "content" : {
-              "*/*" : {
-                "schema" : {
-                  "$ref" : "#/components/schemas/GetGdprProcedureDetailsPageResponse"
-                }
-              }
-            },
             "description" : "OK"
           }
         },
-        "summary" : "Get GDPR procedure details page information. Used exclusively by the frontend to display the GDPR Procedure.",
+        "summary" : "Delete one or multiple downloads of GDPR-related document or data of this GDPR procedure.",
         "tags" : [ "GdprProcedure" ]
       }
     },
-    "/gdpr-procedures/{id}/downloads" : {
-      "delete" : {
-        "operationId" : "deleteDownloads",
+    "/gdpr-procedures/{id}/details-page" : {
+      "get" : {
+        "operationId" : "getGdprProcedureDetailsPage",
         "parameters" : [ {
+          "description" : "The Id of the GDPR procedure.",
           "in" : "path",
           "name" : "id",
           "required" : true,
@@ -2121,24 +2124,23 @@
             "format" : "uuid"
           }
         } ],
-        "requestBody" : {
-          "content" : {
-            "application/json" : {
-              "schema" : {
-                "$ref" : "#/components/schemas/DeleteGdprDownloadsRequest"
-              }
-            }
-          },
-          "required" : true
-        },
         "responses" : {
           "200" : {
+            "content" : {
+              "*/*" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/GetGdprProcedureDetailsPageResponse"
+                }
+              }
+            },
             "description" : "OK"
           }
         },
-        "summary" : "Delete one or multiple downloads of GDPR-related document or data of this GDPR procedure.",
+        "summary" : "Get GDPR procedure details page information. Used exclusively by the frontend to display the GDPR Procedure.",
         "tags" : [ "GdprProcedure" ]
-      },
+      }
+    },
+    "/gdpr-procedures/{id}/downloads" : {
       "get" : {
         "operationId" : "getDownloads",
         "parameters" : [ {
@@ -4277,7 +4279,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -4286,9 +4288,9 @@
         "tags" : [ "TestHelper" ]
       }
     },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+    "/test-helper/auditlog-notification-job" : {
+      "post" : {
+        "operationId" : "runAuditlogNotificationJob",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -4297,9 +4299,9 @@
         "tags" : [ "TestHelper" ]
       }
     },
-    "/test-helper/auditlog-notification-job" : {
+    "/test-helper/business-modules/reset" : {
       "post" : {
-        "operationId" : "runAuditlogNotificationJob",
+        "operationId" : "resetActivatedBusinessModules",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -4393,6 +4395,17 @@
         "tags" : [ "TestHelper" ]
       }
     },
+    "/test-helper/gdpr-cleanup-job" : {
+      "post" : {
+        "operationId" : "runGdprCleanupJob",
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "tags" : [ "TestHelper" ]
+      }
+    },
     "/test-helper/idp-user/{nameId}" : {
       "get" : {
         "operationId" : "getIdpUser",
@@ -7520,7 +7533,7 @@
       "GdprProcedureStatus" : {
         "type" : "string",
         "description" : "A list of statuses a GDPR procedure can have.",
-        "enum" : [ "DRAFT", "OPEN", "IN_PROGRESS", "CLOSED", "ABORTED" ]
+        "enum" : [ "DRAFT", "IN_PROGRESS", "CLOSED", "ABORTED" ]
       },
       "GdprProcedureType" : {
         "type" : "string",
@@ -11023,7 +11036,7 @@
             "example" : "UUID_2"
           },
           "updatedPerson" : {
-            "$ref" : "#/components/schemas/PersonDetails"
+            "$ref" : "#/components/schemas/UpdatePersonRequest"
           }
         }
       },
@@ -11046,11 +11059,90 @@
         }
       },
       "UpdatePersonRequest" : {
-        "required" : [ "updatedPerson" ],
+        "required" : [ "dateOfBirth", "firstName", "lastName" ],
         "type" : "object",
         "properties" : {
-          "updatedPerson" : {
-            "$ref" : "#/components/schemas/PersonDetails"
+          "contactAddress" : {
+            "oneOf" : [ {
+              "$ref" : "#/components/schemas/DomesticAddress"
+            }, {
+              "$ref" : "#/components/schemas/PostboxAddress"
+            } ]
+          },
+          "countryOfBirth" : {
+            "$ref" : "#/components/schemas/CountryCode"
+          },
+          "dateOfBirth" : {
+            "type" : "string",
+            "description" : "The date of birth of the Person.",
+            "format" : "date",
+            "example" : "2000-01-01"
+          },
+          "differentBillingAddress" : {
+            "oneOf" : [ {
+              "$ref" : "#/components/schemas/DomesticAddress"
+            }, {
+              "$ref" : "#/components/schemas/PostboxAddress"
+            } ]
+          },
+          "emailAddresses" : {
+            "type" : "array",
+            "description" : "A list of email addresses of the Person.",
+            "example" : "['mail1@address.de','mail2@address.de','mail3@address.de']",
+            "items" : {
+              "type" : "string"
+            }
+          },
+          "firstName" : {
+            "maxLength" : 80,
+            "minLength" : 1,
+            "type" : "string",
+            "description" : "The given name(s) of the Person.",
+            "example" : "John"
+          },
+          "gender" : {
+            "$ref" : "#/components/schemas/Gender"
+          },
+          "lastName" : {
+            "maxLength" : 120,
+            "minLength" : 1,
+            "type" : "string",
+            "description" : "The last name of the Person.",
+            "example" : "Doe"
+          },
+          "nameAtBirth" : {
+            "maxLength" : 40,
+            "minLength" : 1,
+            "type" : "string",
+            "description" : "The last name at birth of the Person.",
+            "example" : "Smith"
+          },
+          "phoneNumbers" : {
+            "type" : "array",
+            "description" : "A list of telephone numbers of the Person.",
+            "example" : "['+4912345678901','+4912345678902','+4912345678903']",
+            "items" : {
+              "maxLength" : 23,
+              "minLength" : 1,
+              "type" : "string"
+            }
+          },
+          "placeOfBirth" : {
+            "maxLength" : 50,
+            "minLength" : 1,
+            "type" : "string",
+            "description" : "The place of birth (without country) of the Person.",
+            "example" : "Berlin"
+          },
+          "salutation" : {
+            "$ref" : "#/components/schemas/Salutation"
+          },
+          "title" : {
+            "maxLength" : 119,
+            "minLength" : 1,
+            "type" : "string",
+            "description" : "The academic title of a Person.",
+            "example" : "Prof. Dr."
           }
         },
         "description" : "Request used for performing a consistent update of a person file state and its associated reference person"
@@ -11110,7 +11202,7 @@
         "type" : "object",
         "properties" : {
           "personDetails" : {
-            "$ref" : "#/components/schemas/PersonDetails"
+            "$ref" : "#/components/schemas/UpdatePersonRequest"
           },
           "version" : {
             "type" : "integer",
diff --git a/backend/base/src/main/java/de/eshg/base/centralfile/mapper/PersonMapper.java b/backend/base/src/main/java/de/eshg/base/centralfile/mapper/PersonMapper.java
index cb6b604e58a2fe9f8cde8bd890d53edcad04122c..b24c8c9a3c3f97d790c7ba0baf628afafe7eb109 100644
--- a/backend/base/src/main/java/de/eshg/base/centralfile/mapper/PersonMapper.java
+++ b/backend/base/src/main/java/de/eshg/base/centralfile/mapper/PersonMapper.java
@@ -190,7 +190,7 @@ public class PersonMapper {
   }
 
   public static Person mapPersonToDm(UpdatePersonRequest request) {
-    return mapPersonDetailsToDm(request.updatedPerson());
+    return mapPersonDetailsToDm(request);
   }
 
   public static Person mapPersonToDm(UpdatePersonInBulkRequest request) {
diff --git a/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureController.java b/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureController.java
index 8bf5f1cf9f65eb0074eb1a78e8467992c33508ff..2f04fb169ef9c023acdc1e9df15f40a1ac17e4c3 100644
--- a/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureController.java
+++ b/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureController.java
@@ -95,7 +95,7 @@ public class GdprProcedureController implements GdprProcedureApi {
 
   @Override
   @Transactional
-  public GetGdprProcedureResponse addGdprProcedureFromCitizenPortal(
+  public CitizenUsersGdprProcedureDto addGdprProcedureFromCitizenPortal(
       AddGdprProcedureFromCitizenPortalRequest request) {
     baseFeatureToggle.assertNewFeatureIsEnabled(BaseFeature.GDPR_ONLINE_PORTAL);
 
@@ -105,7 +105,7 @@ public class GdprProcedureController implements GdprProcedureApi {
     procedure.setIdentificationData(identificationData);
 
     GdprProcedure saved = service.addFromCitizenPortal(procedure);
-    return mapGdprProcedureToApi(saved);
+    return GdprProcedureMapper.mapProcedureToCitizenApi(saved);
   }
 
   @Override
@@ -216,6 +216,7 @@ public class GdprProcedureController implements GdprProcedureApi {
   public GetGdprProcedureResponse addCentralFileIdToGdprProcedure(
       UUID id, AddCentralFileIdToGdprProcedureRequest request) {
     baseFeatureToggle.assertNewFeatureIsEnabled(BaseFeature.GDPR);
+
     List<CentralFileIdWrapper> centralFileIds =
         mapToDm(request.centralFileIds().stream().distinct().toList());
     return mapGdprProcedureToApi(
diff --git a/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureMapper.java b/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureMapper.java
index d263c95b469f7df9da125aa3e6b441626defa2be..d9c00252e42fdb051b36f23656cf79f958ca89e2 100644
--- a/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureMapper.java
+++ b/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureMapper.java
@@ -144,7 +144,6 @@ public class GdprProcedureMapper {
   public static GdprProcedureStatusDto mapToApi(GdprProcedureStatus status) {
     return switch (status) {
       case DRAFT -> GdprProcedureStatusDto.DRAFT;
-      case OPEN -> GdprProcedureStatusDto.OPEN;
       case CLOSED -> GdprProcedureStatusDto.CLOSED;
       case ABORTED -> GdprProcedureStatusDto.ABORTED;
       case IN_PROGRESS -> GdprProcedureStatusDto.IN_PROGRESS;
@@ -260,7 +259,7 @@ public class GdprProcedureMapper {
     return new GetCitizenSelfUsersGdprProceduresResponse(responses);
   }
 
-  private static CitizenUsersGdprProcedureDto mapProcedureToCitizenApi(GdprProcedure procedure) {
+  static CitizenUsersGdprProcedureDto mapProcedureToCitizenApi(GdprProcedure procedure) {
     return new CitizenUsersGdprProcedureDto(
         procedure.getExternalId(),
         GdprProcedureMapper.mapToApi(procedure.getType()),
diff --git a/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureService.java b/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureService.java
index 0826b792b57ddeefd59e82b013850722f74dcf8b..d9bc9c190e40d21c12d6e75f69c27bb0c71f5932 100644
--- a/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureService.java
+++ b/backend/base/src/main/java/de/eshg/base/gdpr/GdprProcedureService.java
@@ -278,8 +278,9 @@ public class GdprProcedureService {
   public GdprProcedure addCentralFileIdsToGdprProcedure(
       List<CentralFileIdWrapper> centralFileIds, UUID gdprProcedureId, long version) {
     GdprProcedure procedure = getGdprProcedureForUpdate(gdprProcedureId);
-    ValidationUtil.validateVersion(version, procedure);
 
+    ValidationUtil.validateVersion(version, procedure);
+    throwIfProcedureIsNoDraft(procedure);
     throwIfCentralFileIdAlreadyExists(centralFileIds, procedure);
 
     entityManager.lock(procedure, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
@@ -317,6 +318,13 @@ public class GdprProcedureService {
     return procedure;
   }
 
+  private static void throwIfProcedureIsNoDraft(GdprProcedure procedure) {
+    if (procedure.getStatus() != GdprProcedureStatus.DRAFT) {
+      throw new BadRequestException(
+          "Cannot add centralFileIds: Gdpr Procedure is not in Draft Status");
+    }
+  }
+
   private static void throwIfCentralFileIdAlreadyExists(
       List<CentralFileIdWrapper> centralFileIds, GdprProcedure procedure) {
     List<UUID> existingIds =
diff --git a/backend/base/src/main/java/de/eshg/base/gdpr/persistence/GdprProcedureStatus.java b/backend/base/src/main/java/de/eshg/base/gdpr/persistence/GdprProcedureStatus.java
index d55c45294ee774f17476aceb76266f6ca07eb756..d15d2cea412b16c841ca7eacb460a8549dba1e98 100644
--- a/backend/base/src/main/java/de/eshg/base/gdpr/persistence/GdprProcedureStatus.java
+++ b/backend/base/src/main/java/de/eshg/base/gdpr/persistence/GdprProcedureStatus.java
@@ -7,7 +7,6 @@ package de.eshg.base.gdpr.persistence;
 
 public enum GdprProcedureStatus {
   DRAFT,
-  OPEN,
   IN_PROGRESS,
   CLOSED,
   ABORTED;
diff --git a/backend/base/src/main/java/de/eshg/base/keycloak/CitizenKeycloakProvisioning.java b/backend/base/src/main/java/de/eshg/base/keycloak/CitizenKeycloakProvisioning.java
index aab71f23001b2cf5c08929917413b36faac2420e..fb04056d5ddea2bd5fa0e6d5f4834087f17ec1a6 100644
--- a/backend/base/src/main/java/de/eshg/base/keycloak/CitizenKeycloakProvisioning.java
+++ b/backend/base/src/main/java/de/eshg/base/keycloak/CitizenKeycloakProvisioning.java
@@ -130,7 +130,8 @@ public class CitizenKeycloakProvisioning extends KeycloakProvisioning<CitizenKey
     builder.setDescription("Citizen Portal Browser Flow");
     builder.addAlternativeStep("auth-cookie");
     builder.addAlternativeStep("identity-provider-redirector");
-    builder.addAlternativeStep("access-code");
+    builder.addAlternativeStep("date-of-birth-access-code");
+    builder.addAlternativeStep("pin-access-code");
     builder.build(keycloakClient);
 
     keycloakClient.bindBrowserFlow(PORTAL_BROWSER_FLOW_ALIAS);
diff --git a/backend/base/src/main/java/de/eshg/base/keycloak/ModuleClient.java b/backend/base/src/main/java/de/eshg/base/keycloak/ModuleClient.java
index 706ea02c1a8982db47bd5f6d15becab56a2ec33a..a87d01ad4ae1f76dd90fb8b853a4905f31aead37 100644
--- a/backend/base/src/main/java/de/eshg/base/keycloak/ModuleClient.java
+++ b/backend/base/src/main/java/de/eshg/base/keycloak/ModuleClient.java
@@ -44,7 +44,8 @@ public enum ModuleClient {
   MEDICAL_REGISTRY(
       "medical-registry", List.of(BASE_MAIL_SEND, BASE_PERSONS_DELETE, BASE_FACILITIES_DELETE)),
   DENTAL("dental", List.of(BASE_MAIL_SEND, BASE_PERSONS_DELETE, BASE_FACILITIES_DELETE)),
-  OFFICIAL_MEDICAL_SERVICE("official-medical-service", List.of(BASE_MAIL_SEND));
+  OFFICIAL_MEDICAL_SERVICE(
+      "official-medical-service", List.of(BASE_MAIL_SEND, BASE_ACCESS_CODE_USER_ADMIN));
 
   private final String clientIdWithoutPrefix;
   private final List<EmployeePermissionRole> roles;
diff --git a/backend/base/src/main/java/de/eshg/base/spring/config/BaseInternalSecurityConfig.java b/backend/base/src/main/java/de/eshg/base/spring/config/BaseInternalSecurityConfig.java
index 14ce214258755079c58ac5e62e47d465454d7b2f..a3dfd6cc2cc4a942e0032834dcc27a7c456ebe4a 100644
--- a/backend/base/src/main/java/de/eshg/base/spring/config/BaseInternalSecurityConfig.java
+++ b/backend/base/src/main/java/de/eshg/base/spring/config/BaseInternalSecurityConfig.java
@@ -6,6 +6,7 @@
 package de.eshg.base.spring.config;
 
 import static de.eshg.base.gdpr.GdprProcedureApi.BY_ID;
+import static de.eshg.base.gdpr.GdprProcedureApi.DELETE_DOWNLOADS;
 import static de.eshg.base.gdpr.GdprProcedureApi.DOWNLOADS;
 import static de.eshg.base.gdpr.GdprProcedureApi.FILE_STATE_IDS;
 import static org.springframework.http.HttpMethod.DELETE;
@@ -87,7 +88,7 @@ public class BaseInternalSecurityConfig {
     auth.requestMatchers(POST, GdprProcedureApi.BASE_URL + DOWNLOADS)
         .hasRole(EmployeePermissionRole.BASE_GDPR_PROCEDURE_REVIEW.name());
 
-    auth.requestMatchers(DELETE, GdprProcedureApi.BASE_URL + DOWNLOADS)
+    auth.requestMatchers(POST, GdprProcedureApi.BASE_URL + DELETE_DOWNLOADS)
         .hasRole(EmployeePermissionRole.BASE_GDPR_PROCEDURE_REVIEW.name());
   }
 
diff --git a/backend/base/src/main/java/de/eshg/base/statistics/StatisticsController.java b/backend/base/src/main/java/de/eshg/base/statistics/StatisticsController.java
index c6b3682df7698174e766e2024a3ecc1e7efd107f..88ed25ffaa1e6b9f976c7a9553333461be888415 100644
--- a/backend/base/src/main/java/de/eshg/base/statistics/StatisticsController.java
+++ b/backend/base/src/main/java/de/eshg/base/statistics/StatisticsController.java
@@ -26,6 +26,7 @@ import de.eshg.base.street.SearchStreetResponse;
 import de.eshg.base.street.StreetController;
 import de.eshg.base.util.Gender;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import de.eshg.lib.statistics.api.DataRow;
 import de.eshg.lib.statistics.api.ValueType;
 import de.eshg.rest.service.error.BadRequestException;
@@ -86,7 +87,8 @@ public class StatisticsController implements BaseStatisticsApi {
         commonAttribute.getType(),
         null,
         commonAttribute.getValueOptions(),
-        commonAttribute.isMandatory());
+        commonAttribute.isMandatory(),
+        DataPrivacyCategory.QUASI_IDENTIFYING);
   }
 
   @Override
@@ -158,7 +160,14 @@ public class StatisticsController implements BaseStatisticsApi {
     ValueType valueType = mapToValueType(subjectType);
     List<BaseAttribute> attributes = new ArrayList<>();
     attributes.add(
-        new BaseAttribute(valueType.name(), valueType.name(), valueType, null, null, true));
+        new BaseAttribute(
+            valueType.name(),
+            valueType.name(),
+            valueType,
+            null,
+            null,
+            true,
+            DataPrivacyCategory.QUASI_IDENTIFYING));
     baseAttributes.forEach(baseAttribute -> attributes.add(mapToAttribute(baseAttribute)));
     return attributes;
   }
diff --git a/backend/base/src/main/java/de/eshg/base/testhelper/BaseTestHelperController.java b/backend/base/src/main/java/de/eshg/base/testhelper/BaseTestHelperController.java
index 835b4cb27875b8628dbb6f9af38351f4fde7e9fe..a3c3a579c5ba9350157dc9760f3d89e51c58b7b7 100644
--- a/backend/base/src/main/java/de/eshg/base/testhelper/BaseTestHelperController.java
+++ b/backend/base/src/main/java/de/eshg/base/testhelper/BaseTestHelperController.java
@@ -6,10 +6,11 @@
 package de.eshg.base.testhelper;
 
 import de.cronn.commons.lang.StreamUtil;
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.base.contact.api.SearchContactsResponse;
 import de.eshg.base.feature.BaseFeature;
 import de.eshg.base.feature.BaseFeatureToggle;
+import de.eshg.base.gdpr.GdprCleanupJob;
 import de.eshg.base.inventory.api.GetInventoryItemsResponse;
 import de.eshg.base.keycloak.CitizenKeycloakClient;
 import de.eshg.base.keycloak.MasterKeycloakProvisioning;
@@ -35,7 +36,6 @@ import de.eshg.testhelper.api.RealmDto;
 import de.eshg.testhelper.api.TestHelperLoginAsCitizenAccessCodeUserRequest;
 import de.eshg.testhelper.api.TestHelperLoginRequest;
 import de.eshg.testhelper.environment.EnvironmentConfig;
-import java.io.IOException;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -48,7 +48,7 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class BaseTestHelperController extends TestHelperController
-    implements BaseTestHelperApi, SharedAuditLogTestHelperApi {
+    implements BaseTestHelperApi, AuditLogClientTestHelperApi {
 
   private final BaseTestHelperService baseTestHelperService;
   private final BaseFeatureToggle baseFeatureToggle;
@@ -57,6 +57,7 @@ public class BaseTestHelperController extends TestHelperController
   private final BusinessModulesConfigurationProperties businessModulesConfigurationProperties;
   private final CitizenKeycloakClient citizenKeycloakClient;
   private final AuditLogNotificationJob auditLogNotificationJob;
+  private final GdprCleanupJob gdprCleanupJob;
 
   public BaseTestHelperController(
       BaseTestHelperService baseTestHelperService,
@@ -66,7 +67,8 @@ public class BaseTestHelperController extends TestHelperController
       EnvironmentConfig environmentConfig,
       BusinessModulesConfigurationProperties businessModulesConfigurationProperties,
       CitizenKeycloakClient citizenKeycloakClient,
-      AuditLogNotificationJob auditLogNotificationJob) {
+      AuditLogNotificationJob auditLogNotificationJob,
+      GdprCleanupJob gdprCleanupJob) {
     super(baseTestHelperService, environmentConfig);
     this.baseTestHelperService = baseTestHelperService;
     this.baseFeatureToggle = baseFeatureToggle;
@@ -75,6 +77,7 @@ public class BaseTestHelperController extends TestHelperController
     this.businessModulesConfigurationProperties = businessModulesConfigurationProperties;
     this.citizenKeycloakClient = citizenKeycloakClient;
     this.auditLogNotificationJob = auditLogNotificationJob;
+    this.gdprCleanupJob = gdprCleanupJob;
   }
 
   @Override
@@ -167,6 +170,11 @@ public class BaseTestHelperController extends TestHelperController
     }
   }
 
+  @Override
+  public void resetActivatedBusinessModules() {
+    baseTestHelperService.resetProperties(businessModulesConfigurationProperties);
+  }
+
   @Override
   public void createSetupAdmin(CreateSetupAdminRequest request) {
     masterKeycloakProvisioning.initializeSetupAdmin(request.username(), request.emailAddress());
@@ -219,17 +227,17 @@ public class BaseTestHelperController extends TestHelperController
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 
   @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditlogNotificationJob() {
+    auditLogNotificationJob.run();
   }
 
   @Override
-  public void runAuditlogNotificationJob() {
-    auditLogNotificationJob.run();
+  public void runGdprCleanupJob() {
+    gdprCleanupJob.performGdprCleanup();
   }
 }
diff --git a/backend/base/src/main/resources/migrations/0040_add_auditlog_entry.xml b/backend/base/src/main/resources/migrations/0040_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ebb946b32565da731dd06d7f947f2ed09deef45b
--- /dev/null
+++ b/backend/base/src/main/resources/migrations/0040_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: Apache-2.0
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/base/src/main/resources/migrations/0041_remove_gdpr_status_open.xml b/backend/base/src/main/resources/migrations/0041_remove_gdpr_status_open.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f27aec59120842dffe0eff214b27681b7d2cb784
--- /dev/null
+++ b/backend/base/src/main/resources/migrations/0041_remove_gdpr_status_open.xml
@@ -0,0 +1,11 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: Apache-2.0
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1738097216405-1">
+    <ext:modifyPostgresEnumType name="gdprprocedurestatus" newValues="ABORTED, CLOSED, DRAFT, IN_PROGRESS"/>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/base/src/main/resources/migrations/changelog.xml b/backend/base/src/main/resources/migrations/changelog.xml
index a617fb2ae3aec8fb4f2c7733737f07ff8b4734d7..7a468ec09feefff1c3be36ee6a54425e7ec6010c 100644
--- a/backend/base/src/main/resources/migrations/changelog.xml
+++ b/backend/base/src/main/resources/migrations/changelog.xml
@@ -47,5 +47,7 @@
   <include file="migrations/0037_add_maps-id-to-muk-facility-link.xml"/>
   <include file="migrations/0038_shedlock.xml"/>
   <include file="migrations/0039-add-countrycodes.xml"/>
+  <include file="migrations/0040_add_auditlog_entry.xml"/>
+  <include file="migrations/0041_remove_gdpr_status_open.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/build.gradle b/backend/build.gradle
index 8a19f90ac40f350a9282c1e423ceae6d5a565984..d2ee26a352df443c947b3c845b2ae4923729ff22 100644
--- a/backend/build.gradle
+++ b/backend/build.gradle
@@ -19,7 +19,8 @@ buildscript {
 plugins {
     id 'io.spring.dependency-management' version 'latest.release' apply false
     id 'com.avast.gradle.docker-compose' version 'latest.release' apply false
-    id 'org.springframework.boot' version 'latest.release' apply false
+    // âš  Note âš  Pinned to 3.4.1 because of https://github.com/spring-projects/spring-framework/issues/34324
+    id 'org.springframework.boot' version '3.4.1' apply false
     id 'org.cyclonedx.bom' version 'latest.release' apply false
     id 'com.trileuco.dependency-track-gradle' version 'latest.release' apply false
     id 'jacoco-report-aggregation'
@@ -61,7 +62,7 @@ sonar {
 //CAUTION: run ./gradlew wrapper (twice) after changes to this task!
 //See https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:upgrading_wrapper
 wrapper {
-    gradleVersion = "8.9"
+    gradleVersion = "8.12.1"
     distributionType = Wrapper.DistributionType.ALL
 }
 
@@ -257,9 +258,6 @@ subprojects {
         dependsOn findUnusedValidationFilesTask
     }
 
-    def springBootVersion = dependencyManagement.managedVersions['org.springframework.boot:spring-boot']
-    assert springBootVersion == "3.4.1": "Remove the dependency overwrite of 'hibernate.version' in gradle.properties since Spring Boot is updated to ${springBootVersion}"
-
     clean {
         delete test.outputs
     }
diff --git a/backend/buildSrc/src/main/groovy/eshg.service.gradle b/backend/buildSrc/src/main/groovy/eshg.service.gradle
index e872a90e03b43a5b9f886680c67ac86ac620931e..161bc76699512cfd41e8757806fd1e3748182244 100644
--- a/backend/buildSrc/src/main/groovy/eshg.service.gradle
+++ b/backend/buildSrc/src/main/groovy/eshg.service.gradle
@@ -76,7 +76,7 @@ bootJar {
 ext {
     listenPort = 8080
     additionalAptPackages = null
-    jreDockerImage = 'eclipse-temurin:21.0.5_11-jre-jammy@sha256:5d7781c6aabbc2f8673ec1899f2fdf6851f20c94dcdefeb8a1ca1e37e9c13e92'
+    jreDockerImage = 'eclipse-temurin:21.0.6_7-jre-noble@sha256:7cad9a0229472d691deae12aaa342dfc1541251a9bfc4557f65cdf0b81817ddd'
 }
 
 tasks.register('createDockerfile', Dockerfile) {
@@ -97,7 +97,7 @@ tasks.register('createDockerfile', Dockerfile) {
     def userName = 'eshg'
 
     runCommand("addgroup --system ${groupName}")
-    runCommand("adduser --shell /usr/sbin/nologin --system --home /app --ingroup ${groupName} --uid 1000 ${userName}")
+    runCommand("adduser --shell /usr/sbin/nologin --system --home /app --ingroup ${groupName} ${userName}")
     if (additionalAptPackages != null) {
         runCommand("DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ${additionalAptPackages} && rm -rf /var/lib/apt/lists/*")
     }
diff --git a/backend/business-module-commons/gradle.lockfile b/backend/business-module-commons/gradle.lockfile
index a53750b217d517cd758d7cc5aead8db225fbc996..20feb6af76568dd077246dd1b12d5b8716681e0f 100644
--- a/backend/business-module-commons/gradle.lockfile
+++ b/backend/business-module-commons/gradle.lockfile
@@ -53,10 +53,10 @@ io.prometheus:prometheus-metrics-exposition-formats:1.3.5=productionRuntimeClass
 io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.3.5=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -91,13 +91,13 @@ org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testFixturesCompileClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jetbrains:annotations:26.0.1=compileClasspath
+org.jetbrains:annotations:26.0.2=compileClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -112,16 +112,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
diff --git a/backend/business-module-persistence-commons/gradle.lockfile b/backend/business-module-persistence-commons/gradle.lockfile
index f2aa7273e59bc3ef7f5b90dc69853f8f4ba62f40..d4a16358e073af51b76b21b3935b52b104b0461c 100644
--- a/backend/business-module-persistence-commons/gradle.lockfile
+++ b/backend/business-module-persistence-commons/gradle.lockfile
@@ -60,10 +60,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -114,10 +114,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -135,16 +135,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
diff --git a/backend/business-module-persistence-commons/src/main/resources/common-persistence.properties b/backend/business-module-persistence-commons/src/main/resources/common-persistence.properties
index ab1884ca92e96e354fca112482e8dadf29a1f6b9..1a67572298420586e68548ee0180478d9a3e5ec2 100644
--- a/backend/business-module-persistence-commons/src/main/resources/common-persistence.properties
+++ b/backend/business-module-persistence-commons/src/main/resources/common-persistence.properties
@@ -13,3 +13,5 @@ spring.jpa.properties.hibernate.order_updates=true
 spring.jpa.properties.hibernate.batch_versioned_data=true
 
 spring.jpa.properties.hibernate.jdbc.fetch_size=100
+
+spring.jpa.properties.hibernate.type.preferred_duration_jdbc_type=INTERVAL_SECOND
diff --git a/backend/central-repository/gradle.lockfile b/backend/central-repository/gradle.lockfile
index 0fb3cb82f5c56df354deda1121c8e2316e096770..ac6f1e427b79cc4540948c069076bb8705cd8c09 100644
--- a/backend/central-repository/gradle.lockfile
+++ b/backend/central-repository/gradle.lockfile
@@ -60,10 +60,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -118,10 +118,10 @@ org.hibernate.common:hibernate-commons-annotations:7.0.3.Final=productionRuntime
 org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -139,16 +139,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/central-repository/src/main/java/de/eshg/centralrepository/config/CentralRepositorySecurityConfig.java b/backend/central-repository/src/main/java/de/eshg/centralrepository/config/CentralRepositorySecurityConfig.java
index 06b19a27db90bbf3ef39483d6d3ad88a2eef4295..15fcc7a5b930230c27e83e5b588548a39e36e282 100644
--- a/backend/central-repository/src/main/java/de/eshg/centralrepository/config/CentralRepositorySecurityConfig.java
+++ b/backend/central-repository/src/main/java/de/eshg/centralrepository/config/CentralRepositorySecurityConfig.java
@@ -5,8 +5,6 @@
 
 package de.eshg.centralrepository.config;
 
-import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
-
 import de.eshg.lib.common.EshgHttpHeaders;
 import de.eshg.rest.service.security.AuthorizationCustomizer;
 import de.eshg.rest.service.security.DefaultEshgSecurityConfig;
@@ -27,6 +25,7 @@ import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.web.SecurityFilterChain;
 import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
+import org.springframework.security.web.context.NullSecurityContextRepository;
 
 @Configuration
 public class CentralRepositorySecurityConfig {
@@ -43,6 +42,8 @@ public class CentralRepositorySecurityConfig {
     EshgHeaderPreAuthenticatedProcessingFilter eshgHeaderPreAuthenticatedProcessingFilter =
         new EshgHeaderPreAuthenticatedProcessingFilter();
     eshgHeaderPreAuthenticatedProcessingFilter.setAuthenticationManager(authenticationManager);
+    eshgHeaderPreAuthenticatedProcessingFilter.setSecurityContextRepository(
+        new NullSecurityContextRepository());
 
     return http.authorizeHttpRequests(
             auth -> {
@@ -61,7 +62,7 @@ public class CentralRepositorySecurityConfig {
         .formLogin(AbstractHttpConfigurer::disable)
         .httpBasic(AbstractHttpConfigurer::disable)
         .logout(AbstractHttpConfigurer::disable)
-        .sessionManagement(customizer -> customizer.sessionCreationPolicy(STATELESS))
+        .sessionManagement(AbstractHttpConfigurer::disable)
         .addFilter(eshgHeaderPreAuthenticatedProcessingFilter)
         .headers(DefaultEshgSecurityConfig::securityHeaders)
         .build();
diff --git a/backend/chat-management/gradle.lockfile b/backend/chat-management/gradle.lockfile
index e39e679051540954f42f9116546c85abe3c0c571..1ed92facd0e32c4739ab809c95f81d81839b23fd 100644
--- a/backend/chat-management/gradle.lockfile
+++ b/backend/chat-management/gradle.lockfile
@@ -61,10 +61,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -116,10 +116,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -137,16 +137,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/compliance-test/gradle.lockfile b/backend/compliance-test/gradle.lockfile
index cfac600db09c788df6be81bae3cf968512c6fb30..c77e4a7a514adcae323b627d1f17924c11ac7f19 100644
--- a/backend/compliance-test/gradle.lockfile
+++ b/backend/compliance-test/gradle.lockfile
@@ -3,8 +3,10 @@
 # This file is expected to be part of source control.
 ch.qos.logback:logback-classic:1.5.12=testCompileClasspath,testRuntimeClasspath
 ch.qos.logback:logback-core:1.5.12=testCompileClasspath,testRuntimeClasspath
+colt:colt:1.2.0=testRuntimeClasspath
 com.adobe.xmp:xmpcore:6.1.11=testRuntimeClasspath
 com.bucket4j:bucket4j-core:8.10.1=testRuntimeClasspath
+com.carrotsearch:hppc:0.6.0=testRuntimeClasspath
 com.drewnoakes:metadata-extractor:2.19.0=testRuntimeClasspath
 com.fasterxml.jackson.core:jackson-annotations:2.18.2=testCompileClasspath,testRuntimeClasspath
 com.fasterxml.jackson.core:jackson-core:2.18.2=testCompileClasspath,testRuntimeClasspath
@@ -100,6 +102,7 @@ commons-codec:commons-codec:1.17.1=testCompileClasspath,testRuntimeClasspath
 commons-collections:commons-collections:3.2.2=testRuntimeClasspath
 commons-io:commons-io:2.18.0=testCompileClasspath,testRuntimeClasspath
 commons-logging:commons-logging:1.3.4=testRuntimeClasspath
+concurrent:concurrent:1.3.4=testRuntimeClasspath
 de.cronn:commons-lang:1.3=testCompileClasspath,testRuntimeClasspath
 de.cronn:liquibase-postgres-enum-extension:1.1=testRuntimeClasspath
 de.cronn:postgres-snapshot-util:1.4=testRuntimeClasspath
@@ -110,7 +113,7 @@ de.rototor.pdfbox:graphics2d:3.0.1=testRuntimeClasspath
 de.topobyte:adt-multicollections:0.0.4=testRuntimeClasspath
 de.topobyte:osm4j-core:1.4.0=testRuntimeClasspath
 de.topobyte:osm4j-pbf:1.4.0=testRuntimeClasspath
-dnsjava:dnsjava:3.6.2=testRuntimeClasspath
+dnsjava:dnsjava:3.6.3=testRuntimeClasspath
 info.picocli:picocli:4.7.6=testRuntimeClasspath
 io.github.hakky54:sslcontext-kickstart-for-netty:9.0.0=testRuntimeClasspath
 io.github.hakky54:sslcontext-kickstart:9.0.0=testRuntimeClasspath
@@ -152,10 +155,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=testRuntimeClasspa
 io.prometheus:prometheus-metrics-model:1.3.5=testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=testRuntimeClasspath
 io.smallrye:jandex:3.2.0=testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=testCompileClasspath,testRuntimeClasspath
 io.swagger:swagger-annotations:1.6.15=testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
@@ -274,10 +277,10 @@ org.hibernate.common:hibernate-commons-annotations:7.0.3.Final=testRuntimeClassp
 org.hibernate.orm:hibernate-core:6.6.4.Final=testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-envers:6.6.4.Final=testCompileClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.java-websocket:Java-WebSocket:1.6.0=testRuntimeClasspath
 org.javassist:javassist:3.28.0-GA=testCompileClasspath,testRuntimeClasspath
 org.jboss.logging:commons-logging-jboss-logging:1.0.0.Final=testRuntimeClasspath
@@ -305,16 +308,17 @@ org.keycloak:keycloak-client-common-synced:26.0.3=testRuntimeClasspath
 org.latencyutils:LatencyUtils:2.0.3=testRuntimeClasspath
 org.liquibase:liquibase-core:4.29.2=testRuntimeClasspath
 org.lz4:lz4-java:1.8.0=testRuntimeClasspath
-org.mnode.ical4j:ical4j:4.0.8=testRuntimeClasspath
+org.mnode.ical4j:ical4j:4.1.0=testRuntimeClasspath
 org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mozilla:rhino:1.7.13=testRuntimeClasspath
 org.objenesis:objenesis:3.4=testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.reactivestreams:reactive-streams:1.0.4=testRuntimeClasspath
 org.reflections:reflections:0.10.2=testCompileClasspath,testRuntimeClasspath
@@ -322,7 +326,7 @@ org.rnorth.duct-tape:duct-tape:1.0.8=testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/dental/gradle.lockfile b/backend/dental/gradle.lockfile
index 0fbd5407e2453743bb90bdb030eb60aef87c977e..03d1be535a86413ba0f5043a301bc2b886f05dbd 100644
--- a/backend/dental/gradle.lockfile
+++ b/backend/dental/gradle.lockfile
@@ -70,10 +70,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -148,10 +148,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -170,16 +170,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/dental/openApi.json b/backend/dental/openApi.json
index 2d20461f41d64a3a1c93ccd668e357301eb784f8..4c9998473728db8586a7fec365bf93dde1d4e432 100644
--- a/backend/dental/openApi.json
+++ b/backend/dental/openApi.json
@@ -3863,7 +3863,7 @@
         } ]
       },
       "Examination" : {
-        "required" : [ "dateAndTime", "fluoridationConsentGiven", "id", "isFluoridation", "isScreening", "prophylaxisType", "version" ],
+        "required" : [ "dateAndTime", "id", "isFluoridation", "isScreening", "prophylaxisType", "version" ],
         "type" : "object",
         "properties" : {
           "dateAndTime" : {
@@ -3905,7 +3905,7 @@
         }
       },
       "ExistingUser" : {
-        "required" : [ "firstName", "lastName" ],
+        "required" : [ "firstName", "id", "lastName" ],
         "type" : "object",
         "allOf" : [ {
           "$ref" : "#/components/schemas/PerformingPerson"
@@ -4024,7 +4024,6 @@
         }
       },
       "FluoridationExaminationResult" : {
-        "required" : [ "fluorideVarnishApplied" ],
         "type" : "object",
         "allOf" : [ {
           "$ref" : "#/components/schemas/DentalExaminationResult"
@@ -5376,6 +5375,7 @@
         }
       },
       "NonExistingUser" : {
+        "required" : [ "id" ],
         "type" : "object",
         "allOf" : [ {
           "$ref" : "#/components/schemas/PerformingPerson"
@@ -5450,11 +5450,15 @@
         } ]
       },
       "PerformingPerson" : {
-        "required" : [ "@type" ],
+        "required" : [ "@type", "id" ],
         "type" : "object",
         "properties" : {
           "@type" : {
             "type" : "string"
+          },
+          "id" : {
+            "type" : "string",
+            "format" : "uuid"
           }
         },
         "discriminator" : {
@@ -5920,7 +5924,7 @@
         "enum" : [ "NOT_SPECIFIED", "NEUTRAL", "FEMALE", "MALE" ]
       },
       "ScreeningExaminationResult" : {
-        "required" : [ "fluorideVarnishApplied", "toothDiagnoses" ],
+        "required" : [ "toothDiagnoses" ],
         "type" : "object",
         "allOf" : [ {
           "$ref" : "#/components/schemas/DentalExaminationResult"
@@ -6322,19 +6326,30 @@
         }
       },
       "UpdateProphylaxisSessionRequest" : {
-        "required" : [ "dateAndTime", "groupName", "isScreening", "type", "version" ],
+        "required" : [ "dateAndTime", "dentistIds", "groupName", "institutionId", "isScreening", "type", "version", "zfaIds" ],
         "type" : "object",
         "properties" : {
           "dateAndTime" : {
             "type" : "string",
             "format" : "date-time"
           },
+          "dentistIds" : {
+            "type" : "array",
+            "items" : {
+              "type" : "string",
+              "format" : "uuid"
+            }
+          },
           "fluoridationVarnish" : {
             "$ref" : "#/components/schemas/FluoridationVarnish"
           },
           "groupName" : {
             "type" : "string"
           },
+          "institutionId" : {
+            "type" : "string",
+            "format" : "uuid"
+          },
           "isScreening" : {
             "type" : "boolean"
           },
@@ -6344,6 +6359,13 @@
           "version" : {
             "type" : "integer",
             "format" : "int64"
+          },
+          "zfaIds" : {
+            "type" : "array",
+            "items" : {
+              "type" : "string",
+              "format" : "uuid"
+            }
           }
         }
       },
diff --git a/backend/dental/src/main/java/de/eshg/dental/ChildController.java b/backend/dental/src/main/java/de/eshg/dental/ChildController.java
index d99e4d59b9b98355835a89740e24f729d93c4544..4f2b4ff10c200542fb8376081c36de387abb2fb0 100644
--- a/backend/dental/src/main/java/de/eshg/dental/ChildController.java
+++ b/backend/dental/src/main/java/de/eshg/dental/ChildController.java
@@ -166,7 +166,7 @@ public class ChildController {
       @PathVariable("examinationId") UUID examinationId,
       @Valid @RequestBody UpdateExaminationRequest request) {
     Examination examination = examinationService.findExaminationForUpdate(examinationId);
-    examinationService.updateExamination(examination, request);
+    examinationService.updateExaminationAndFlush(examination, request);
     return ExaminationMapper.mapToDto(examination);
   }
 
diff --git a/backend/dental/src/main/java/de/eshg/dental/ChildService.java b/backend/dental/src/main/java/de/eshg/dental/ChildService.java
index 079fdffead46d8063edd1ef52e05aa50665e5960..f1a694d5f14348199f2c0e3e5d94d93a9dab96d0 100644
--- a/backend/dental/src/main/java/de/eshg/dental/ChildService.java
+++ b/backend/dental/src/main/java/de/eshg/dental/ChildService.java
@@ -60,6 +60,7 @@ import de.eshg.rest.service.error.NotFoundException;
 import de.eshg.validation.ValidationUtil;
 import java.io.IOException;
 import java.time.Clock;
+import java.time.Instant;
 import java.time.Year;
 import java.util.Collection;
 import java.util.Collections;
@@ -259,7 +260,7 @@ public class ChildService {
         .map(ChildWithAugmentedData::child)
         .map(Child::getFluoridationConsents)
         .flatMap(Collection::stream)
-        .sorted(Comparator.comparing(FluoridationConsent::dateOfConsent).reversed())
+        .sorted(Comparator.comparing(FluoridationConsent::getModifiedAt).reversed())
         .toList();
   }
 
@@ -407,7 +408,7 @@ public class ChildService {
           ChildImporter importer =
               new ChildImporter(
                   sheet,
-                  new ChildRowReader(sheet, actualColumns),
+                  new ChildRowReader(sheet, clock, actualColumns),
                   new FeedbackColumnAccessor(actualColumns, ChildColumn.CHILD_ID.getHeader()),
                   institutionId,
                   year,
@@ -485,20 +486,28 @@ public class ChildService {
 
     FluoridationConsent requestedFluoridationConsent =
         ChildMapper.mapFluoridationToDomain(request.fluoridationConsent());
-    List<FluoridationConsent> persistedFluoridationConsents = child.getFluoridationConsents();
+    FluoridationConsent persistedFluoridationConsent = child.getCurrentFluoridationConsent();
     boolean updateFluoridationConsent =
         requestedFluoridationConsent != null
-            && (persistedFluoridationConsents.isEmpty()
-                || !Objects.equals(
-                    requestedFluoridationConsent, persistedFluoridationConsents.getLast()));
+            && (persistedFluoridationConsent == null
+                || !fluoridationConsentsMatch(
+                    requestedFluoridationConsent, persistedFluoridationConsent));
 
     if (updateFluoridationConsent) {
+      requestedFluoridationConsent.setModifiedAt(Instant.now(clock));
       child.addFluoridationConsent(requestedFluoridationConsent);
     }
 
     childRepository.flush();
   }
 
+  private boolean fluoridationConsentsMatch(
+      FluoridationConsent fluoridationConsent1, FluoridationConsent fluoridationConsent2) {
+    return fluoridationConsent1.isConsented() == fluoridationConsent2.isConsented()
+        && Objects.equals(fluoridationConsent1.hasAllergy(), fluoridationConsent2.hasAllergy())
+        && fluoridationConsent1.getDateOfConsent().equals(fluoridationConsent2.getDateOfConsent());
+  }
+
   private void addSystemProgressEntry(
       Child child, ChildSystemProgressEntryType childSystemProgressEntryType) {
     progressEntryUtil.addSystemProgressEntry(child, childSystemProgressEntryType);
diff --git a/backend/dental/src/main/java/de/eshg/dental/ExaminationService.java b/backend/dental/src/main/java/de/eshg/dental/ExaminationService.java
index fdb952c1d82b52f9882b20c608b00c3530321446..ef6ecd79a4501c4472fd1234c4db662eb2300e08 100644
--- a/backend/dental/src/main/java/de/eshg/dental/ExaminationService.java
+++ b/backend/dental/src/main/java/de/eshg/dental/ExaminationService.java
@@ -5,16 +5,12 @@
 
 package de.eshg.dental;
 
-import static de.eshg.dental.mapper.ExaminationMapper.mapToDomain;
-
 import de.cronn.reflection.util.ClassUtils;
 import de.eshg.dental.api.AbsenceExaminationResultDto;
 import de.eshg.dental.api.ExaminationResultDto;
 import de.eshg.dental.api.FluoridationExaminationResultDto;
 import de.eshg.dental.api.IsFluorideVarnishApplicable;
 import de.eshg.dental.api.ScreeningExaminationResultDto;
-import de.eshg.dental.api.ToothDiagnosisDto;
-import de.eshg.dental.api.ToothDto;
 import de.eshg.dental.api.UpdateExaminationRequest;
 import de.eshg.dental.domain.model.AbsenceExaminationResult;
 import de.eshg.dental.domain.model.Examination;
@@ -22,21 +18,17 @@ import de.eshg.dental.domain.model.ExaminationResult;
 import de.eshg.dental.domain.model.FluoridationExaminationResult;
 import de.eshg.dental.domain.model.ProphylaxisSession;
 import de.eshg.dental.domain.model.ScreeningExaminationResult;
-import de.eshg.dental.domain.model.Tooth;
-import de.eshg.dental.domain.model.ToothDiagnosis;
 import de.eshg.dental.domain.repository.ExaminationRepository;
+import de.eshg.dental.mapper.ExaminationMapper;
 import de.eshg.dental.util.ChildSystemProgressEntryType;
 import de.eshg.dental.util.ExceptionUtil;
 import de.eshg.dental.util.ProgressEntryUtil;
 import de.eshg.rest.service.error.BadRequestException;
 import de.eshg.rest.service.error.NotFoundException;
 import de.eshg.validation.ValidationUtil;
-import java.util.List;
-import java.util.Map;
 import java.util.UUID;
 import java.util.function.Consumer;
 import org.springframework.stereotype.Component;
-import org.springframework.util.Assert;
 
 @Component
 public class ExaminationService {
@@ -62,13 +54,17 @@ public class ExaminationService {
         .orElseThrow(ExaminationService::examinationNotFoundException);
   }
 
+  void updateExaminationAndFlush(Examination examination, UpdateExaminationRequest request) {
+    updateExamination(examination, request);
+    examinationRepository.flush();
+  }
+
   void updateExamination(Examination examination, UpdateExaminationRequest request) {
     ValidationUtil.validateVersion(request.version(), examination);
     examination.setNote(request.note());
     updateResult(examination, request.result());
     progressEntryUtil.addSystemProgressEntry(
         examination.getChild(), ChildSystemProgressEntryType.EXAMINATION_MODIFIED);
-    examinationRepository.flush();
   }
 
   private void updateResult(Examination examination, ExaminationResultDto newResult) {
@@ -94,22 +90,28 @@ public class ExaminationService {
 
   private static void validateExaminationResult(
       Examination examination, ExaminationResultDto newResult) {
-    if (newResult == null || newResult instanceof AbsenceExaminationResultDto) {
+    if (newResult == null) {
       return;
     }
 
     ProphylaxisSession prophylaxisSession = examination.getProphylaxisSession();
     if (prophylaxisSession.isScreening()) {
+      if (newResult instanceof AbsenceExaminationResultDto) {
+        return;
+      }
       if (!(newResult instanceof ScreeningExaminationResultDto screeningExaminationResult)) {
         throw newIllegalExaminationResultException(newResult, ScreeningExaminationResultDto.class);
       }
-      if (screeningExaminationResult.fluorideVarnishApplied()
+      if (screeningExaminationResult.isFluorideVarnishAppliedOrFalse()
           && !prophylaxisSession.hasFluoridationVarnish()) {
         throw newIllegalExaminationResultException(
             "Got fluorideVarnishApplied=true but no fluoridation varnish is configured for prophylaxis session");
       }
       Validator.validateToothDiagnoses(screeningExaminationResult.toothDiagnoses());
     } else if (prophylaxisSession.hasFluoridationVarnish()) {
+      if (newResult instanceof AbsenceExaminationResultDto) {
+        return;
+      }
       if (!(newResult instanceof FluoridationExaminationResultDto)) {
         throw newIllegalExaminationResultException(
             newResult, FluoridationExaminationResultDto.class);
@@ -119,7 +121,7 @@ public class ExaminationService {
     }
 
     if (newResult instanceof IsFluorideVarnishApplicable fluorideVarnishApplicableResult
-        && fluorideVarnishApplicableResult.fluorideVarnishApplied()
+        && fluorideVarnishApplicableResult.isFluorideVarnishAppliedOrFalse()
         && !examination.getChild().isFluoridationConsentCurrentlyGiven()) {
       throw newIllegalExaminationResultException(
           "Got fluorideVarnishApplied=true but fluoridation consent is not given");
@@ -140,77 +142,54 @@ public class ExaminationService {
   }
 
   private void mapResult(Examination examination, ScreeningExaminationResultDto newResult) {
-    Map<Tooth, ToothDiagnosis> persistedToothDiagnoses = Map.of();
-    if (examination.getResult() instanceof ScreeningExaminationResult screeningExaminationResult
-        && !newResult.toothDiagnoses().isEmpty()) {
-      List<ToothDto> teeth =
-          newResult.toothDiagnoses().stream().map(ToothDiagnosisDto::tooth).toList();
-      persistedToothDiagnoses = screeningExaminationResult.getToothDiagnoses();
-
-      removeMatchingTeethFromPersistedTeeth(teeth, persistedToothDiagnoses);
-    }
-
-    Map<Tooth, ToothDiagnosis> newToothDiagnoses = mapToDomain(newResult.toothDiagnoses());
-    newToothDiagnoses.putAll(persistedToothDiagnoses);
     mapResult(
         examination,
         ScreeningExaminationResult.class,
         existingResult -> {
           existingResult.setFluorideVarnishApplied(newResult.fluorideVarnishApplied());
-          existingResult.setOralHygieneStatus(mapToDomain(newResult.oralHygieneStatus()));
-          existingResult.setToothDiagnoses(newToothDiagnoses);
+          existingResult.setOralHygieneStatus(
+              ExaminationMapper.mapToDomain(newResult.oralHygieneStatus()));
+          existingResult.setToothDiagnoses(
+              ExaminationMapper.mapToDomain(newResult.toothDiagnoses()));
         });
   }
 
-  private static void removeMatchingTeethFromPersistedTeeth(
-      List<ToothDto> teeth, Map<Tooth, ToothDiagnosis> persistedToothDiagnoses) {
-    for (ToothDto tooth : teeth) {
-      // milk teeth
-      Tooth matchingPermanentTooth =
-          mapToDomain(ToothDto.matchingPermanentToothForMilkTooth(tooth));
-      if (matchingPermanentTooth != null) {
-        persistedToothDiagnoses.remove(matchingPermanentTooth);
-      }
-
-      // permanentTeeth
-      Tooth matchingMilkTooth = mapToDomain(ToothDto.matchingMilkToothForPermanentTooth(tooth));
-      if (matchingMilkTooth != null) {
-        persistedToothDiagnoses.remove(matchingMilkTooth);
-      }
-
-      persistedToothDiagnoses.remove(mapToDomain(tooth));
-    }
-  }
-
   private void mapResult(Examination examination, AbsenceExaminationResultDto newResult) {
     mapResult(
         examination,
         AbsenceExaminationResult.class,
         existingResult ->
-            existingResult.setReasonForAbsence(mapToDomain(newResult.reasonForAbsence())));
+            existingResult.setReasonForAbsence(
+                ExaminationMapper.mapToDomain(newResult.reasonForAbsence())));
   }
 
   private <R extends ExaminationResult> void mapResult(
       Examination examination, Class<R> expectedResultClass, Consumer<R> mapping) {
     ExaminationResult existingResult = examination.getResult();
-    if (existingResult != null) {
+    if (existingResult == null || existingResult instanceof AbsenceExaminationResult) {
+      acceptAndSetResult(examination, expectedResultClass, mapping);
+    } else {
       Class<? extends ExaminationResult> examinationResultClass =
           ClassUtils.getRealClass(existingResult);
-      Assert.isTrue(
-          examinationResultClass.equals(expectedResultClass),
-          () ->
-              "Cannot change examination result class from %s to %s"
-                  .formatted(examinationResultClass, expectedResultClass));
+      if (!examinationResultClass.equals(expectedResultClass)) {
+        throw new BadRequestException(
+            "Illegal examination result type",
+            "Cannot change examination result class from %s to %s"
+                .formatted(examinationResultClass, expectedResultClass));
+      }
       @SuppressWarnings("unchecked") // We actually did check the type
       R castedResult = (R) existingResult;
       mapping.accept(castedResult);
-    } else {
-      R result = ClassUtils.createNewInstance(expectedResultClass);
-      mapping.accept(result);
-      examination.setResult(result);
     }
   }
 
+  private static <R extends ExaminationResult> void acceptAndSetResult(
+      Examination examination, Class<R> expectedResultClass, Consumer<R> mapping) {
+    R result = ClassUtils.createNewInstance(expectedResultClass);
+    mapping.accept(result);
+    examination.setResult(result);
+  }
+
   private static NotFoundException examinationNotFoundException() {
     return ExceptionUtil.notFoundException(Examination.class);
   }
diff --git a/backend/dental/src/main/java/de/eshg/dental/ProphylaxisSessionService.java b/backend/dental/src/main/java/de/eshg/dental/ProphylaxisSessionService.java
index bf78d43199023d5aabae943573c545c6a5c1a793..53247b32d833f0841434de35948abe0c95ca84ec 100644
--- a/backend/dental/src/main/java/de/eshg/dental/ProphylaxisSessionService.java
+++ b/backend/dental/src/main/java/de/eshg/dental/ProphylaxisSessionService.java
@@ -25,12 +25,12 @@ import de.eshg.dental.business.model.ProphylaxisSessionWithAugmentedInstitution;
 import de.eshg.dental.client.PersonClient;
 import de.eshg.dental.domain.model.Child;
 import de.eshg.dental.domain.model.Examination;
+import de.eshg.dental.domain.model.Person;
 import de.eshg.dental.domain.model.ProphylaxisSession;
 import de.eshg.dental.domain.repository.ChildRepository;
 import de.eshg.dental.domain.repository.ExaminationRepository;
 import de.eshg.dental.domain.repository.ProphylaxisSessionRepository;
 import de.eshg.dental.mapper.ProphylaxisSessionMapper;
-import de.eshg.domain.model.BaseEntityWithExternalId;
 import de.eshg.lib.contact.ContactClient;
 import de.eshg.lib.procedure.domain.model.ProcedureStatus;
 import de.eshg.rest.service.error.BadRequestException;
@@ -44,6 +44,7 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.slf4j.Logger;
@@ -92,9 +93,6 @@ public class ProphylaxisSessionService {
   public ProphylaxisSession createProphylaxisSession(CreateProphylaxisSessionRequest request) {
     ProphylaxisSession session = new ProphylaxisSession();
     mapProphylaxisSessionRequest(session, request);
-    session.setInstitutionId(request.institutionId());
-    session.setDentistIds(request.dentistIds());
-    session.setZfaIds(request.zfaIds());
     addExaminationsForChildren(request, session);
     prophylaxisSessionRepository.save(session);
     return session;
@@ -198,8 +196,11 @@ public class ProphylaxisSessionService {
             .toList();
 
     Map<UUID, List<Examination>> examinationsByFileStateId =
-        examinationRepository.findAllByChildFileStateIds(allFileStateIds).stream()
-            .collect(Collectors.groupingBy(ex -> ex.getChild().getChildIdFromCentralFile()));
+        examinationRepository
+            .findAllByPersonFileStateIds(Person.PERSON_TYPE_USED_FOR_CHILDREN, allFileStateIds)
+            .collect(
+                Collectors.groupingBy(
+                    examination -> examination.getChild().getChildIdFromCentralFile()));
 
     Map<UUID, List<Examination>> previousExaminationsBySessionChildFileStateId =
         fileStateIdsOfChildrenInSession.stream()
@@ -233,9 +234,18 @@ public class ProphylaxisSessionService {
                     .map(examinationsByChildFileStateId::get)
                     .filter(Objects::nonNull)
                     .flatMap(List::stream))
+            .filter(isBefore(prophylaxisSessionToIgnore))
             .toList();
   }
 
+  private static Predicate<Examination> isBefore(ProphylaxisSession prophylaxisSession) {
+    return examination ->
+        examination
+            .getProphylaxisSession()
+            .getDateAndTime()
+            .isBefore(prophylaxisSession.getDateAndTime());
+  }
+
   private Map<UUID, GetPersonFileStateResponse> fetchPersonFileStatesInBulk(
       List<Examination> examinations) {
     List<Child> children = examinations.stream().map(Examination::getChild).toList();
@@ -320,6 +330,9 @@ public class ProphylaxisSessionService {
       UUID prophylaxisSessionId, UpdateProphylaxisSessionRequest updateRequest) {
     ProphylaxisSession persistedProphylaxisSession =
         findProphylaxisSessionForUpdate(prophylaxisSessionId, updateRequest.version());
+    Validator.validateUpdatableFields(
+        persistedProphylaxisSession,
+        mapProphylaxisSessionRequest(new ProphylaxisSession(), updateRequest));
     validator.validateGroupAtInstitutionExists(
         persistedProphylaxisSession.getInstitutionId(), updateRequest.groupName());
 
@@ -337,30 +350,38 @@ public class ProphylaxisSessionService {
             .map(UpdateExaminationsInBulkRequest::id)
             .toList();
 
+    List<Long> ids = examinationRepository.findAllByExternalIdsForUpdate(examinationIds);
     Map<UUID, Examination> persistedExaminations =
-        examinationRepository.findAllByExternalIdsForUpdate(examinationIds).stream()
-            .collect(
-                Collectors.toMap(BaseEntityWithExternalId::getExternalId, Function.identity()));
+        examinationRepository
+            .fetchByIds(ids)
+            .collect(StreamUtil.toLinkedHashMap(Examination::getExternalId));
 
     for (UpdateExaminationsInBulkRequest examinationUpdate : updateRequest.examinationUpdates()) {
       Examination persistedExamination = persistedExaminations.get(examinationUpdate.id());
-
+      if (persistedExamination == null) {
+        throw new NotFoundException(
+            "Examination with id %s not found".formatted(examinationUpdate.id()));
+      }
       examinationService.updateExamination(
           persistedExamination,
           new UpdateExaminationRequest(
               examinationUpdate.version(), examinationUpdate.note(), examinationUpdate.result()));
     }
-
+    examinationRepository.flush();
     return getProphylaxisSessionWithDetails(prophylaxisSessionId);
   }
 
-  private void mapProphylaxisSessionRequest(
+  private ProphylaxisSession mapProphylaxisSessionRequest(
       ProphylaxisSession session, ProphylaxisSessionRequest request) {
+    session.setInstitutionId(request.institutionId());
     session.setDateAndTime(request.dateAndTime());
     session.setGroupName(request.groupName());
     session.setType(ProphylaxisSessionMapper.mapToDomain(request.type()));
     session.setIsScreening(request.isScreening());
     session.setFluoridationVarnish(
         ProphylaxisSessionMapper.mapToDomain(request.fluoridationVarnish()));
+    session.setDentistIds(request.dentistIds());
+    session.setZfaIds(request.zfaIds());
+    return session;
   }
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/Validator.java b/backend/dental/src/main/java/de/eshg/dental/Validator.java
index 9f65e6ef483f99401f86937065f96d5ee40c4c52..7e3d32479737c0b83776dd0bcace28f96c2c6eeb 100644
--- a/backend/dental/src/main/java/de/eshg/dental/Validator.java
+++ b/backend/dental/src/main/java/de/eshg/dental/Validator.java
@@ -8,6 +8,8 @@ package de.eshg.dental;
 import static de.eshg.lib.procedure.util.ProcedureValidator.hasNonNullValue;
 
 import de.cronn.commons.lang.StreamUtil;
+import de.cronn.reflection.util.PropertyGetter;
+import de.cronn.reflection.util.PropertyUtils;
 import de.eshg.base.contact.api.InstitutionContactCategoryDto;
 import de.eshg.base.user.UserApi;
 import de.eshg.base.user.api.UserDto;
@@ -15,16 +17,20 @@ import de.eshg.dental.api.ChildFilterParameters;
 import de.eshg.dental.api.FluoridationConsentDto;
 import de.eshg.dental.api.ToothDiagnosisDto;
 import de.eshg.dental.api.ToothDto;
+import de.eshg.dental.domain.model.Examination;
+import de.eshg.dental.domain.model.ProphylaxisSession;
 import de.eshg.dental.domain.repository.ChildRepository;
 import de.eshg.lib.contact.ContactClient;
 import de.eshg.lib.keycloak.TechnicalGroup;
 import de.eshg.lib.procedure.api.ProcedureSearchParameters;
 import de.eshg.lib.procedure.domain.model.ProcedureStatus;
 import de.eshg.rest.service.error.BadRequestException;
+import java.beans.PropertyDescriptor;
 import java.time.Clock;
 import java.time.Year;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 import org.springframework.stereotype.Component;
@@ -37,6 +43,13 @@ public class Validator {
   private final ChildRepository childRepository;
   private final UserApi userApi;
 
+  private static final List<PropertyGetter<ProphylaxisSession>> UPDATABLE_WITHOUT_RESULT_ONLY =
+      List.of(
+          ProphylaxisSession::getInstitutionId,
+          ProphylaxisSession::getGroupName,
+          ProphylaxisSession::isScreening,
+          ProphylaxisSession::getFluoridationVarnish);
+
   public Validator(
       Clock clock, ContactClient contactClient, ChildRepository childRepository, UserApi userApi) {
     this.clock = clock;
@@ -135,4 +148,27 @@ public class Validator {
       throw new BadRequestException("There are teeth twice in the list.");
     }
   }
+
+  public static void validateUpdatableFields(
+      ProphylaxisSession current, ProphylaxisSession update) {
+    boolean hasExaminationResult =
+        current.getExaminations().stream().anyMatch(Examination::hasResult);
+    if (hasExaminationResult) {
+      UPDATABLE_WITHOUT_RESULT_ONLY.forEach(
+          valueGetter -> validateNotChanged(current, update, valueGetter));
+    }
+  }
+
+  private static void validateNotChanged(
+      ProphylaxisSession current,
+      ProphylaxisSession update,
+      PropertyGetter<ProphylaxisSession> valueGetter) {
+    if (!Objects.equals(valueGetter.get(current), valueGetter.get(update))) {
+      PropertyDescriptor property = PropertyUtils.getPropertyDescriptor(current, valueGetter);
+      throw new BadRequestException(
+          String.format(
+              "The '%s' property cannot be modified once examination results have been entered.",
+              property.getDisplayName()));
+    }
+  }
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/CreateChildRequest.java b/backend/dental/src/main/java/de/eshg/dental/api/CreateChildRequest.java
index 1546a3570851096a2d17c10c38fa5963813fdce0..d32a492e5283950258261e33248d1f46283df858 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/CreateChildRequest.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/CreateChildRequest.java
@@ -9,6 +9,7 @@ import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.DateOfBirth;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
@@ -25,7 +26,7 @@ public record CreateChildRequest(
     @NotNull @Size(min = 1, max = 80) String firstName,
     @NotNull @Size(min = 1, max = 120) String lastName,
     GenderDto gender,
-    @NotNull LocalDate dateOfBirth,
+    @NotNull @DateOfBirth LocalDate dateOfBirth,
     @Size(min = 1, max = 40) String nameAtBirth,
     @Size(min = 1, max = 50) String placeOfBirth,
     CountryCode countryOfBirth,
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/ExaminationDto.java b/backend/dental/src/main/java/de/eshg/dental/api/ExaminationDto.java
index 9c17af8dccbafb1725be8ae18437f0c22737896f..4d1052174978322b6c634bba823a1d596285c97e 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/ExaminationDto.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/ExaminationDto.java
@@ -19,6 +19,6 @@ public record ExaminationDto(
     @NotNull ProphylaxisTypeDto prophylaxisType,
     @NotNull boolean isScreening,
     @NotNull boolean isFluoridation,
-    @NotNull boolean fluoridationConsentGiven,
+    Boolean fluoridationConsentGiven,
     String note,
     @Valid ExaminationResultDto result) {}
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/ExistingUserDto.java b/backend/dental/src/main/java/de/eshg/dental/api/ExistingUserDto.java
index 456f520521f39f1b827d726a4ba966aa77735288..00b682d009b83f57866d2cb289f9853c15353993 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/ExistingUserDto.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/ExistingUserDto.java
@@ -7,9 +7,10 @@ package de.eshg.dental.api;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotNull;
+import java.util.UUID;
 
 @Schema(name = ExistingUserDto.SCHEMA_NAME)
-public record ExistingUserDto(@NotNull String firstName, @NotNull String lastName)
+public record ExistingUserDto(@NotNull UUID id, @NotNull String firstName, @NotNull String lastName)
     implements PerformingPersonDto {
   public static final String SCHEMA_NAME = "ExistingUser";
 
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/FluoridationExaminationResultDto.java b/backend/dental/src/main/java/de/eshg/dental/api/FluoridationExaminationResultDto.java
index b4a176f4c707659e4049c71cdbca817cd47063ea..1e741adbb090de0365b59ee4d3b43636a189cc5a 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/FluoridationExaminationResultDto.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/FluoridationExaminationResultDto.java
@@ -6,14 +6,17 @@
 package de.eshg.dental.api;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotNull;
 
 @Schema(name = FluoridationExaminationResultDto.SCHEMA_NAME)
-public record FluoridationExaminationResultDto(@NotNull boolean fluorideVarnishApplied)
+public record FluoridationExaminationResultDto(Boolean fluorideVarnishApplied)
     implements ExaminationResultDto, IsFluorideVarnishApplicable {
 
   static final String SCHEMA_NAME = "FluoridationExaminationResult";
 
+  public FluoridationExaminationResultDto() {
+    this(null);
+  }
+
   @Override
   public String type() {
     return SCHEMA_NAME;
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/IsFluorideVarnishApplicable.java b/backend/dental/src/main/java/de/eshg/dental/api/IsFluorideVarnishApplicable.java
index f2dc46b9bc83a13309ad3c1465c780b8760aa181..21b15366328776d1fb02ac1140ccdd36cf47c721 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/IsFluorideVarnishApplicable.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/IsFluorideVarnishApplicable.java
@@ -5,6 +5,14 @@
 
 package de.eshg.dental.api;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.apache.commons.lang3.BooleanUtils;
+
 public interface IsFluorideVarnishApplicable {
-  boolean fluorideVarnishApplied();
+  Boolean fluorideVarnishApplied();
+
+  @JsonIgnore
+  default boolean isFluorideVarnishAppliedOrFalse() {
+    return BooleanUtils.isTrue(fluorideVarnishApplied());
+  }
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/NonExistingUserDto.java b/backend/dental/src/main/java/de/eshg/dental/api/NonExistingUserDto.java
index 2dd9b7fddc4b407741d14ba23bf83035b5d6c648..67378b1f791dccfc3f4dd0c6fe86ab6eb1c104eb 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/NonExistingUserDto.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/NonExistingUserDto.java
@@ -6,9 +6,11 @@
 package de.eshg.dental.api;
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import java.util.UUID;
 
 @Schema(name = NonExistingUserDto.SCHEMA_NAME)
-public record NonExistingUserDto() implements PerformingPersonDto {
+public record NonExistingUserDto(@NotNull UUID id) implements PerformingPersonDto {
   public static final String SCHEMA_NAME = "NonExistingUser";
 
   @Override
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/PerformingPersonDto.java b/backend/dental/src/main/java/de/eshg/dental/api/PerformingPersonDto.java
index 506bb6899c598f1e2369f52bcadafef0eb28f48f..5eece77b3ee7897a29790d2fedff9c9ea00cad47 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/PerformingPersonDto.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/PerformingPersonDto.java
@@ -5,10 +5,13 @@
 
 package de.eshg.dental.api;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonSubTypes;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import de.eshg.base.HasTypeDiscriminator;
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import java.util.UUID;
 
 @Schema(name = "PerformingPerson")
 @JsonTypeInfo(
@@ -20,4 +23,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
   @JsonSubTypes.Type(value = NonExistingUserDto.class, name = NonExistingUserDto.SCHEMA_NAME)
 })
 public sealed interface PerformingPersonDto extends HasTypeDiscriminator
-    permits ExistingUserDto, NonExistingUserDto {}
+    permits ExistingUserDto, NonExistingUserDto {
+  @NotNull
+  @JsonProperty
+  UUID id();
+}
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/ProphylaxisSessionRequest.java b/backend/dental/src/main/java/de/eshg/dental/api/ProphylaxisSessionRequest.java
index a30d77a7f3e0386fba9c650bd52d9a329bf85fe1..f49e0e606d9042c42971415129e54eb57b76f677 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/ProphylaxisSessionRequest.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/ProphylaxisSessionRequest.java
@@ -6,8 +6,12 @@
 package de.eshg.dental.api;
 
 import java.time.Instant;
+import java.util.List;
+import java.util.UUID;
 
 public interface ProphylaxisSessionRequest {
+  UUID institutionId();
+
   Instant dateAndTime();
 
   String groupName();
@@ -17,4 +21,8 @@ public interface ProphylaxisSessionRequest {
   boolean isScreening();
 
   FluoridationVarnishDto fluoridationVarnish();
+
+  List<UUID> dentistIds();
+
+  List<UUID> zfaIds();
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/ScreeningExaminationResultDto.java b/backend/dental/src/main/java/de/eshg/dental/api/ScreeningExaminationResultDto.java
index ea809cc0ab7d3a18f8ad256666e1ced203f91daa..6686a305f5b9964f31a67116f9befda4bd321a2e 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/ScreeningExaminationResultDto.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/ScreeningExaminationResultDto.java
@@ -12,15 +12,19 @@ import java.util.List;
 
 @Schema(name = ScreeningExaminationResultDto.SCHEMA_NAME)
 public record ScreeningExaminationResultDto(
-    @NotNull boolean fluorideVarnishApplied,
+    Boolean fluorideVarnishApplied,
     OralHygieneStatusDto oralHygieneStatus,
     @NotNull @Valid List<ToothDiagnosisDto> toothDiagnoses)
     implements ExaminationResultDto, IsFluorideVarnishApplicable {
 
   static final String SCHEMA_NAME = "ScreeningExaminationResult";
 
+  public ScreeningExaminationResultDto() {
+    this(null, null, List.of());
+  }
+
   public ScreeningExaminationResultDto(
-      boolean fluorideVarnishApplied, OralHygieneStatusDto oralHygieneStatus) {
+      Boolean fluorideVarnishApplied, OralHygieneStatusDto oralHygieneStatus) {
     this(fluorideVarnishApplied, oralHygieneStatus, List.of());
   }
 
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/ToothDto.java b/backend/dental/src/main/java/de/eshg/dental/api/ToothDto.java
index 27b9519479b9b2f5557a0d979e100ab15e87062d..72a8382c95c73b5457f864c1d13f9deda415ef7f 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/ToothDto.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/ToothDto.java
@@ -90,10 +90,6 @@ public enum ToothDto {
   }
 
   public static ToothDto matchingPermanentToothForMilkTooth(ToothDto tooth) {
-    if (!tooth.isMilkTooth()) {
-      return null;
-    }
-
     return switch (tooth) {
       case T51 -> T11;
       case T52 -> T12;
@@ -118,39 +114,40 @@ public enum ToothDto {
       case T83 -> T43;
       case T84 -> T44;
       case T85 -> T45;
-      default -> null;
-    };
-  }
 
-  public static ToothDto matchingMilkToothForPermanentTooth(ToothDto tooth) {
-    if (tooth.isMilkTooth()) {
-      return null;
-    }
-    return switch (tooth) {
-      case T11 -> T51;
-      case T12 -> T52;
-      case T13 -> T53;
-      case T14 -> T54;
-      case T15 -> T55;
-
-      case T21 -> T61;
-      case T22 -> T62;
-      case T23 -> T63;
-      case T24 -> T64;
-      case T25 -> T65;
-
-      case T31 -> T71;
-      case T32 -> T72;
-      case T33 -> T73;
-      case T34 -> T74;
-      case T35 -> T75;
-
-      case T41 -> T81;
-      case T42 -> T82;
-      case T43 -> T83;
-      case T44 -> T84;
-      case T45 -> T85;
-      default -> null;
+      case T11,
+              T12,
+              T13,
+              T14,
+              T15,
+              T16,
+              T17,
+              T18,
+              T21,
+              T22,
+              T23,
+              T24,
+              T25,
+              T26,
+              T27,
+              T28,
+              T31,
+              T32,
+              T33,
+              T34,
+              T35,
+              T36,
+              T37,
+              T38,
+              T41,
+              T42,
+              T43,
+              T44,
+              T45,
+              T46,
+              T47,
+              T48 ->
+          throw new IllegalArgumentException("Unexpected tooth: " + tooth);
     };
   }
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/UpdateProphylaxisSessionParticipantsRequest.java b/backend/dental/src/main/java/de/eshg/dental/api/UpdateProphylaxisSessionParticipantsRequest.java
index 89e2dfb358b26c2b01edc1df791ae4b4b8a8d9f5..8d87485f9ecdc4ab1f8993f04fc4bde41b13ba3c 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/UpdateProphylaxisSessionParticipantsRequest.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/UpdateProphylaxisSessionParticipantsRequest.java
@@ -5,10 +5,9 @@
 
 package de.eshg.dental.api;
 
-import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
 import java.util.List;
 import java.util.UUID;
 
 public record UpdateProphylaxisSessionParticipantsRequest(
-    @NotNull long version, @NotEmpty List<UUID> participants) {}
+    @NotNull long version, @NotNull List<UUID> participants) {}
diff --git a/backend/dental/src/main/java/de/eshg/dental/api/UpdateProphylaxisSessionRequest.java b/backend/dental/src/main/java/de/eshg/dental/api/UpdateProphylaxisSessionRequest.java
index 545791f50d0f14b2d2039375ff02e635087f9992..5c5a0505133bdc4ba0ec49fd36965d42b8d9e95f 100644
--- a/backend/dental/src/main/java/de/eshg/dental/api/UpdateProphylaxisSessionRequest.java
+++ b/backend/dental/src/main/java/de/eshg/dental/api/UpdateProphylaxisSessionRequest.java
@@ -6,19 +6,31 @@
 package de.eshg.dental.api;
 
 import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
 import java.time.Instant;
+import java.util.List;
+import java.util.UUID;
 
 public record UpdateProphylaxisSessionRequest(
     @NotNull long version,
+    @NotNull UUID institutionId,
     @NotNull Instant dateAndTime,
     @NotBlank String groupName,
     @NotNull ProphylaxisTypeDto type,
     @NotNull boolean isScreening,
-    FluoridationVarnishDto fluoridationVarnish)
+    FluoridationVarnishDto fluoridationVarnish,
+    @NotEmpty List<UUID> dentistIds,
+    @NotEmpty List<UUID> zfaIds)
     implements ProphylaxisSessionRequest {
   public UpdateProphylaxisSessionRequest(
-      Long version, Instant dateAndTime, String groupName, ProphylaxisTypeDto type) {
-    this(version, dateAndTime, groupName, type, false, null);
+      Long version,
+      UUID institutionId,
+      Instant dateAndTime,
+      String groupName,
+      ProphylaxisTypeDto type,
+      List<UUID> dentistIds,
+      List<UUID> zfaIds) {
+    this(version, institutionId, dateAndTime, groupName, type, false, null, dentistIds, zfaIds);
   }
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/domain/model/Child.java b/backend/dental/src/main/java/de/eshg/dental/domain/model/Child.java
index a61fd46a9469a9f4077aa9874f6c7daaee1e0ea6..811cd2f3fa8dea062ba7aafe506517ed5afb9c6a 100644
--- a/backend/dental/src/main/java/de/eshg/dental/domain/model/Child.java
+++ b/backend/dental/src/main/java/de/eshg/dental/domain/model/Child.java
@@ -12,6 +12,7 @@ import static de.eshg.lib.common.SensitivityLevel.SENSITIVE;
 import de.cronn.commons.lang.StreamUtil;
 import de.eshg.lib.common.DataSensitivity;
 import de.eshg.lib.procedure.domain.model.Procedure;
+import jakarta.annotation.Nullable;
 import jakarta.persistence.CascadeType;
 import jakarta.persistence.Column;
 import jakarta.persistence.ElementCollection;
@@ -109,15 +110,22 @@ public class Child extends Procedure<Child, ChildTask, Person, Facility> {
     return fluoridationConsents;
   }
 
-  public Boolean getCurrentFluoridationConsent() {
+  public FluoridationConsent getCurrentFluoridationConsent() {
     return fluoridationConsents.stream()
-        .max(Comparator.comparing(FluoridationConsent::dateOfConsent))
-        .map(FluoridationConsent::consented)
+        .max(Comparator.comparing(FluoridationConsent::getModifiedAt))
         .orElse(null);
   }
 
+  @Nullable
+  public Boolean isFluoridationConsentCurrentlyGivenOptionally() {
+    if (getCurrentFluoridationConsent() == null) {
+      return null;
+    }
+    return getCurrentFluoridationConsent().isConsented();
+  }
+
   public boolean isFluoridationConsentCurrentlyGiven() {
-    return BooleanUtils.isTrue(getCurrentFluoridationConsent());
+    return BooleanUtils.isTrue(isFluoridationConsentCurrentlyGivenOptionally());
   }
 
   public void addFluoridationConsent(FluoridationConsent fluoridationConsent) {
diff --git a/backend/dental/src/main/java/de/eshg/dental/domain/model/Examination.java b/backend/dental/src/main/java/de/eshg/dental/domain/model/Examination.java
index 5b5d0960c19fd533bccc9127254479cdcd8da795..9964dd80474847d0570204f4aae4414ea6e1f0ff 100644
--- a/backend/dental/src/main/java/de/eshg/dental/domain/model/Examination.java
+++ b/backend/dental/src/main/java/de/eshg/dental/domain/model/Examination.java
@@ -84,6 +84,10 @@ public class Examination extends BaseEntityWithExternalId {
     this.result = result;
   }
 
+  public boolean hasResult() {
+    return result != null;
+  }
+
   public Instant getDateAndTime() {
     return getProphylaxisSession().getDateAndTime();
   }
diff --git a/backend/dental/src/main/java/de/eshg/dental/domain/model/ExaminationResult.java b/backend/dental/src/main/java/de/eshg/dental/domain/model/ExaminationResult.java
index 6b0aff7be7473534528aaeb726cb86071bcd50fc..8c0dfb8c82eac971b0a18112abedeabcc2dd0699 100644
--- a/backend/dental/src/main/java/de/eshg/dental/domain/model/ExaminationResult.java
+++ b/backend/dental/src/main/java/de/eshg/dental/domain/model/ExaminationResult.java
@@ -5,7 +5,7 @@
 
 package de.eshg.dental.domain.model;
 
-import de.eshg.domain.model.BaseEntity;
+import de.eshg.domain.model.SequencedBaseEntity;
 import de.eshg.lib.common.DataSensitivity;
 import de.eshg.lib.common.SensitivityLevel;
 import jakarta.persistence.DiscriminatorColumn;
@@ -19,7 +19,7 @@ import jakarta.persistence.OneToOne;
 @Inheritance(strategy = InheritanceType.JOINED)
 @DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
 @DataSensitivity(SensitivityLevel.SENSITIVE)
-public abstract class ExaminationResult extends BaseEntity {
+public abstract class ExaminationResult extends SequencedBaseEntity {
 
   @OneToOne(optional = false, mappedBy = Examination_.RESULT)
   private Examination examination;
diff --git a/backend/dental/src/main/java/de/eshg/dental/domain/model/FluoridationConsent.java b/backend/dental/src/main/java/de/eshg/dental/domain/model/FluoridationConsent.java
index ec5cc09c93ad1b9f558d821bc6fc90b22fccd48b..3179757aeedc6c66e1ef674653b97d2e5baa9e7e 100644
--- a/backend/dental/src/main/java/de/eshg/dental/domain/model/FluoridationConsent.java
+++ b/backend/dental/src/main/java/de/eshg/dental/domain/model/FluoridationConsent.java
@@ -9,11 +9,54 @@ import de.eshg.lib.common.DataSensitivity;
 import de.eshg.lib.common.SensitivityLevel;
 import jakarta.persistence.Column;
 import jakarta.persistence.Embeddable;
+import java.time.Instant;
 import java.time.LocalDate;
+import org.springframework.data.annotation.LastModifiedDate;
 
 @Embeddable
 @DataSensitivity(SensitivityLevel.SENSITIVE)
-public record FluoridationConsent(
-    @Column(nullable = false) LocalDate dateOfConsent,
-    @Column(nullable = false) boolean consented,
-    Boolean hasAllergy) {}
+public class FluoridationConsent {
+  @LastModifiedDate
+  @Column(nullable = false)
+  private Instant modifiedAt;
+
+  @Column(nullable = false)
+  private LocalDate dateOfConsent;
+
+  @Column(nullable = false)
+  private boolean consented;
+
+  private Boolean hasAllergy;
+
+  public LocalDate getDateOfConsent() {
+    return dateOfConsent;
+  }
+
+  public void setDateOfConsent(LocalDate dateOfConsent) {
+    this.dateOfConsent = dateOfConsent;
+  }
+
+  public boolean isConsented() {
+    return consented;
+  }
+
+  public void setConsented(boolean consented) {
+    this.consented = consented;
+  }
+
+  public Boolean hasAllergy() {
+    return hasAllergy;
+  }
+
+  public void setHasAllergy(Boolean hasAllergy) {
+    this.hasAllergy = hasAllergy;
+  }
+
+  public Instant getModifiedAt() {
+    return modifiedAt;
+  }
+
+  public void setModifiedAt(Instant modifiedAt) {
+    this.modifiedAt = modifiedAt;
+  }
+}
diff --git a/backend/dental/src/main/java/de/eshg/dental/domain/model/FluoridationExaminationResult.java b/backend/dental/src/main/java/de/eshg/dental/domain/model/FluoridationExaminationResult.java
index b539cedc780a75c2db29301760618807d5099080..1a80050fc591083a36a42f962841cfda324027c9 100644
--- a/backend/dental/src/main/java/de/eshg/dental/domain/model/FluoridationExaminationResult.java
+++ b/backend/dental/src/main/java/de/eshg/dental/domain/model/FluoridationExaminationResult.java
@@ -15,13 +15,13 @@ import jakarta.persistence.Entity;
 @DiscriminatorValue("FLUORIDATION")
 public class FluoridationExaminationResult extends ExaminationResult {
 
-  private boolean fluorideVarnishApplied;
+  private Boolean fluorideVarnishApplied;
 
-  public boolean isFluorideVarnishApplied() {
+  public Boolean isFluorideVarnishApplied() {
     return fluorideVarnishApplied;
   }
 
-  public void setFluorideVarnishApplied(boolean fluorideVarnishApplied) {
+  public void setFluorideVarnishApplied(Boolean fluorideVarnishApplied) {
     this.fluorideVarnishApplied = fluorideVarnishApplied;
   }
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/domain/model/ScreeningExaminationResult.java b/backend/dental/src/main/java/de/eshg/dental/domain/model/ScreeningExaminationResult.java
index e696b672303c79c939721711dfbc207ff734b20f..517288a96f1b3306d60fef120f420bb302dbf52b 100644
--- a/backend/dental/src/main/java/de/eshg/dental/domain/model/ScreeningExaminationResult.java
+++ b/backend/dental/src/main/java/de/eshg/dental/domain/model/ScreeningExaminationResult.java
@@ -23,7 +23,7 @@ import org.hibernate.dialect.PostgreSQLEnumJdbcType;
 @DiscriminatorValue("SCREENING")
 public class ScreeningExaminationResult extends ExaminationResult {
 
-  private boolean fluorideVarnishApplied;
+  private Boolean fluorideVarnishApplied;
 
   @JdbcType(PostgreSQLEnumJdbcType.class)
   private OralHygieneStatus oralHygieneStatus;
@@ -51,11 +51,11 @@ public class ScreeningExaminationResult extends ExaminationResult {
     this.toothDiagnoses = toothDiagnoses;
   }
 
-  public boolean isFluorideVarnishApplied() {
+  public Boolean isFluorideVarnishApplied() {
     return fluorideVarnishApplied;
   }
 
-  public void setFluorideVarnishApplied(boolean fluorideVarnishApplied) {
+  public void setFluorideVarnishApplied(Boolean fluorideVarnishApplied) {
     this.fluorideVarnishApplied = fluorideVarnishApplied;
   }
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/domain/repository/ExaminationRepository.java b/backend/dental/src/main/java/de/eshg/dental/domain/repository/ExaminationRepository.java
index 50de86b5d79f9977f723b331d4460ab75f235ce9..1e8d310aa248d0b62d0ec76969289ec688a669a5 100644
--- a/backend/dental/src/main/java/de/eshg/dental/domain/repository/ExaminationRepository.java
+++ b/backend/dental/src/main/java/de/eshg/dental/domain/repository/ExaminationRepository.java
@@ -6,11 +6,13 @@
 package de.eshg.dental.domain.repository;
 
 import de.eshg.dental.domain.model.Examination;
+import de.eshg.lib.procedure.domain.model.PersonType;
 import de.eshg.lib.procedure.domain.model.ProcedureStatus;
 import jakarta.persistence.LockModeType;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
+import java.util.stream.Stream;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Lock;
@@ -25,30 +27,38 @@ public interface ExaminationRepository
   Optional<Examination> findOneByExternalIdForUpdate(@Param("examinationId") UUID examinationId);
 
   @Lock(LockModeType.PESSIMISTIC_WRITE)
-  @Query("select e from Examination e where e.externalId in :examinationIds order by e.id")
-  List<Examination> findAllByExternalIdsForUpdate(
-      @Param("examinationIds") List<UUID> examinationIds);
+  @Query("select e.id from Examination e where e.externalId in :examinationIds order by e.id")
+  List<Long> findAllByExternalIdsForUpdate(@Param("examinationIds") List<UUID> examinationIds);
+
+  @Query(
+      """
+    select e from Examination e
+    join fetch e.child
+    join fetch e.prophylaxisSession
+    left join fetch e.result
+    where e.id in :ids
+    order by e.id""")
+  Stream<Examination> fetchByIds(@Param("ids") List<Long> ids);
 
   @Query(
       """
     select e from Examination e
     where e.child.procedureStatus = :status
+    and e.result is null
     order by e.id""")
-  List<Examination> findAllByChildStatus(@Param("status") ProcedureStatus status);
+  List<Examination> findAllByChildStatusWhereResultIsNull(@Param("status") ProcedureStatus status);
 
   Optional<Examination> findByExternalId(UUID examinationId);
 
   @Query(
-      nativeQuery = true,
-      value =
-          """
-    select e.*
-    from examination e
-      join child c on c.id = e.child_id
-      join person pers on pers.procedure_id = c.id
-      join prophylaxis_session sess on sess.id = e.prophylaxis_session_id
-    where pers.central_file_state_id in :fileStateIds
-    order by sess.date_and_time desc, e.id;
-    """)
-  List<Examination> findAllByChildFileStateIds(List<UUID> fileStateIds);
+      """
+    select e from Examination e
+    join fetch e.child
+    join fetch e.prophylaxisSession
+    left join fetch e.result
+    join e.child.relatedPersons rp on rp.personType = :personType
+    where rp.centralFileStateId in :fileStateIds
+    order by e.prophylaxisSession.dateAndTime desc, e.id""")
+  Stream<Examination> findAllByPersonFileStateIds(
+      @Param("personType") PersonType personType, @Param("fileStateIds") List<UUID> fileStateIds);
 }
diff --git a/backend/dental/src/main/java/de/eshg/dental/importer/ChildRowReader.java b/backend/dental/src/main/java/de/eshg/dental/importer/ChildRowReader.java
index d89eb2a9f6b6e6d42eb5fc44c15db3f0f83d6eba..e7f23b18717f4f2aa8dbb4c75946ea6be01d1efa 100644
--- a/backend/dental/src/main/java/de/eshg/dental/importer/ChildRowReader.java
+++ b/backend/dental/src/main/java/de/eshg/dental/importer/ChildRowReader.java
@@ -17,13 +17,14 @@ import de.eshg.dental.business.model.ImportChildData;
 import de.eshg.lib.xlsximport.ColumnAccessor;
 import de.eshg.lib.xlsximport.ErrorHandler;
 import de.eshg.lib.xlsximport.RowReader;
+import java.time.Clock;
 import java.util.List;
 import org.apache.poi.ss.usermodel.Sheet;
 
 public class ChildRowReader extends RowReader<ChildRow, ChildColumn> {
 
-  public ChildRowReader(Sheet sheet, List<ChildColumn> actualColumns) {
-    super(sheet, actualColumns, ChildRow::new);
+  public ChildRowReader(Sheet sheet, Clock clock, List<ChildColumn> actualColumns) {
+    super(sheet, actualColumns, ChildRow::new, clock);
   }
 
   @Override
@@ -40,7 +41,7 @@ public class ChildRowReader extends RowReader<ChildRow, ChildColumn> {
     return new ImportChildData(
         cellAsString(col, LAST_NAME, errorHandler),
         cellAsString(col, FIRST_NAME, errorHandler),
-        cellAsDate(col, DATE_OF_BIRTH, errorHandler),
+        cellAsDateOfBirth(col, DATE_OF_BIRTH, errorHandler),
         cellAsGender(col, GENDER, errorHandler),
         cellAsString(col, GROUP, errorHandler));
   }
diff --git a/backend/dental/src/main/java/de/eshg/dental/mapper/ChildMapper.java b/backend/dental/src/main/java/de/eshg/dental/mapper/ChildMapper.java
index 2abb8c8ca23a4811fe45a6f64c84f8b726dd21b5..042354cad6bd2e98f36ba2ba2b69f7b64ca226b0 100644
--- a/backend/dental/src/main/java/de/eshg/dental/mapper/ChildMapper.java
+++ b/backend/dental/src/main/java/de/eshg/dental/mapper/ChildMapper.java
@@ -92,19 +92,20 @@ public final class ChildMapper {
       return new ArrayList<>();
     }
     return fluoridationConsent.stream()
-        .map(f -> new FluoridationConsentDto(f.dateOfConsent(), f.consented(), f.hasAllergy()))
+        .map(f -> new FluoridationConsentDto(f.getDateOfConsent(), f.isConsented(), f.hasAllergy()))
         .toList();
   }
 
-  public static FluoridationConsent mapFluoridationToDomain(
-      FluoridationConsentDto fluoridationConsent) {
-    if (fluoridationConsent == null) {
+  public static FluoridationConsent mapFluoridationToDomain(FluoridationConsentDto dto) {
+    if (dto == null) {
       return null;
     }
-    return new FluoridationConsent(
-        fluoridationConsent.dateOfConsent(),
-        fluoridationConsent.consented(),
-        fluoridationConsent.hasAllergy());
+
+    FluoridationConsent fluoridationConsent = new FluoridationConsent();
+    fluoridationConsent.setDateOfConsent(dto.dateOfConsent());
+    fluoridationConsent.setConsented(dto.consented());
+    fluoridationConsent.setHasAllergy(dto.hasAllergy());
+    return fluoridationConsent;
   }
 
   public static CreateChildRequest mapImportDataToCreateChildRequest(
diff --git a/backend/dental/src/main/java/de/eshg/dental/mapper/ExaminationMapper.java b/backend/dental/src/main/java/de/eshg/dental/mapper/ExaminationMapper.java
index f6add52339a8eb40e0992d1a9052ce5f2c9d19be..375938c00b5182c427cc50d0a25391990cecaf84 100644
--- a/backend/dental/src/main/java/de/eshg/dental/mapper/ExaminationMapper.java
+++ b/backend/dental/src/main/java/de/eshg/dental/mapper/ExaminationMapper.java
@@ -47,7 +47,7 @@ public final class ExaminationMapper {
         ProphylaxisSessionMapper.mapToDto(prophylaxisSession.getType()),
         prophylaxisSession.isScreening(),
         prophylaxisSession.hasFluoridationVarnish(),
-        examination.getChild().isFluoridationConsentCurrentlyGiven(),
+        examination.getChild().isFluoridationConsentCurrentlyGivenOptionally(),
         examination.getNote(),
         mapToDto(examination.getResult()));
   }
diff --git a/backend/dental/src/main/java/de/eshg/dental/mapper/ProphylaxisSessionMapper.java b/backend/dental/src/main/java/de/eshg/dental/mapper/ProphylaxisSessionMapper.java
index 9e541b11283e44d08ed421b34601f9f82ec7868f..cd940595d6f90285b7c26a3922d6676c6b63891a 100644
--- a/backend/dental/src/main/java/de/eshg/dental/mapper/ProphylaxisSessionMapper.java
+++ b/backend/dental/src/main/java/de/eshg/dental/mapper/ProphylaxisSessionMapper.java
@@ -127,7 +127,7 @@ public final class ProphylaxisSessionMapper {
         examination.getChild().getGroupName().trim(),
         fileStateResponse.gender(),
         examination.getNote(),
-        examination.getChild().getCurrentFluoridationConsent(),
+        examination.getChild().isFluoridationConsentCurrentlyGivenOptionally(),
         ExaminationMapper.mapToDto(examination.getResult()),
         previousExaminations.stream()
             .map(Examination::getResult)
@@ -143,8 +143,8 @@ public final class ProphylaxisSessionMapper {
             userId ->
                 Optional.ofNullable(userMap.get(userId))
                     .<PerformingPersonDto>map(
-                        user -> new ExistingUserDto(user.firstName(), user.lastName()))
-                    .orElse(new NonExistingUserDto()))
+                        user -> new ExistingUserDto(userId, user.firstName(), user.lastName()))
+                    .orElse(new NonExistingUserDto(userId)))
         .toList();
   }
 
diff --git a/backend/dental/src/main/java/de/eshg/dental/testhelper/ChildrenPopulator.java b/backend/dental/src/main/java/de/eshg/dental/testhelper/ChildrenPopulator.java
index 1ca6b92832bcce495bffcc2da568e269ef3c0b90..416f0cc22718f0c0f9021a6abaf48d8dcd8b2b6d 100644
--- a/backend/dental/src/main/java/de/eshg/dental/testhelper/ChildrenPopulator.java
+++ b/backend/dental/src/main/java/de/eshg/dental/testhelper/ChildrenPopulator.java
@@ -77,16 +77,16 @@ public class ChildrenPopulator extends DentalPopulator<CreateChildResponse> {
       Year yearInPast = Year.of(request.year() - i);
       CreateChildRequest requestForPast = withNewYear(request, yearInPast);
       UUID childId = childController.createChild(requestForPast).id();
-      updateChild(childId, faker, i);
+      updateChild(childId, faker);
     }
 
     CreateChildResponse child = childController.createChild(request);
-    updateChild(child.id(), faker, numberOfPastYears);
+    updateChild(child.id(), faker);
 
     return child;
   }
 
-  private void updateChild(UUID childId, Faker faker, int numberOfPastYears) {
+  private void updateChild(UUID childId, Faker faker) {
     ChildDetailsDto childDetails = childController.getChild(childId);
     childController.updateChild(
         childId,
diff --git a/backend/dental/src/main/java/de/eshg/dental/testhelper/ProphylaxisSessionsPopulator.java b/backend/dental/src/main/java/de/eshg/dental/testhelper/ProphylaxisSessionsPopulator.java
index 0bff92c209aa824ed7bf38965099952b5fd083a3..32c187ce4da15dfbd3c988b002e0df6664f66530 100644
--- a/backend/dental/src/main/java/de/eshg/dental/testhelper/ProphylaxisSessionsPopulator.java
+++ b/backend/dental/src/main/java/de/eshg/dental/testhelper/ProphylaxisSessionsPopulator.java
@@ -166,7 +166,9 @@ public class ProphylaxisSessionsPopulator
 
   private void randomExaminations(Faker faker) {
     List<Examination> someExaminations =
-        randomElements(faker, examinationRepository.findAllByChildStatus(ProcedureStatus.OPEN));
+        randomElements(
+            faker,
+            examinationRepository.findAllByChildStatusWhereResultIsNull(ProcedureStatus.OPEN));
 
     for (Examination examination : someExaminations) {
       UpdateExaminationRequest request =
@@ -180,21 +182,28 @@ public class ProphylaxisSessionsPopulator
 
   private static ExaminationResultDto randomResult(Faker faker, Examination examination) {
     ProphylaxisSession prophylaxisSession = examination.getProphylaxisSession();
+    boolean isScreening = prophylaxisSession.isScreening();
     boolean hasFluoridationVarnish = prophylaxisSession.hasFluoridationVarnish();
+
+    if (isScreening || hasFluoridationVarnish) {
+      if (faker.random().nextDouble() < 0.1) {
+        return new AbsenceExaminationResultDto(randomElement(faker, ReasonForAbsenceDto.values()));
+      }
+    }
+
     boolean isFluoridationConsentGiven =
         examination.getChild().isFluoridationConsentCurrentlyGiven();
-    if (prophylaxisSession.isScreening()) {
+
+    if (isScreening) {
       return new ScreeningExaminationResultDto(
-          hasFluoridationVarnish && isFluoridationConsentGiven && faker.bool().bool(),
+          optional(
+              faker, hasFluoridationVarnish && isFluoridationConsentGiven && faker.bool().bool()),
           optional(faker, randomElement(faker, OralHygieneStatusDto.values())),
           randomToothDiagnoses(faker));
     } else if (hasFluoridationVarnish) {
       return new FluoridationExaminationResultDto(
-          isFluoridationConsentGiven && faker.bool().bool());
+          optional(faker, isFluoridationConsentGiven && faker.bool().bool()));
     } else {
-      if (faker.random().nextDouble() <= 0.5) {
-        return new AbsenceExaminationResultDto(randomElement(faker, ReasonForAbsenceDto.values()));
-      }
       return null;
     }
   }
diff --git a/backend/dental/src/main/resources/migrations/0029_add_auditlog_entry.xml b/backend/dental/src/main/resources/migrations/0029_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ebb946b32565da731dd06d7f947f2ed09deef45b
--- /dev/null
+++ b/backend/dental/src/main/resources/migrations/0029_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: Apache-2.0
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/dental/src/main/resources/migrations/0030_add_modified_at_fluoridation.xml b/backend/dental/src/main/resources/migrations/0030_add_modified_at_fluoridation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..46319f5c8435369d00d62d0da6740b1cb791351a
--- /dev/null
+++ b/backend/dental/src/main/resources/migrations/0030_add_modified_at_fluoridation.xml
@@ -0,0 +1,19 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: Apache-2.0
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1738056540772-1">
+    <addColumn tableName="child_fluoridation_consents">
+      <column name="modified_at" type="TIMESTAMP WITH TIME ZONE"
+              valueComputed="now()">
+        <constraints nullable="false"/>
+      </column>
+    </addColumn>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/dental/src/main/resources/migrations/0031_fluoride_varnish_applied_optional.xml b/backend/dental/src/main/resources/migrations/0031_fluoride_varnish_applied_optional.xml
new file mode 100644
index 0000000000000000000000000000000000000000..26fb42da4140ef931a75fe9a3a8274bcff283077
--- /dev/null
+++ b/backend/dental/src/main/resources/migrations/0031_fluoride_varnish_applied_optional.xml
@@ -0,0 +1,12 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: Apache-2.0
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1738304707114-1">
+    <dropNotNullConstraint columnDataType="boolean" columnName="fluoride_varnish_applied" tableName="fluoridation_examination_result"/>
+    <dropNotNullConstraint columnDataType="boolean" columnName="fluoride_varnish_applied" tableName="screening_examination_result"/>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/dental/src/main/resources/migrations/0032_migrate_examination_result_to_use_sequences.xml b/backend/dental/src/main/resources/migrations/0032_migrate_examination_result_to_use_sequences.xml
new file mode 100644
index 0000000000000000000000000000000000000000..341792d7da567100b450e16d0897479c3f18d920
--- /dev/null
+++ b/backend/dental/src/main/resources/migrations/0032_migrate_examination_result_to_use_sequences.xml
@@ -0,0 +1,11 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: Apache-2.0
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="migrate_examination_result_to_use_sequence">
+    <ext:migrateAutoIncrementToSequence tableName="examination_result"/>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/dental/src/main/resources/migrations/changelog.xml b/backend/dental/src/main/resources/migrations/changelog.xml
index 1a81ab2eef386d60e05a22fe84855a0d740ab5c2..f8a472d321b9e423bae683ad0d2dac4fd695db07 100644
--- a/backend/dental/src/main/resources/migrations/changelog.xml
+++ b/backend/dental/src/main/resources/migrations/changelog.xml
@@ -36,5 +36,9 @@
   <include file="migrations/0026_add_tooth_diagnoses.xml"/>
   <include file="migrations/0027_add_absence_examination_result.xml"/>
   <include file="migrations/0028_rename_screening.xml"/>
+  <include file="migrations/0029_add_auditlog_entry.xml"/>
+  <include file="migrations/0030_add_modified_at_fluoridation.xml"/>
+  <include file="migrations/0031_fluoride_varnish_applied_optional.xml"/>
+  <include file="migrations/0032_migrate_examination_result_to_use_sequences.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/docker-compose.yaml b/backend/docker-compose.yaml
index 03507540d4ad4cd8f094c76ca02034d041f3572f..699a8b13117d71447d66fa5b7884fa186635440b 100644
--- a/backend/docker-compose.yaml
+++ b/backend/docker-compose.yaml
@@ -572,6 +572,8 @@ services:
       - de.eshg.base.service-url=http://base:8080
       - eshg.keycloak.internal.url=http://keycloak:8080
       - de.eshg.auditlog.service-url=http://auditlog:8080
+      - de.eshg.official-medical-service.notification.fromAddress=tba@stadt-frankfurt.de
+      - de.eshg.official-medical-service.notification.greeting=Ihr TBA-Team der Stadt Frankfurt
     depends_on:
       official-medical-service-db:
         condition: service_healthy
diff --git a/backend/file-commons/gradle.lockfile b/backend/file-commons/gradle.lockfile
index ddb42dbb6cfbb355fe2a44863828434ea52bb4a7..8d6033aab308517228df33b1067740d89a4602ad 100644
--- a/backend/file-commons/gradle.lockfile
+++ b/backend/file-commons/gradle.lockfile
@@ -35,8 +35,8 @@ de.cronn:test-utils:1.1.1=testCompileClasspath,testRuntimeClasspath
 de.cronn:validation-file-assertions:0.8.0=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -68,10 +68,10 @@ org.glassfish.jaxb:jaxb-runtime:4.0.5=compileClasspath,productionRuntimeClasspat
 org.glassfish.jaxb:txw2:4.0.5=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest-core:2.2=testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jetbrains:annotations:17.0.0=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
@@ -86,9 +86,10 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.mozilla:rhino:1.7.13=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/gradle.lockfile b/backend/gradle.lockfile
index 1f2f8de2978c8cffa4de7da808131fc39271bd58..a3802b6798ca5bcc9e5140e0696fe09efad22ec1 100644
--- a/backend/gradle.lockfile
+++ b/backend/gradle.lockfile
@@ -1,11 +1,11 @@
 # This is a Gradle generated file for dependency locking.
 # Manual edits can break the build and are not advised.
 # This file is expected to be part of source control.
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.7=jacocoAnt
 empty=aggregateCodeCoverageReportResults
diff --git a/backend/gradle/wrapper/gradle-wrapper.jar b/backend/gradle/wrapper/gradle-wrapper.jar
index 2c3521197d7c4586c843d1d3e9090525f1898cde..a4b76b9530d66f5e68d973ea569d8e19de379189 100644
Binary files a/backend/gradle/wrapper/gradle-wrapper.jar and b/backend/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/backend/gradle/wrapper/gradle-wrapper.properties b/backend/gradle/wrapper/gradle-wrapper.properties
index dedd5d1e69e694f9dc7b13edab8c7f2e9c377e45..d9fbee2e1d61a32b9c35e11fd9a851dd3639dda0 100644
--- a/backend/gradle/wrapper/gradle-wrapper.properties
+++ b/backend/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-all.zip
 networkTimeout=10000
 validateDistributionUrl=true
 zipStoreBase=GRADLE_USER_HOME
diff --git a/backend/gradlew b/backend/gradlew
index f5feea6d6b116baaca5a2642d4d9fa1f47d574a7..f3b75f3b0d4faeb4b1c8a02b5c47007e6efb7dcd 100755
--- a/backend/gradlew
+++ b/backend/gradlew
@@ -86,8 +86,7 @@ done
 # shellcheck disable=SC2034
 APP_BASE_NAME=${0##*/}
 # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
-' "$PWD" ) || exit
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD=maximum
diff --git a/backend/gradlew.bat b/backend/gradlew.bat
index 9d21a21834d5195c278ba17baec3115b2aaab06e..9b42019c7915b971238526075306ffba3b666dd5 100644
Binary files a/backend/gradlew.bat and b/backend/gradlew.bat differ
diff --git a/backend/inspection/build.gradle b/backend/inspection/build.gradle
index da4de001f7a6665bbe6c368f3aad95ea555ef889..3101df0cd8cfa715a7f1d46909c4b4f7e68d3267 100644
--- a/backend/inspection/build.gradle
+++ b/backend/inspection/build.gradle
@@ -36,6 +36,7 @@ dependencies {
     testImplementation testFixtures(project(':lib-document-generator'))
     testImplementation testFixtures(project(':lib-xlsx-import'))
     testImplementation testFixtures(project(':lib-statistics'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 }
 
 dockerCompose {
diff --git a/backend/inspection/gradle.lockfile b/backend/inspection/gradle.lockfile
index 061d1161ca5ac5a72bfe689a1da7ffa4d2514a73..548afc417b729da751efecaedc84eb9df17a6214 100644
--- a/backend/inspection/gradle.lockfile
+++ b/backend/inspection/gradle.lockfile
@@ -114,10 +114,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -213,10 +213,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -236,16 +236,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/inspection/openApi.json b/backend/inspection/openApi.json
index 75e26b9b8d931db047b6a0243f6e2e99cd98d8b3..1d42add9facbd28723b88c031787f5401ee9ff01 100644
--- a/backend/inspection/openApi.json
+++ b/backend/inspection/openApi.json
@@ -4686,18 +4686,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
-        "responses" : {
-          "200" : {
-            "description" : "OK"
-          }
-        },
-        "tags" : [ "TestHelper" ]
-      }
-    },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
diff --git a/backend/inspection/src/main/java/de/eshg/inspection/importer/InspectionProcedureRowReader.java b/backend/inspection/src/main/java/de/eshg/inspection/importer/InspectionProcedureRowReader.java
index 3b31911a6df9089981df06ffb9044a2403bda3a8..cc2b45c0374d8d7b8b0c61530c0f6a2d1f0366ed 100644
--- a/backend/inspection/src/main/java/de/eshg/inspection/importer/InspectionProcedureRowReader.java
+++ b/backend/inspection/src/main/java/de/eshg/inspection/importer/InspectionProcedureRowReader.java
@@ -57,7 +57,7 @@ class InspectionProcedureRowReader extends RowReader<InspectionImporterRow, Insp
       List<InspectionListColumn> actualColumns,
       ImportPersister importPersister,
       Clock clock) {
-    super(sheet, actualColumns, InspectionImporterRow::new);
+    super(sheet, actualColumns, InspectionImporterRow::new, clock);
     this.importPersister = importPersister;
     this.clock = clock;
   }
@@ -120,7 +120,7 @@ class InspectionProcedureRowReader extends RowReader<InspectionImporterRow, Insp
     String firstName = cellAsString(col, CONTACT_FIRSTNAME, true, false, errorHandler);
     String lastName = cellAsString(col, CONTACT_LASTNAME, true, false, errorHandler);
     String email = cellAsString(col, CONTACT_EMAIL, true, false, errorHandler);
-    String phonenumber = cellAsString(col, CONTACT_PHONENUMBER, true, false, errorHandler);
+    String phonenumber = cellAsString(col, CONTACT_PHONENUMBER, true, true, errorHandler);
 
     // If every contact field is empty then don't create a contact
     if (salutation == null
diff --git a/backend/inspection/src/main/java/de/eshg/inspection/testhelper/InspectionTestHelperController.java b/backend/inspection/src/main/java/de/eshg/inspection/testhelper/InspectionTestHelperController.java
index 0fe6f8ba0f5d7fc24dcc23c09bc324f1a70095bd..476c2be8837c87d26350ef290a73fe3510db24d4 100644
--- a/backend/inspection/src/main/java/de/eshg/inspection/testhelper/InspectionTestHelperController.java
+++ b/backend/inspection/src/main/java/de/eshg/inspection/testhelper/InspectionTestHelperController.java
@@ -5,7 +5,7 @@
 
 package de.eshg.inspection.testhelper;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.inspection.checklist.persistence.ChecklistRepository;
 import de.eshg.inspection.feature.InspectionFeature;
 import de.eshg.inspection.feature.InspectionFeatureToggle;
@@ -13,7 +13,6 @@ import de.eshg.lib.auditlog.AuditLogTestHelperService;
 import de.eshg.testhelper.ConditionalOnTestHelperEnabled;
 import de.eshg.testhelper.TestHelperController;
 import de.eshg.testhelper.environment.EnvironmentConfig;
-import java.io.IOException;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RestController;
@@ -23,7 +22,7 @@ import org.springframework.web.service.annotation.PostExchange;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class InspectionTestHelperController extends TestHelperController
-    implements SharedAuditLogTestHelperApi {
+    implements AuditLogClientTestHelperApi {
 
   private final AuditLogTestHelperService auditLogTestHelperService;
   private final InspectionFeatureToggle inspectionFeatureToggle;
@@ -42,13 +41,8 @@ public class InspectionTestHelperController extends TestHelperController
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
-  }
-
-  @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 
   @PostExchange("/enabled-new-features/{featureToEnable}")
diff --git a/backend/inspection/src/main/resources/migrations/0064_add_auditlog_entry.xml b/backend/inspection/src/main/resources/migrations/0064_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..123233c564a61e3312bf33ae50680e5b2f8c2c7c
--- /dev/null
+++ b/backend/inspection/src/main/resources/migrations/0064_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 SCOOP Software GmbH, cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/inspection/src/main/resources/migrations/changelog.xml b/backend/inspection/src/main/resources/migrations/changelog.xml
index 6c3a85a96736daf895da9e67e1421c3ec8fe9aef..0a5a6f7af7a979da56a5c54da7661cc5d253cfb3 100644
--- a/backend/inspection/src/main/resources/migrations/changelog.xml
+++ b/backend/inspection/src/main/resources/migrations/changelog.xml
@@ -77,5 +77,6 @@
   <include file="migrations/0061_add_oms_task_type.xml"/>
   <include file="migrations/0062_add_cemetery_delete_at.xml"/>
   <include file="migrations/0063_add_previous_file_state_id_to_system_progress_entry.xml"/>
+  <include file="migrations/0064_add_auditlog_entry.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/keycloak-api/gradle.lockfile b/backend/keycloak-api/gradle.lockfile
index f4c5880ce8d7b7266007b97dde613aa4744c6aad..c46c7009b44be1e9e1489ee7d2a2f2b2b895c9f4 100644
--- a/backend/keycloak-api/gradle.lockfile
+++ b/backend/keycloak-api/gradle.lockfile
@@ -11,8 +11,8 @@ com.sun.istack:istack-commons-runtime:4.1.2=compileClasspath,productionRuntimeCl
 com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.swagger:swagger-annotations:1.6.15=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -40,10 +40,10 @@ org.glassfish.jaxb:jaxb-core:4.0.5=compileClasspath,productionRuntimeClasspath,r
 org.glassfish.jaxb:jaxb-runtime:4.0.5=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.glassfish.jaxb:txw2:4.0.5=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -56,9 +56,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/keycloak/gradle.lockfile b/backend/keycloak/gradle.lockfile
index 8ae82fcd0f39e89f0062284521239a13c935ed30..d0d7f06ccf1943f822651c1e395e0d85f167f25a 100644
--- a/backend/keycloak/gradle.lockfile
+++ b/backend/keycloak/gradle.lockfile
@@ -75,8 +75,8 @@ io.opentelemetry:opentelemetry-sdk-metrics:1.43.0=compileClasspath
 io.opentelemetry:opentelemetry-sdk-trace:1.43.0=compileClasspath
 io.opentelemetry:opentelemetry-sdk:1.43.0=compileClasspath
 io.quarkus.arc:arc:3.15.1=compileClasspath
-io.quarkus.resteasy.reactive:resteasy-reactive-common-types:3.17.7=compileClasspath
-io.quarkus.resteasy.reactive:resteasy-reactive-common:3.17.7=compileClasspath
+io.quarkus.resteasy.reactive:resteasy-reactive-common-types:3.18.0=compileClasspath
+io.quarkus.resteasy.reactive:resteasy-reactive-common:3.18.0=compileClasspath
 io.quarkus.security:quarkus-security:2.1.0=compileClasspath
 io.quarkus:quarkus-arc:3.15.1=compileClasspath
 io.quarkus:quarkus-bootstrap-runner:3.15.1=compileClasspath
@@ -114,7 +114,7 @@ io.smallrye.config:smallrye-config-core:3.9.1=compileClasspath
 io.smallrye.config:smallrye-config:3.9.1=compileClasspath
 io.smallrye.reactive:mutiny-smallrye-context-propagation:2.6.2=compileClasspath
 io.smallrye.reactive:mutiny-zero-flow-adapters:1.1.0=compileClasspath
-io.smallrye.reactive:mutiny:2.6.2=compileClasspath
+io.smallrye.reactive:mutiny:2.7.0=compileClasspath
 io.smallrye.reactive:smallrye-mutiny-vertx-core:3.15.0=compileClasspath
 io.smallrye.reactive:smallrye-mutiny-vertx-runtime:3.15.0=compileClasspath
 io.smallrye.reactive:vertx-mutiny-generator:3.15.0=compileClasspath
@@ -165,10 +165,10 @@ org.infinispan.protostream:protostream-processor:5.0.10.Final=compileClasspath
 org.infinispan.protostream:protostream-types:5.0.10.Final=compileClasspath
 org.infinispan.protostream:protostream:5.0.10.Final=compileClasspath
 org.infinispan:infinispan-commons:15.0.11.Final=compileClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging-annotations:3.0.1.Final=compileClasspath
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath
 org.jboss.logmanager:jboss-logmanager:3.0.6.Final=compileClasspath
@@ -195,9 +195,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.reactivestreams:reactive-streams:1.0.4=compileClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/keycloak/resources/themes/custom-keycloak/login/date-of-birth-access-code.ftl b/backend/keycloak/resources/themes/custom-keycloak/login/date-of-birth-access-code.ftl
new file mode 100644
index 0000000000000000000000000000000000000000..622eeac6b9de30edd68e7a3901b59b38e23092c3
--- /dev/null
+++ b/backend/keycloak/resources/themes/custom-keycloak/login/date-of-birth-access-code.ftl
@@ -0,0 +1,61 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout; section>
+    <#if section = "title">
+
+        ${msg("loginTitle",(realm.displayName!''))}
+
+    <#elseif section = "header">
+
+        ${msg("accessCodePageTitle")}
+
+        <div id="page-title-info-text">
+            ${msg(context_info!'')}
+        </div>
+
+    <#elseif section = "form">
+
+        <div id="kc-form">
+        <div id="kc-form-wrapper">
+        <form id="kc-form-login" class="form" onsubmit="return true;" action="${url.loginAction}" method="post" autocomplete="off">
+
+            <div class="${properties.kcFormGroupClass!}">
+                <label for="access-code" class="${properties.kcLabelClass!}">
+                    ${msg("accessCodeLabel")}
+                </label>
+                <input tabindex="1" id="access-code" class="${properties.kcInputClass!}" name="access_code" type="text"
+                    value="${(access_code!'')}" <#if access_code?exists>readonly</#if>
+                    aria-invalid="<#if messagesPerField.existsError('access_code')>true</#if>"
+                />
+                <#if messagesPerField.existsError('access_code')>
+                    <span id="input-error" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
+                        ${kcSanitize(messagesPerField.getFirstError('access_code'))?no_esc}
+                    </span>
+                </#if>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <label for="date-of-birth" class="${properties.kcLabelClass!}">
+                    ${msg("dateOfBirthLabel")}
+                </label>
+                <input tabindex="2" id="date-of-birth" class="${properties.kcInputClass!}" name="date_of_birth" type="date"
+                    aria-invalid="<#if messagesPerField.existsError('access_code')>true</#if>"
+                />
+                <#if messagesPerField.existsError('access_code')>
+                    <span id="input-error" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
+                        ${kcSanitize(messagesPerField.getFirstError('access_code'))?no_esc}
+                    </span>
+                </#if>
+            </div>
+
+            <div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
+                <input tabindex="3" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
+                    name="login" id="kc-login" type="submit" value="${msg("doSubmit")}"
+                />
+            </div>
+
+        </form>
+        </div>
+        </div>
+
+    </#if>
+</@layout.registrationLayout>
diff --git a/backend/keycloak/resources/themes/custom-keycloak/login/messages/messages_de.properties b/backend/keycloak/resources/themes/custom-keycloak/login/messages/messages_de.properties
index 6d60540d5721353bc8f6316b31520e6b549296e8..ef80a3a1d0d858511ee6fedf080ce3b800e49631 100644
--- a/backend/keycloak/resources/themes/custom-keycloak/login/messages/messages_de.properties
+++ b/backend/keycloak/resources/themes/custom-keycloak/login/messages/messages_de.properties
@@ -1,14 +1,23 @@
 accessCodePageTitle=Anmelden mit Anmeldecode
 accessCodeLabel=Anmeldecode
 dateOfBirthLabel=Geburtsdatum
+pinLabel=PIN
 
 missingAccessCode=Bitte geben Sie einen Anmeldecode ein.
 missingDateOfBirth=Bitte geben Sie das Geburtsdatum ein.
-invalidAccessCodeCredentials=Ungültiger Anmeldecode oder Geburtsdatum.
+missingPin=Bitte geben Sie Ihre geheime PIN ein.
+invalidAccessCodeOrDateOfBirth=Ungültiger Anmeldecode oder Geburtsdatum.
+invalidAccessCodeOrPin=Ungültiger Anmeldecode oder PIN.
 accountLockedOut=Zu viele fehlgeschlagene Anmeldeversuche. Bitte versuchen Sie es in 6 Stunden erneut.
+defaultDateOfBirthPageTitleInfo=Geben Sie den Anmeldecode zusammen mit dem zweiten Faktor an.
+esuDateOfBirthPageTitleInfo=Geben Sie den Anmeldecode aus dem Einladungsbrief zusammen mit dem Geburtsdatum des Kindes an.
+tmDateOfBirthPageTitleInfo=Geben Sie den Anmeldecode aus der Bestätigungsemail zusammen mit Ihrem Geburtsdatum an.
+pinPageTitleInfo=Bitte geben Sie den Anmeldecode sowie Ihre persönliche 6-stellige, nur numerische PIN ein.
 
-access-code-display-name=Anmeldecode und Geburtsdatum
-access-code-help-text=Anmelden, indem Sie den Ihnen zugesandten Anmeldecode verwenden und Ihr Geburtsdatum eingeben.
+date-of-birth-access-code-display-name=Anmeldecode und Geburtsdatum
+date-of-birth-access-code-help-text=Anmelden, indem Sie den Ihnen zugesandten Anmeldecode verwenden und Ihr Geburtsdatum eingeben.
+pin-access-code-display-name=Anmeldecode und PIN
+pin-access-code-help-text=Anmelden, indem Sie den Ihnen gegebenen Anmeldecode verwenden und Ihren geheime PIN eingeben.
 
 loginAccountTitle=Anmelden
 noAccount=Noch keinen Account?
diff --git a/backend/keycloak/resources/themes/custom-keycloak/login/messages/messages_en.properties b/backend/keycloak/resources/themes/custom-keycloak/login/messages/messages_en.properties
index 1cbfe5db1728115f518b7fe3778a4fffba78d61b..730ddcfab80cdf41769bb102a4432fdd8b54788c 100644
--- a/backend/keycloak/resources/themes/custom-keycloak/login/messages/messages_en.properties
+++ b/backend/keycloak/resources/themes/custom-keycloak/login/messages/messages_en.properties
@@ -1,13 +1,22 @@
 accessCodePageTitle=Login with Access Code
 accessCodeLabel=Access Code
 dateOfBirthLabel=Date of Birth
+pinLabel=PIN
 
 missingAccessCode=Missing access code
 missingDateOfBirth=Missing date of birth
+missingPin=Missing PIN
 invalidAccessCodeCredentials=Invalid access code or date of birth
 accountLockedOut=Too many failed login attempts, try again in 6 hours.
+defaultAccessCodeTitleInfo=Enter the access code.
+esuDateOfBirthPageTitleInfo=Enter the access code and the birthday of the child.
+tmDateOfBirthPageTitleInfo=Enter the access code and your birthday.
+pinPageTitleInfo=Enter the access code and the PIN.
+
+date-of-birth-access-code-display-name=Access Code and Birthday
+date-of-birth-access-code-help-text=Sign in by entering an access code provided to you and your birthday.
+pin-access-code-display-name=Access Code and PIN
+pin-access-code-help-text=Sign in by entering an access code provided to you and your secret PIN.
 
-access-code-display-name=Access Code and Birthday
-access-code-help-text=Sign in by entering an access code provided to you and your birthday.
 
 logoutConfirmHeader=Important note: To ensure that no sensible data is revealed, you must close the browser entirely after successful logout.
diff --git a/backend/keycloak/resources/themes/custom-keycloak/login/access-code.ftl b/backend/keycloak/resources/themes/custom-keycloak/login/pin-access-code.ftl
similarity index 67%
rename from backend/keycloak/resources/themes/custom-keycloak/login/access-code.ftl
rename to backend/keycloak/resources/themes/custom-keycloak/login/pin-access-code.ftl
index d14b2107574ce8c373b68371e6944c1e5fabbf5a..74e75bd5dff84e091bfbcbeefaf836b3ce0068bd 100644
--- a/backend/keycloak/resources/themes/custom-keycloak/login/access-code.ftl
+++ b/backend/keycloak/resources/themes/custom-keycloak/login/pin-access-code.ftl
@@ -8,6 +8,10 @@
 
         ${msg("accessCodePageTitle")}
 
+        <div id="page-title-info-text">
+            ${msg(context_info!'')}
+        </div>
+
     <#elseif section = "form">
 
         <div id="kc-form">
@@ -29,19 +33,19 @@
                 </#if>
             </div>
 
-           <div class="${properties.kcFormGroupClass!}">
-               <label for="date-of-birth" class="${properties.kcLabelClass!}">
-                   ${msg("dateOfBirthLabel")}
-               </label>
-               <input tabindex="2" id="date-of-birth" class="${properties.kcInputClass!}" name="date_of_birth" type="date"
-                   aria-invalid="<#if messagesPerField.existsError('access_code')>true</#if>"
-               />
-               <#if messagesPerField.existsError('access_code')>
-                   <span id="input-error" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
-                       ${kcSanitize(messagesPerField.getFirstError('access_code'))?no_esc}
-                   </span>
-               </#if>
-           </div>
+            <div class="${properties.kcFormGroupClass!}">
+                <label for="pin" class="${properties.kcLabelClass!}">
+                    ${msg("pinLabel")}
+                </label>
+                <input tabindex="2" id="pin" class="${properties.kcInputClass!}" name="pin" type="password" maxlength="6"
+                    aria-invalid="<#if messagesPerField.existsError('access_code')>true</#if>"
+                />
+                <#if messagesPerField.existsError('access_code')>
+                    <span id="input-error" class="${properties.kcInputErrorMessageClass!}" aria-live="polite">
+                        ${kcSanitize(messagesPerField.getFirstError('access_code'))?no_esc}
+                    </span>
+                </#if>
+            </div>
 
             <div id="kc-form-buttons" class="${properties.kcFormGroupClass!}">
                 <input tabindex="3" class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonBlockClass!} ${properties.kcButtonLargeClass!}"
diff --git a/backend/keycloak/resources/themes/custom-keycloak/login/resources/css/custom-login.css b/backend/keycloak/resources/themes/custom-keycloak/login/resources/css/custom-login.css
index 4e6e15793b433d708b3b990ad1285897472df10f..05aada8982dcb458f285c1de25b5ad7e3ef4e8f9 100644
--- a/backend/keycloak/resources/themes/custom-keycloak/login/resources/css/custom-login.css
+++ b/backend/keycloak/resources/themes/custom-keycloak/login/resources/css/custom-login.css
@@ -207,3 +207,10 @@ a {
     position: initial;
     color: var(--global--color-primary);
 }
+
+#page-title-info-text {
+    font-size: 16px;
+    font-weight: normal;
+    line-height: 24px;
+    margin-top: 24px;
+}
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeAwareAuthenticationContextBean.java b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeAwareAuthenticationContextBean.java
new file mode 100644
index 0000000000000000000000000000000000000000..6530b94a711e91f6a86cf6b2bf8698af9307711b
--- /dev/null
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeAwareAuthenticationContextBean.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.keycloak.authenticator;
+
+import org.keycloak.forms.login.freemarker.model.AuthenticationContextBean;
+
+public class AccessCodeAwareAuthenticationContextBean extends AuthenticationContextBean {
+
+  public AccessCodeAwareAuthenticationContextBean() {
+    super(null, null);
+  }
+
+  @Override
+  public boolean showTryAnotherWayLink() {
+    return false;
+  }
+
+  @Override
+  public boolean showUsername() {
+    return false;
+  }
+
+  @Override
+  public boolean showResetCredentials() {
+    return false;
+  }
+}
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeForm.java b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeForm.java
index c566f6de640ea8c644ecd20d35e45e883e4a8462..574943c6f6777a122aaad1ecaf06581b615392bf 100644
--- a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeForm.java
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeForm.java
@@ -8,13 +8,13 @@ package de.eshg.keycloak.authenticator;
 import static org.keycloak.authentication.authenticators.util.AuthenticatorUtils.getDisabledByBruteForceEventError;
 
 import de.eshg.keycloak.api.user.KeycloakAttributes;
-import de.eshg.keycloak.credentialprovider.DateOfBirthCredentialModel;
 import jakarta.ws.rs.core.MultivaluedHashMap;
 import jakarta.ws.rs.core.MultivaluedMap;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Function;
 import org.jboss.logging.Logger;
 import org.keycloak.authentication.AbstractFormAuthenticator;
 import org.keycloak.authentication.AuthenticationFlowContext;
@@ -23,27 +23,20 @@ import org.keycloak.events.Errors;
 import org.keycloak.forms.login.LoginFormsProvider;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.FormMessage;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.sessions.AuthenticationSessionModel;
 import org.keycloak.utils.StringUtil;
 
-public class AccessCodeForm extends AbstractFormAuthenticator {
+public abstract class AccessCodeForm extends AbstractFormAuthenticator {
 
   private static final Logger logger = Logger.getLogger(AccessCodeForm.class);
 
-  public static final String FORM_TEMPLATE = "access-code.ftl";
   public static final String ACCESS_CODE_QUERY_PARAMETER = "access_code";
-
+  public static final String CONTEXT_INFO_QUERY_PARAMETER = "context_info";
   public static final String ACCESS_CODE_FIELD = "access_code";
-  public static final String DATE_OF_BIRTH_FIELD = "date_of_birth";
-
   public static final String MISSING_ACCESS_CODE_MESSAGE = "missingAccessCode";
-  public static final String MISSING_DATE_OF_BIRTH_MESSAGE = "missingDateOfBirth";
-  public static final String INVALID_ACCESS_CODE_CREDENTIALS_MESSAGE =
-      "invalidAccessCodeCredentials";
   public static final String ACCOUNT_LOCKED_OUT_MESSAGE = "accountLockedOut";
 
   @Override
@@ -54,11 +47,11 @@ public class AccessCodeForm extends AbstractFormAuthenticator {
 
     // Only show the authenticator if prompted by query parameter or auth note set
     if (Objects.equals(
-            queryParameters.getFirst(OIDCLoginProtocol.PROMPT_PARAM), ACCESS_CODE_QUERY_PARAMETER)
+            queryParameters.getFirst(OIDCLoginProtocol.PROMPT_PARAM), getAuthenticatorPrompt())
         || Objects.equals(
-            authSession.getAuthNote(OIDCLoginProtocol.PROMPT_PARAM), ACCESS_CODE_QUERY_PARAMETER)) {
+            authSession.getAuthNote(OIDCLoginProtocol.PROMPT_PARAM), getAuthenticatorPrompt())) {
 
-      authSession.setAuthNote(OIDCLoginProtocol.PROMPT_PARAM, ACCESS_CODE_QUERY_PARAMETER);
+      authSession.setAuthNote(OIDCLoginProtocol.PROMPT_PARAM, getAuthenticatorPrompt());
 
       // If an access code was provided in the initial rendering of the page
       // add it to the formData
@@ -66,12 +59,21 @@ public class AccessCodeForm extends AbstractFormAuthenticator {
         String accessCode = queryParameters.getFirst(ACCESS_CODE_QUERY_PARAMETER);
         formData.add(ACCESS_CODE_FIELD, accessCode);
       }
+      applyCustomFormTemplateValues(context);
+      addContextInfo(context, formData);
       challenge(context, formData, Map.of());
     } else {
       context.attempted();
     }
   }
 
+  protected abstract void addContextInfo(
+      AuthenticationFlowContext context, MultivaluedMap<String, String> formData);
+
+  protected abstract String getAuthenticatorPrompt();
+
+  protected abstract String getInvalidCredentialsMessage();
+
   /*
    * This processes the form submission and adds error handling to the same form on failure
    * or delegates to the next authenticators and required actions on success
@@ -80,14 +82,11 @@ public class AccessCodeForm extends AbstractFormAuthenticator {
   public void action(AuthenticationFlowContext context) {
     MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
     Map<String, String> errors = new HashMap<>();
-
     String accessCode = formData.getFirst(ACCESS_CODE_FIELD).replaceAll("\\s+", "");
-    if (StringUtil.isBlank(accessCode)) {
-      errors.put(ACCESS_CODE_FIELD, MISSING_ACCESS_CODE_MESSAGE);
-    }
-    if (StringUtil.isBlank(formData.getFirst(DATE_OF_BIRTH_FIELD))) {
-      errors.put(DATE_OF_BIRTH_FIELD, MISSING_DATE_OF_BIRTH_MESSAGE);
-    }
+    applyCustomFormTemplateValues(context);
+    addContextInfo(context, formData);
+    validateAccesCodeField(accessCode, errors);
+    validateCredentialField(formData, errors);
 
     if (errors.isEmpty()) {
       getUserByAccessCodeAttribute(context, accessCode)
@@ -96,17 +95,7 @@ public class AccessCodeForm extends AbstractFormAuthenticator {
                 // Check if the user is locked out
                 String bruteForceError = getDisabledByBruteForceEventError(context, user);
                 boolean isDisabled = bruteForceError != null;
-                // Is submitted in the format yyyy-mm-dd from the html input tag with type=date
-                String dateOfBirth = formData.getFirst(DATE_OF_BIRTH_FIELD);
-                if (!isDisabled
-                    && (user.credentialManager()
-                            .isValid(
-                                new UserCredentialModel(
-                                    null, DateOfBirthCredentialModel.TYPE, dateOfBirth))
-                        // Todo(ISSUE-7041): Remove. For accounts in prod that still save the date
-                        // of birth as attribute
-                        || dateOfBirth.equals(
-                            user.getFirstAttribute(KeycloakAttributes.DATE_OF_BIRTH_ATTRIBUTE)))) {
+                if (!isDisabled && validateCredentials(formData, user)) {
                   context.setUser(user);
                   context.success();
                 } else {
@@ -117,14 +106,14 @@ public class AccessCodeForm extends AbstractFormAuthenticator {
                   if (isDisabled) {
                     errors.put(ACCESS_CODE_FIELD, ACCOUNT_LOCKED_OUT_MESSAGE);
                   } else {
-                    errors.put(ACCESS_CODE_FIELD, INVALID_ACCESS_CODE_CREDENTIALS_MESSAGE);
+                    errors.put(ACCESS_CODE_FIELD, getInvalidCredentialsMessage());
                   }
                 }
               },
               () -> {
                 // Invalid access code, but display the same error
                 formData.remove(ACCESS_CODE_FIELD);
-                errors.put(ACCESS_CODE_FIELD, INVALID_ACCESS_CODE_CREDENTIALS_MESSAGE);
+                errors.put(ACCESS_CODE_FIELD, getInvalidCredentialsMessage());
               });
     }
 
@@ -133,6 +122,31 @@ public class AccessCodeForm extends AbstractFormAuthenticator {
     }
   }
 
+  private void validateAccesCodeField(String accessCode, Map<String, String> errors) {
+    if (StringUtil.isBlank(accessCode)) {
+      errors.put(ACCESS_CODE_FIELD, MISSING_ACCESS_CODE_MESSAGE);
+    }
+  }
+
+  private void applyCustomFormTemplateValues(AuthenticationFlowContext context) {
+    LoginFormsProvider form = context.form();
+    form.setAttributeMapper(
+        new Function<Map<String, Object>, Map<String, Object>>() {
+          @Override
+          public Map<String, Object> apply(Map<String, Object> attributes) {
+            attributes.computeIfPresent(
+                "auth", (key, bean) -> new AccessCodeAwareAuthenticationContextBean());
+            return attributes;
+          }
+        });
+  }
+
+  protected abstract void validateCredentialField(
+      MultivaluedMap<String, String> formData, Map<String, String> errors);
+
+  protected abstract boolean validateCredentials(
+      MultivaluedMap<String, String> formData, UserModel user);
+
   /*
    * This creates the custom code form which asks for an access code and a second authentication information
    * The access code is prefilled if it was previously included in the url and was a valid one where a use lookup was successful
@@ -148,17 +162,15 @@ public class AccessCodeForm extends AbstractFormAuthenticator {
         .filter(name -> StringUtil.isNotBlank(formData.getFirst(name)))
         .forEach(name -> form.setAttribute(name, formData.getFirst(name)));
     errors.forEach((field, message) -> form.addError(new FormMessage(field, message)));
-    context.challenge(form.createForm(FORM_TEMPLATE));
+    context.challenge(form.createForm(getFormTemplate()));
   }
 
   static void logFailedAttemptOnUser(
       AuthenticationFlowContext context, UserModel user, String bruteForceError) {
     context.getEvent().user(user);
-    if (bruteForceError != null) {
-      context.getEvent().error(bruteForceError);
-    } else {
-      context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
-    }
+    context
+        .getEvent()
+        .error(Objects.requireNonNullElse(bruteForceError, Errors.INVALID_USER_CREDENTIALS));
     RealmModel realm = context.getRealm();
     if (realm.isBruteForceProtected()) {
       context
@@ -198,4 +210,6 @@ public class AccessCodeForm extends AbstractFormAuthenticator {
 
   @Override
   public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) {}
+
+  protected abstract String getFormTemplate();
 }
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeFormFactory.java b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeFormFactory.java
index c10afd316a8ebf0c2ed9df1c7660959a3082c23d..01288a48cf0cb6147610b28ee724684299fc74d2 100644
--- a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeFormFactory.java
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/AccessCodeFormFactory.java
@@ -7,21 +7,16 @@ package de.eshg.keycloak.authenticator;
 
 import java.util.List;
 import org.keycloak.Config;
-import org.keycloak.authentication.Authenticator;
 import org.keycloak.authentication.AuthenticatorFactory;
 import org.keycloak.models.AuthenticationExecutionModel;
-import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.provider.ProviderConfigProperty;
 
-public class AccessCodeFormFactory implements AuthenticatorFactory {
-
-  public static final String PROVIDER_ID = "access-code";
-  static AccessCodeForm SINGLETON = new AccessCodeForm();
+public abstract class AccessCodeFormFactory implements AuthenticatorFactory {
 
   @Override
   public String getDisplayType() {
-    return "Access Code Form";
+    return "%s Access Code Form".formatted(getFormattedCredentialType());
   }
 
   @Override
@@ -46,7 +41,8 @@ public class AccessCodeFormFactory implements AuthenticatorFactory {
 
   @Override
   public String getHelpText() {
-    return "Validates a code and a second identity factory from a form";
+    return "Validates a code and a %s credential from a form"
+        .formatted(getFormattedCredentialType());
   }
 
   @Override
@@ -54,11 +50,6 @@ public class AccessCodeFormFactory implements AuthenticatorFactory {
     return null;
   }
 
-  @Override
-  public Authenticator create(KeycloakSession session) {
-    return SINGLETON;
-  }
-
   @Override
   public void init(Config.Scope config) {}
 
@@ -70,6 +61,10 @@ public class AccessCodeFormFactory implements AuthenticatorFactory {
 
   @Override
   public String getId() {
-    return PROVIDER_ID;
+    return getCredentialType() + "-access-code";
   }
+
+  public abstract String getCredentialType();
+
+  public abstract String getFormattedCredentialType();
 }
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DateOfBirthAccessCodeForm.java b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DateOfBirthAccessCodeForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..0968dd8d68ccd23f288c611bc7f9ae0fcde7de09
--- /dev/null
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DateOfBirthAccessCodeForm.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.keycloak.authenticator;
+
+import de.eshg.keycloak.api.user.KeycloakAttributes;
+import de.eshg.keycloak.credentialprovider.DateOfBirthCredentialModel;
+import jakarta.ws.rs.core.MultivaluedMap;
+import java.util.Map;
+import java.util.Objects;
+import org.keycloak.authentication.AuthenticationFlowContext;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.sessions.AuthenticationSessionModel;
+import org.keycloak.utils.StringUtil;
+
+public class DateOfBirthAccessCodeForm extends AccessCodeForm {
+
+  public static final String FORM_TEMPLATE = "date-of-birth-access-code.ftl";
+  public static final String DATE_OF_BIRTH_FIELD = "date_of_birth";
+  public static final String MISSING_DATE_OF_BIRTH_MESSAGE = "missingDateOfBirth";
+  public static final String INVALID_CREDENTIALS_MESSAGE = "invalidAccessCodeOrDateOfBirth";
+  public static final String AUTHENTICATION_PROMPT = DateOfBirthCredentialModel.TYPE;
+
+  @Override
+  protected void addContextInfo(
+      AuthenticationFlowContext context, MultivaluedMap<String, String> formData) {
+    MultivaluedMap<String, String> queryParameters = context.getUriInfo().getQueryParameters();
+    AuthenticationSessionModel authSession = context.getAuthenticationSession();
+    String contextInfoKey =
+        Objects.requireNonNullElse(
+            queryParameters.getFirst(CONTEXT_INFO_QUERY_PARAMETER),
+            Objects.requireNonNullElse(
+                authSession.getAuthNote(CONTEXT_INFO_QUERY_PARAMETER), "default"));
+
+    String contextInfoQueryParameter =
+        switch (contextInfoKey) {
+          case "esu" -> "esuDateOfBirthPageTitleInfo";
+          case "tm" -> "tmDateOfBirthPageTitleInfo";
+          default -> "defaultDateOfBirthPageTitleInfo";
+        };
+    formData.add(CONTEXT_INFO_QUERY_PARAMETER, contextInfoQueryParameter);
+
+    authSession.setAuthNote(CONTEXT_INFO_QUERY_PARAMETER, contextInfoKey);
+  }
+
+  @Override
+  protected String getAuthenticatorPrompt() {
+    return AUTHENTICATION_PROMPT;
+  }
+
+  @Override
+  protected String getInvalidCredentialsMessage() {
+    return INVALID_CREDENTIALS_MESSAGE;
+  }
+
+  @Override
+  protected void validateCredentialField(
+      MultivaluedMap<String, String> formData, Map<String, String> errors) {
+    if (StringUtil.isBlank(formData.getFirst(DATE_OF_BIRTH_FIELD))) {
+      errors.put(DATE_OF_BIRTH_FIELD, MISSING_DATE_OF_BIRTH_MESSAGE);
+    }
+  }
+
+  @Override
+  protected boolean validateCredentials(MultivaluedMap<String, String> formData, UserModel user) {
+    // Is submitted in the format yyyy-mm-dd from the html input tag with type=date
+    String dateOfBirth = formData.getFirst(DATE_OF_BIRTH_FIELD);
+    return user.credentialManager()
+            .isValid(new UserCredentialModel(null, DateOfBirthCredentialModel.TYPE, dateOfBirth))
+        // Todo(ISSUE-7041): Remove. For accounts in prod that still save the date
+        // of birth as attribute
+        || dateOfBirth.equals(user.getFirstAttribute(KeycloakAttributes.DATE_OF_BIRTH_ATTRIBUTE));
+  }
+
+  @Override
+  protected String getFormTemplate() {
+    return FORM_TEMPLATE;
+  }
+}
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DateOfBirthAccessCodeFormFactory.java b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DateOfBirthAccessCodeFormFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..14d074871d0cc0501878413d8d2aa8d338eb3b5f
--- /dev/null
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DateOfBirthAccessCodeFormFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.keycloak.authenticator;
+
+import de.eshg.keycloak.credentialprovider.DateOfBirthCredentialModel;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.models.KeycloakSession;
+
+public class DateOfBirthAccessCodeFormFactory extends AccessCodeFormFactory {
+
+  static DateOfBirthAccessCodeForm SINGLETON = new DateOfBirthAccessCodeForm();
+
+  @Override
+  public String getCredentialType() {
+    return DateOfBirthCredentialModel.TYPE;
+  }
+
+  @Override
+  public String getFormattedCredentialType() {
+    return "Date of Birth";
+  }
+
+  @Override
+  public Authenticator create(KeycloakSession session) {
+    return SINGLETON;
+  }
+}
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DeprecatedAccessCodeFormFactory.java b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DeprecatedAccessCodeFormFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..8807c666359e3200f560d5077b796c6dfa80a054
--- /dev/null
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/DeprecatedAccessCodeFormFactory.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.keycloak.authenticator;
+
+import java.util.List;
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.models.AuthenticationExecutionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderConfigProperty;
+
+// ToDo: remove after all environments migrated to new dob-authenticator
+@Deprecated(since = "forever")
+public class DeprecatedAccessCodeFormFactory implements AuthenticatorFactory {
+
+  private static final Logger logger = Logger.getLogger(DeprecatedAccessCodeFormFactory.class);
+
+  @Override
+  public String getDisplayType() {
+    return "Access Code Form";
+  }
+
+  @Override
+  public String getReferenceCategory() {
+    return "Access Code";
+  }
+
+  @Override
+  public boolean isConfigurable() {
+    return false;
+  }
+
+  @Override
+  public AuthenticationExecutionModel.Requirement[] getRequirementChoices() {
+    return REQUIREMENT_CHOICES;
+  }
+
+  @Override
+  public boolean isUserSetupAllowed() {
+    return false;
+  }
+
+  @Override
+  public String getHelpText() {
+    return "";
+  }
+
+  @Override
+  public List<ProviderConfigProperty> getConfigProperties() {
+    return null;
+  }
+
+  @Override
+  public Authenticator create(KeycloakSession keycloakSession) {
+    logger.warn("Access Code Form created from deprecated Factory!");
+    return new DateOfBirthAccessCodeForm();
+  }
+
+  @Override
+  public void init(Config.Scope config) {
+    logger.warn("DeprecatedAccessCodeFormFactory initialized!");
+  }
+
+  @Override
+  public void postInit(KeycloakSessionFactory factory) {
+    logger.warn("DeprecatedAccessCodeFormFactory post init!");
+  }
+
+  @Override
+  public void close() {}
+
+  @Override
+  public String getId() {
+    return "access-code";
+  }
+}
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/PinAccessCodeForm.java b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/PinAccessCodeForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8480a33eabe4276cd694eb14969689b5d205610
--- /dev/null
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/PinAccessCodeForm.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.keycloak.authenticator;
+
+import de.eshg.keycloak.credentialprovider.PinCredentialModel;
+import jakarta.ws.rs.core.MultivaluedMap;
+import java.util.Map;
+import org.keycloak.authentication.AuthenticationFlowContext;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.utils.StringUtil;
+
+public class PinAccessCodeForm extends AccessCodeForm {
+
+  public static final String FORM_TEMPLATE = "pin-access-code.ftl";
+  public static final String PIN_FIELD = "pin";
+  public static final String MISSING_PIN_MESSAGE = "missingPin";
+  public static final String INVALID_CREDENTIALS_MESSAGE = "invalidAccessCodeOrPin";
+  public static final String AUTHENTICATION_PROMPT = PinCredentialModel.TYPE;
+
+  @Override
+  protected void addContextInfo(
+      AuthenticationFlowContext context, MultivaluedMap<String, String> formData) {
+    formData.add(CONTEXT_INFO_QUERY_PARAMETER, "pinPageTitleInfo");
+  }
+
+  @Override
+  protected String getAuthenticatorPrompt() {
+    return AUTHENTICATION_PROMPT;
+  }
+
+  @Override
+  protected String getInvalidCredentialsMessage() {
+    return INVALID_CREDENTIALS_MESSAGE;
+  }
+
+  @Override
+  protected void validateCredentialField(
+      MultivaluedMap<String, String> formData, Map<String, String> errors) {
+    if (StringUtil.isBlank(formData.getFirst(PIN_FIELD))) {
+      errors.put(PIN_FIELD, MISSING_PIN_MESSAGE);
+    }
+  }
+
+  @Override
+  protected boolean validateCredentials(MultivaluedMap<String, String> formData, UserModel user) {
+    String pin = formData.getFirst(PIN_FIELD);
+    return user.credentialManager()
+        .isValid(new UserCredentialModel(null, PinCredentialModel.TYPE, pin));
+  }
+
+  @Override
+  protected String getFormTemplate() {
+    return FORM_TEMPLATE;
+  }
+}
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/PinAccessCodeFormFactory.java b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/PinAccessCodeFormFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac9a0ad90528f7cd355f3b4a931e901956015208
--- /dev/null
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/authenticator/PinAccessCodeFormFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.keycloak.authenticator;
+
+import de.eshg.keycloak.credentialprovider.PinCredentialModel;
+import org.keycloak.authentication.Authenticator;
+import org.keycloak.models.KeycloakSession;
+
+public class PinAccessCodeFormFactory extends AccessCodeFormFactory {
+
+  static PinAccessCodeForm SINGLETON = new PinAccessCodeForm();
+
+  @Override
+  public String getCredentialType() {
+    return PinCredentialModel.TYPE;
+  }
+
+  @Override
+  public String getFormattedCredentialType() {
+    return "PIN";
+  }
+
+  @Override
+  public Authenticator create(KeycloakSession session) {
+    return SINGLETON;
+  }
+}
diff --git a/backend/keycloak/src/main/java/de/eshg/keycloak/credentialprovider/PinCredentialProvider.java b/backend/keycloak/src/main/java/de/eshg/keycloak/credentialprovider/PinCredentialProvider.java
index 66058486d079f38befe5d8e052c12e73b984f844..2a84a8343e9c91d0ffb64f4e4a260908a845b878 100644
--- a/backend/keycloak/src/main/java/de/eshg/keycloak/credentialprovider/PinCredentialProvider.java
+++ b/backend/keycloak/src/main/java/de/eshg/keycloak/credentialprovider/PinCredentialProvider.java
@@ -29,6 +29,8 @@ public class PinCredentialProvider
         CredentialInputUpdater,
         CredentialInputValidator {
 
+  private static final Pattern PIN_PATTERN = Pattern.compile("^\\d{6}$");
+
   protected final KeycloakSession session;
 
   public PinCredentialProvider(KeycloakSession session) {
@@ -85,10 +87,9 @@ public class PinCredentialProvider
   }
 
   private void validate(String pin) {
-    Pattern pattern = Pattern.compile("^\\d{6}$");
-    Matcher matcher = pattern.matcher(pin);
+    Matcher matcher = PIN_PATTERN.matcher(pin);
     if (!matcher.matches()) {
-      throw new ModelException("PIN does not match defined pattern", pattern.pattern());
+      throw new ModelException("PIN does not match defined pattern", PIN_PATTERN.pattern());
     }
   }
 
diff --git a/backend/keycloak/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory b/backend/keycloak/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
index 5acaae06e1ea093f14a25e2a2f531f389c7457c9..4db830f410b2a203a91441187384cea7bc0162f0 100755
--- a/backend/keycloak/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
+++ b/backend/keycloak/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory
@@ -1 +1,3 @@
-de.eshg.keycloak.authenticator.AccessCodeFormFactory
+de.eshg.keycloak.authenticator.DateOfBirthAccessCodeFormFactory
+de.eshg.keycloak.authenticator.PinAccessCodeFormFactory
+de.eshg.keycloak.authenticator.DeprecatedAccessCodeFormFactory
diff --git a/backend/lib-aggregation/gradle.lockfile b/backend/lib-aggregation/gradle.lockfile
index d11c2c92be5906b3f5ace4c3b5540cb1cc5b2f43..fea50cf3e6a785007080bc7f1ef3db404e07c61f 100644
--- a/backend/lib-aggregation/gradle.lockfile
+++ b/backend/lib-aggregation/gradle.lockfile
@@ -52,10 +52,10 @@ io.prometheus:prometheus-metrics-exposition-formats:1.3.5=productionRuntimeClass
 io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -90,10 +90,10 @@ org.hamcrest:hamcrest-core:2.2=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -110,15 +110,16 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testFixturesCompil
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
diff --git a/backend/lib-appointmentblock/gradle.lockfile b/backend/lib-appointmentblock/gradle.lockfile
index 4fb93e1d6d677b7306618a522f2e80db82818a89..c4de7f8685b1186255ec232cd300974f066310dd 100644
--- a/backend/lib-appointmentblock/gradle.lockfile
+++ b/backend/lib-appointmentblock/gradle.lockfile
@@ -60,10 +60,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -114,13 +114,13 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
-org.jetbrains:annotations:26.0.1=compileClasspath
+org.jetbrains:annotations:26.0.2=compileClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -136,16 +136,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-appointmentblock/openApi.json b/backend/lib-appointmentblock/openApi.json
index af595e4b5aff54278fdc5f7b39cd18207bc9fe9c..22ba0626c336863382ab5e8198ededc825c855d0 100644
--- a/backend/lib-appointmentblock/openApi.json
+++ b/backend/lib-appointmentblock/openApi.json
@@ -488,9 +488,9 @@
             "format" : "uuid"
           },
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
@@ -819,9 +819,9 @@
         "type" : "object",
         "properties" : {
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockService.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockService.java
index 3a950e6ab1b9920423be19aa765a590a15f78eb4..7232301cfe8b39ef6967eaaf6902f1320b49af54 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockService.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockService.java
@@ -24,8 +24,8 @@ import de.eshg.rest.service.security.CurrentUserHelper;
 import java.time.Clock;
 import java.time.DayOfWeek;
 import java.time.Instant;
-import java.time.LocalDate;
 import java.time.LocalTime;
+import java.time.ZonedDateTime;
 import java.util.*;
 import java.util.stream.Stream;
 import org.springframework.data.domain.Page;
@@ -267,8 +267,7 @@ public class AppointmentBlockService {
     AppointmentBlockGroup appointmentBlockGroup = new AppointmentBlockGroup();
     appointmentBlockGroup.setType(appointmentType);
     appointmentBlockGroup.setParallelExaminations(request.parallelExaminations());
-    appointmentBlockGroup.setSlotDurationInMinutes(
-        appointmentTypeConfig.getStandardDurationInMinutes());
+    appointmentBlockGroup.setSlotDuration(appointmentTypeConfig.getStandardDuration());
     appointmentBlockGroup.setMfas(request.mfas());
     appointmentBlockGroup.setPhysicians(request.physicians());
     appointmentBlockGroup.setConsultants(request.consultants());
@@ -289,35 +288,31 @@ public class AppointmentBlockService {
     if (block.start().isBefore(Instant.now(clock))) {
       throw new BadRequestException("Start of first appointment block must be in the future.");
     }
+    ZonedDateTime start = block.start().atZone(clock.getZone());
+    ZonedDateTime end = block.end().atZone(clock.getZone());
+    List<DayOfWeek> daysOfWeek = DayOfWeekDtoMapper.toJavaTime(block.daysOfWeek());
+    return createDailyAppointmentBlocks(start, end, daysOfWeek);
+  }
 
+  private static List<CreateAppointmentBlockData> createDailyAppointmentBlocks(
+      ZonedDateTime start, ZonedDateTime end, List<DayOfWeek> daysOfWeek) {
     List<CreateAppointmentBlockData> result = new ArrayList<>();
 
-    LocalDate startDate = block.start().atZone(clock.getZone()).toLocalDate();
-    LocalTime startTime = block.start().atZone(clock.getZone()).toLocalTime();
-    LocalTime endTime = block.end().atZone(clock.getZone()).toLocalTime();
-    long totalDays = DAYS.between(block.start(), block.end());
+    LocalTime endTime = end.toLocalTime();
+    long totalDays = DAYS.between(start, end);
     for (int daysToAdd = 0; daysToAdd <= totalDays; daysToAdd++) {
-      LocalDate date = startDate.plusDays(daysToAdd);
-      List<DayOfWeek> daysOfWeek = DayOfWeekDtoMapper.toJavaTime(block.daysOfWeek());
-      if (daysOfWeek.contains(date.getDayOfWeek())) {
-        result.add(appointmentBlockData(date, startTime, endTime));
+      ZonedDateTime appointmentStart = start.plusDays(daysToAdd);
+      if (daysOfWeek.contains(appointmentStart.getDayOfWeek())) {
+        ZonedDateTime appointmentEnd = appointmentStart.with(endTime);
+        result.add(
+            new CreateAppointmentBlockData(
+                appointmentStart.toInstant(), appointmentEnd.toInstant()));
       }
     }
 
     return result;
   }
 
-  private CreateAppointmentBlockData appointmentBlockData(
-      LocalDate date, LocalTime startTime, LocalTime endTime) {
-    Instant appointmentStart = toInstant(date, startTime);
-    Instant appointmentEnd = toInstant(date, endTime);
-    return new CreateAppointmentBlockData(appointmentStart, appointmentEnd);
-  }
-
-  private Instant toInstant(LocalDate date, LocalTime startTime) {
-    return date.atTime(startTime).atZone(clock.getZone()).toInstant();
-  }
-
   public ValidateAppointmentBlockGroupResponse validateDailyAppointmentBlocksForGroup(
       CreateDailyAppointmentBlockGroupRequest request) {
     List<UUID> usersForEvent =
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockSlotUtil.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockSlotUtil.java
index feda11e733a10da4c267d3dea825549a7f8bd07e..d3dbc4dc5bd92378d099ff520e6bf1934941e4ef 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockSlotUtil.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockSlotUtil.java
@@ -16,7 +16,6 @@ import de.eshg.lib.appointmentblock.persistence.entity.AppointmentBlockGroup;
 import de.eshg.rest.service.error.BadRequestException;
 import java.time.Duration;
 import java.time.Instant;
-import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.LinkedHashMap;
@@ -75,11 +74,9 @@ public class AppointmentBlockSlotUtil {
     Instant start = appointmentBlock.getAppointmentBlockStart();
     Instant end = appointmentBlock.getAppointmentBlockEnd();
     long sequentialSlotCount =
-        getNumberOfSequentialAppointmentSlots(
-            appointmentBlockGroup.getSlotDurationInMinutes(), start, end);
+        getNumberOfSequentialAppointmentSlots(appointmentBlockGroup.getSlotDuration(), start, end);
 
-    Duration examinationDuration =
-        Duration.of(appointmentBlockGroup.getSlotDurationInMinutes(), ChronoUnit.MINUTES);
+    Duration examinationDuration = appointmentBlockGroup.getSlotDuration();
     Instant slotStart = start;
     for (int i = 0; i < sequentialSlotCount; i++) {
       Instant slotEnd = slotStart.plus(examinationDuration);
@@ -194,22 +191,20 @@ public class AppointmentBlockSlotUtil {
 
   private long getNumberOfTotalAppointmentSlots(AppointmentBlock appointmentBlock) {
     return getNumberOfTotalAppointmentSlots(
-        appointmentBlock.getAppointmentBlockGroup().getSlotDurationInMinutes(),
+        appointmentBlock.getAppointmentBlockGroup().getSlotDuration(),
         appointmentBlock.getAppointmentBlockGroup().getParallelExaminations(),
         appointmentBlock.getAppointmentBlockStart(),
         appointmentBlock.getAppointmentBlockEnd());
   }
 
   private long getNumberOfTotalAppointmentSlots(
-      int slotDurationInMinutes, int parallelExaminations, Instant start, Instant end) {
-    long numberOfSequentialSlots =
-        getNumberOfSequentialAppointmentSlots(slotDurationInMinutes, start, end);
+      Duration slotDuration, int parallelExaminations, Instant start, Instant end) {
+    long numberOfSequentialSlots = getNumberOfSequentialAppointmentSlots(slotDuration, start, end);
     return numberOfSequentialSlots * parallelExaminations;
   }
 
   private long getNumberOfSequentialAppointmentSlots(
-      int slotDurationInMinutes, Instant start, Instant end) {
-    Duration examinationDuration = Duration.of(slotDurationInMinutes, ChronoUnit.MINUTES);
+      Duration examinationDuration, Instant start, Instant end) {
     Duration appointmentBlockDuration = Duration.between(start, end);
     return appointmentBlockDuration.dividedBy(examinationDuration);
   }
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockValidator.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockValidator.java
index 23709742d071a400b45118d651409d69b0b997b9..45f595880084931b9c841ebed295431d78d1653e 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockValidator.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentBlockValidator.java
@@ -22,7 +22,6 @@ import java.time.Clock;
 import java.time.Duration;
 import java.time.Instant;
 import java.time.LocalTime;
-import java.time.temporal.ChronoUnit;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
@@ -88,9 +87,8 @@ public class AppointmentBlockValidator {
         throw new BadRequestException(
             "AppointmentBlockGroup end time of day must be after start time of day.");
       }
-      Duration examinationDuration =
-          Duration.of(typeConfig.getStandardDurationInMinutes(), ChronoUnit.MINUTES);
-      Duration appointmentBlockLength = Duration.between(startTime, endTime);
+      Duration examinationDuration = typeConfig.getStandardDuration();
+      Duration appointmentBlockLength = Duration.between(start, end);
       if (!DurationUtil.isDivisible(appointmentBlockLength, examinationDuration)) {
         String errorMessage =
             "Appointment block length %s is not a multiple of examination duration %s."
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentTypeMapper.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentTypeMapper.java
index f4ae7bd4ccebb7986dcb30cddda08872a56bc827..4ef669b16af7e548c6d4820b84bdeabba45ac555 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentTypeMapper.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentTypeMapper.java
@@ -27,6 +27,6 @@ public class AppointmentTypeMapper {
     return new AppointmentTypeConfigDto(
         appointmentTypeConfig.getId(),
         toInterfaceType(appointmentTypeConfig.getAppointmentType()),
-        appointmentTypeConfig.getStandardDurationInMinutes());
+        appointmentTypeConfig.getStandardDuration().toMinutes());
   }
 }
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentTypeService.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentTypeService.java
index fca653fe3c2be9c5c4dcf20db5ae2e35efaaf363..615ebc01f69fe50e594ef98c4b8c66fc2841e6fd 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentTypeService.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/AppointmentTypeService.java
@@ -11,6 +11,7 @@ import de.eshg.lib.appointmentblock.api.UpdateAppointmentTypeRequest;
 import de.eshg.lib.appointmentblock.persistence.AppointmentTypeRepository;
 import de.eshg.lib.appointmentblock.persistence.entity.AppointmentTypeConfig;
 import de.eshg.rest.service.error.NotFoundException;
+import java.time.Duration;
 import java.util.Comparator;
 import java.util.List;
 import java.util.UUID;
@@ -49,12 +50,12 @@ public class AppointmentTypeService {
 
   public AppointmentTypeConfigDto updateAppointmentType(
       UUID id, UpdateAppointmentTypeRequest request) {
-
     AppointmentTypeConfig appointmentTypeConfig =
         appointmentTypeRepository
             .findById(id)
             .orElseThrow(() -> new NotFoundException("Appointment type not found"));
-    appointmentTypeConfig.setStandardDurationInMinutes(request.standardDurationInMinutes());
+    appointmentTypeConfig.setStandardDuration(
+        Duration.ofMinutes(request.standardDurationInMinutes()));
     appointmentTypeRepository.save(appointmentTypeConfig);
 
     return AppointmentTypeMapper.toInterfaceType(appointmentTypeConfig);
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/api/AppointmentTypeConfigDto.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/api/AppointmentTypeConfigDto.java
index b9c049e7d0b2c8642fb8361416eb38c4a26568b0..265b216d106f60455b73cad141a739d3841be305 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/api/AppointmentTypeConfigDto.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/api/AppointmentTypeConfigDto.java
@@ -14,4 +14,4 @@ import java.util.UUID;
 public record AppointmentTypeConfigDto(
     @NotNull UUID id,
     @NotNull AppointmentTypeDto appointmentTypeDto,
-    @NotNull @Min(0) int standardDurationInMinutes) {}
+    @NotNull @Min(1) long standardDurationInMinutes) {}
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/api/UpdateAppointmentTypeRequest.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/api/UpdateAppointmentTypeRequest.java
index 6856ec61efe47fab24887e87e9842598e658a72b..9a150002d6db9a778afa895dc56422a9982fb7f5 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/api/UpdateAppointmentTypeRequest.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/api/UpdateAppointmentTypeRequest.java
@@ -8,4 +8,4 @@ package de.eshg.lib.appointmentblock.api;
 import jakarta.validation.constraints.Min;
 import jakarta.validation.constraints.NotNull;
 
-public record UpdateAppointmentTypeRequest(@NotNull @Min(0) int standardDurationInMinutes) {}
+public record UpdateAppointmentTypeRequest(@NotNull @Min(1) long standardDurationInMinutes) {}
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/CreateAppointmentTypeTask.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/CreateAppointmentTypeTask.java
index 5b1464af874e1b6347bde0a8975ad18212ac21fb..306c41eebe6c643f2eb5bd2d40a2fc904ddce31a 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/CreateAppointmentTypeTask.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/CreateAppointmentTypeTask.java
@@ -9,6 +9,7 @@ import de.eshg.lib.appointmentblock.persistence.entity.AppointmentTypeConfig;
 import de.eshg.lib.appointmentblock.spring.AppointmentBlockProperties;
 import de.eshg.persistence.TransactionHelper;
 import jakarta.annotation.PostConstruct;
+import java.time.Duration;
 import java.util.Optional;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -39,8 +40,7 @@ public class CreateAppointmentTypeTask {
             appointmentBlockProperties
                 .getDefaultAppointmentTypeConfiguration()
                 .forEach(
-                    (appointmentType, defaultDuration) -> {
-                      int standardDuration = Math.toIntExact(defaultDuration.toMinutes());
+                    (appointmentType, standardDuration) -> {
                       Optional<AppointmentTypeConfig> config =
                           appointmentTypeRepository.findByAppointmentType(appointmentType);
 
@@ -54,23 +54,23 @@ public class CreateAppointmentTypeTask {
   }
 
   private void createAppointmentTypeConfig(
-      AppointmentType appointmentType, int standardDurationInMinutes) {
+      AppointmentType appointmentType, Duration standardDuration) {
     AppointmentTypeConfig appointmentTypeConfig = new AppointmentTypeConfig();
     appointmentTypeConfig.setAppointmentType(appointmentType);
-    appointmentTypeConfig.setStandardDurationInMinutes(standardDurationInMinutes);
+    appointmentTypeConfig.setStandardDuration(standardDuration);
     appointmentTypeRepository.save(appointmentTypeConfig);
   }
 
   private static void updateAppointmentTypeConfig(
-      AppointmentTypeConfig config, int standardDurationInMinutes) {
-    int previousStandardDurationInMinutes = config.getStandardDurationInMinutes();
-    if (previousStandardDurationInMinutes != standardDurationInMinutes) {
+      AppointmentTypeConfig config, Duration standardDuration) {
+    Duration previousStandardDuration = config.getStandardDuration();
+    if (!previousStandardDuration.equals(standardDuration)) {
       log.info(
-          "Updated appointment type configuration for type {} from {} to {} minutes",
+          "Updated appointment type configuration for type {} from {} to {}",
           config.getAppointmentType(),
-          previousStandardDurationInMinutes,
-          standardDurationInMinutes);
+          previousStandardDuration,
+          standardDuration);
     }
-    config.setStandardDurationInMinutes(standardDurationInMinutes);
+    config.setStandardDuration(standardDuration);
   }
 }
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/entity/AppointmentBlockGroup.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/entity/AppointmentBlockGroup.java
index 74efd1b0ef7b1efbd71497e2ef7fb9689bea21df..db65b8421df875580664f435ec1cca70cee73048 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/entity/AppointmentBlockGroup.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/entity/AppointmentBlockGroup.java
@@ -16,6 +16,7 @@ import jakarta.persistence.Entity;
 import jakarta.persistence.OneToMany;
 import jakarta.persistence.OrderBy;
 import jakarta.persistence.OrderColumn;
+import java.time.Duration;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
@@ -34,7 +35,8 @@ public class AppointmentBlockGroup extends BaseEntityWithExternalId {
 
   private int parallelExaminations;
 
-  private int slotDurationInMinutes;
+  @Column(nullable = false)
+  private Duration slotDuration;
 
   @ElementCollection
   @Column(name = "physician_id", nullable = false)
@@ -77,12 +79,12 @@ public class AppointmentBlockGroup extends BaseEntityWithExternalId {
     this.parallelExaminations = parallelExaminations;
   }
 
-  public int getSlotDurationInMinutes() {
-    return slotDurationInMinutes;
+  public Duration getSlotDuration() {
+    return slotDuration;
   }
 
-  public void setSlotDurationInMinutes(int slotDurationInMinutes) {
-    this.slotDurationInMinutes = slotDurationInMinutes;
+  public void setSlotDuration(Duration slotDuration) {
+    this.slotDuration = slotDuration;
   }
 
   public List<UUID> getPhysicians() {
diff --git a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/entity/AppointmentTypeConfig.java b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/entity/AppointmentTypeConfig.java
index 3136501bd0be865657b630ce8e8814dcdec4a4b7..da2fd8fb38af733de9266f1b19299fa3100f6039 100644
--- a/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/entity/AppointmentTypeConfig.java
+++ b/backend/lib-appointmentblock/src/main/java/de/eshg/lib/appointmentblock/persistence/entity/AppointmentTypeConfig.java
@@ -12,6 +12,7 @@ import de.eshg.lib.common.SensitivityLevel;
 import jakarta.persistence.Column;
 import jakarta.persistence.Entity;
 import jakarta.persistence.Table;
+import java.time.Duration;
 import org.hibernate.annotations.JdbcType;
 import org.hibernate.dialect.PostgreSQLEnumJdbcType;
 
@@ -26,7 +27,8 @@ public class AppointmentTypeConfig extends GloballyUniqueEntityBase {
   @Column(nullable = false, unique = true)
   private AppointmentType appointmentType;
 
-  private int standardDurationInMinutes;
+  @Column(nullable = false)
+  private Duration standardDuration;
 
   public AppointmentType getAppointmentType() {
     return appointmentType;
@@ -36,11 +38,11 @@ public class AppointmentTypeConfig extends GloballyUniqueEntityBase {
     this.appointmentType = appointmentType;
   }
 
-  public int getStandardDurationInMinutes() {
-    return standardDurationInMinutes;
+  public Duration getStandardDuration() {
+    return standardDuration;
   }
 
-  public void setStandardDurationInMinutes(int standardDuration) {
-    this.standardDurationInMinutes = standardDuration;
+  public void setStandardDuration(Duration standardDuration) {
+    this.standardDuration = standardDuration;
   }
 }
diff --git a/backend/lib-auditlog/build.gradle b/backend/lib-auditlog/build.gradle
index 2198bea77cfd9101b877f635773b9e23849e5b15..0578e7e9e22ae0ca42e00599fbadff9907b98aac 100644
--- a/backend/lib-auditlog/build.gradle
+++ b/backend/lib-auditlog/build.gradle
@@ -1,6 +1,7 @@
 plugins {
     id "eshg.java-lib"
     id "eshg.base-test-dependency"
+    id "java-test-fixtures"
 }
 
 dependencies {
@@ -9,6 +10,7 @@ dependencies {
     implementation project(':rest-oauth-client-commons')
     implementation project(':test-helper-commons')
     implementation project(':lib-security-config-urls')
+    implementation project(':business-module-persistence-commons')
 
     implementation 'org.slf4j:slf4j-api'
     implementation 'org.springframework.boot:spring-boot-autoconfigure'
@@ -20,9 +22,17 @@ dependencies {
     testImplementation project(':base-api')
     testImplementation project(':lib-base-client')
     testImplementation testFixtures(project(':business-module-commons'))
+    testImplementation testFixtures(project(':business-module-persistence-commons'))
     testImplementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
 
     testRuntimeOnly 'org.springframework.boot:spring-boot-starter-web'
+    testRuntimeOnly 'org.postgresql:postgresql'
+
+    testFixturesApi project(':lib-auditlog')
+    testFixturesApi project(':test-commons')
+    testFixturesApi 'de.cronn:validation-file-assertions:latest.release'
+    testFixturesApi 'org.springframework.data:spring-data-jpa'
+    testFixturesImplementation project(':business-module-persistence-commons')
 }
 
 tasks.named("test").configure {
diff --git a/backend/lib-auditlog/gradle.lockfile b/backend/lib-auditlog/gradle.lockfile
index 96976a90e354caeff8d40399881ad0a25bc08bda..67d2f3d65988e4861285dd6f19eca420fc534ab4 100644
--- a/backend/lib-auditlog/gradle.lockfile
+++ b/backend/lib-auditlog/gradle.lockfile
@@ -1,178 +1,212 @@
 # This is a Gradle generated file for dependency locking.
 # Manual edits can break the build and are not advised.
 # This file is expected to be part of source control.
-ch.qos.logback:logback-classic:1.5.12=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-ch.qos.logback:logback-core:1.5.12=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.fasterxml.jackson.core:jackson-annotations:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.fasterxml.jackson.core:jackson-core:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.fasterxml.jackson.core:jackson-databind:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2=testCompileClasspath,testRuntimeClasspath
-com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.fasterxml.jackson.module:jackson-module-parameter-names:2.18.2=testCompileClasspath,testRuntimeClasspath
-com.fasterxml.jackson:jackson-bom:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.fasterxml:classmate:1.7.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.github.curious-odd-man:rgxgen:2.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.github.docker-java:docker-java-api:3.4.0=testCompileClasspath,testRuntimeClasspath
-com.github.docker-java:docker-java-transport-zerodep:3.4.0=testCompileClasspath,testRuntimeClasspath
-com.github.docker-java:docker-java-transport:3.4.0=testCompileClasspath,testRuntimeClasspath
-com.github.gavlyukovskiy:datasource-decorator-spring-boot-autoconfigure:1.10.0=testRuntimeClasspath
-com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.10.0=testRuntimeClasspath
-com.github.stephenc.jcip:jcip-annotations:1.0-1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.google.code.findbugs:jsr305:3.0.2=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-com.google.errorprone:error_prone_annotations:2.28.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-com.google.guava:failureaccess:1.0.2=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-com.google.guava:guava:33.3.1-jre=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-com.google.j2objc:j2objc-annotations:3.0.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-com.googlecode.java-diff-utils:diffutils:1.3.0=testCompileClasspath,testRuntimeClasspath
-com.googlecode.libphonenumber:libphonenumber:8.13.50=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.jayway.jsonpath:json-path:2.9.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.nimbusds:content-type:2.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.nimbusds:lang-tag:1.7=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.nimbusds:nimbus-jose-jwt:9.37.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.nimbusds:oauth2-oidc-sdk:9.43.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-com.tngtech.archunit:archunit-junit5-api:1.3.0=testRuntimeClasspath
-com.tngtech.archunit:archunit-junit5-engine-api:1.3.0=testRuntimeClasspath
-com.tngtech.archunit:archunit-junit5-engine:1.3.0=testRuntimeClasspath
-com.tngtech.archunit:archunit-junit5:1.3.0=testRuntimeClasspath
-com.tngtech.archunit:archunit:1.3.0=testRuntimeClasspath
+ch.qos.logback:logback-classic:1.5.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+ch.qos.logback:logback-core:1.5.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson.core:jackson-annotations:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson.core:jackson-core:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson.core:jackson-databind:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.18.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson.datatype:jackson-datatype-hibernate6:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson.module:jackson-module-parameter-names:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml.jackson:jackson-bom:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.fasterxml:classmate:1.7.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.github.curious-odd-man:rgxgen:2.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.github.docker-java:docker-java-api:3.4.0=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.github.docker-java:docker-java-transport-zerodep:3.4.0=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.github.docker-java:docker-java-transport:3.4.0=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.github.gavlyukovskiy:datasource-decorator-spring-boot-autoconfigure:1.10.0=testFixturesRuntimeClasspath,testRuntimeClasspath
+com.github.gavlyukovskiy:datasource-proxy-spring-boot-starter:1.10.0=testFixturesRuntimeClasspath,testRuntimeClasspath
+com.github.stephenc.jcip:jcip-annotations:1.0-1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.google.code.findbugs:jsr305:3.0.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.google.errorprone:error_prone_annotations:2.28.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.google.guava:failureaccess:1.0.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.google.guava:guava:33.3.1-jre=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.google.j2objc:j2objc-annotations:3.0.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.googlecode.java-diff-utils:diffutils:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.googlecode.libphonenumber:libphonenumber:8.13.50=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.jayway.jsonpath:json-path:2.9.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.nimbusds:content-type:2.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.nimbusds:lang-tag:1.7=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.nimbusds:nimbus-jose-jwt:9.37.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.nimbusds:oauth2-oidc-sdk:9.43.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.opencsv:opencsv:5.9=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.sun.istack:istack-commons-runtime:4.1.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+com.tngtech.archunit:archunit-junit5-api:1.3.0=testFixturesRuntimeClasspath,testRuntimeClasspath
+com.tngtech.archunit:archunit-junit5-engine-api:1.3.0=testFixturesRuntimeClasspath,testRuntimeClasspath
+com.tngtech.archunit:archunit-junit5-engine:1.3.0=testFixturesRuntimeClasspath,testRuntimeClasspath
+com.tngtech.archunit:archunit-junit5:1.3.0=testFixturesRuntimeClasspath,testRuntimeClasspath
+com.tngtech.archunit:archunit:1.3.0=testFixturesRuntimeClasspath,testRuntimeClasspath
 com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath
-commons-io:commons-io:2.18.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-de.cronn:postgres-snapshot-util:1.4=testRuntimeClasspath
-de.cronn:reflection-util:2.17.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-de.cronn:test-utils:1.1.1=testCompileClasspath,testRuntimeClasspath
-de.cronn:validation-file-assertions:0.8.0=testCompileClasspath,testRuntimeClasspath
-io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.micrometer:micrometer-core:1.14.2=testCompileClasspath,testRuntimeClasspath
-io.micrometer:micrometer-jakarta9:1.14.2=testCompileClasspath,testRuntimeClasspath
-io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.micrometer:micrometer-registry-prometheus:1.14.2=testRuntimeClasspath
-io.prometheus:prometheus-metrics-config:1.3.5=testRuntimeClasspath
-io.prometheus:prometheus-metrics-core:1.3.5=testRuntimeClasspath
-io.prometheus:prometheus-metrics-exposition-formats:1.3.5=testRuntimeClasspath
-io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=testRuntimeClasspath
-io.prometheus:prometheus-metrics-model:1.3.5=testRuntimeClasspath
-io.prometheus:prometheus-metrics-tracer-common:1.3.5=testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-jakarta.annotation:jakarta.annotation-api:2.1.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-junit:junit:4.13.2=testCompileClasspath,testRuntimeClasspath
+com.zaxxer:HikariCP:5.1.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+commons-io:commons-io:2.18.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+de.cronn:liquibase-changelog-generator-postgresql:1.0=testCompileClasspath,testRuntimeClasspath
+de.cronn:liquibase-changelog-generator:1.0=testCompileClasspath,testRuntimeClasspath
+de.cronn:liquibase-postgres-enum-extension:1.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+de.cronn:postgres-snapshot-util:1.4=testFixturesRuntimeClasspath,testRuntimeClasspath
+de.cronn:reflection-util:2.17.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+de.cronn:test-utils:1.1.1=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+de.cronn:validation-file-assertions:0.8.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.micrometer:micrometer-core:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.micrometer:micrometer-jakarta9:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.micrometer:micrometer-registry-prometheus:1.14.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.prometheus:prometheus-metrics-config:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.prometheus:prometheus-metrics-core:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.prometheus:prometheus-metrics-exposition-formats:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.smallrye:jandex:3.2.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+jakarta.inject:jakarta.inject-api:2.0.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+jakarta.persistence:jakarta.persistence-api:3.1.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+jakarta.transaction:jakarta.transaction-api:2.0.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+javax.xml.bind:jaxb-api:2.3.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+junit:junit:4.13.2=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 net.bytebuddy:byte-buddy-agent:1.15.11=testCompileClasspath,testRuntimeClasspath
-net.bytebuddy:byte-buddy:1.15.11=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-net.datafaker:datafaker:2.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-net.java.dev.jna:jna:5.13.0=testCompileClasspath,testRuntimeClasspath
-net.minidev:accessors-smart:2.5.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-net.minidev:json-smart:2.5.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-net.ttddyy:datasource-proxy:1.10=testRuntimeClasspath
-org.apache.commons:commons-compress:1.24.0=testCompileClasspath,testRuntimeClasspath
-org.apache.commons:commons-lang3:3.17.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.apache.httpcomponents.client5:httpclient5:5.4.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.apache.httpcomponents.core5:httpcore5-h2:5.3.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.apache.httpcomponents.core5:httpcore5:5.3.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.apache.logging.log4j:log4j-api:2.24.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.apache.logging.log4j:log4j-to-slf4j:2.24.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.apache.tomcat.embed:tomcat-embed-core:10.1.34=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.apache.tomcat.embed:tomcat-embed-el:10.1.34=testCompileClasspath,testRuntimeClasspath
-org.apache.tomcat.embed:tomcat-embed-websocket:10.1.34=testCompileClasspath,testRuntimeClasspath
-org.apache.tomcat:tomcat-annotations-api:10.1.34=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.apiguardian:apiguardian-api:1.1.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
+net.bytebuddy:byte-buddy:1.15.11=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+net.datafaker:datafaker:2.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+net.java.dev.jna:jna:5.13.0=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+net.minidev:accessors-smart:2.5.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+net.minidev:json-smart:2.5.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+net.ttddyy:datasource-proxy:1.10=testFixturesRuntimeClasspath,testRuntimeClasspath
+org.antlr:antlr4-runtime:4.13.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.commons:commons-collections4:4.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.commons:commons-compress:1.24.0=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.commons:commons-lang3:3.17.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.commons:commons-text:1.12.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.httpcomponents.client5:httpclient5:5.4.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.httpcomponents.core5:httpcore5-h2:5.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.httpcomponents.core5:httpcore5:5.3.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.logging.log4j:log4j-api:2.24.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.logging.log4j:log4j-to-slf4j:2.24.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.tomcat.embed:tomcat-embed-core:10.1.34=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.tomcat.embed:tomcat-embed-el:10.1.34=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.tomcat.embed:tomcat-embed-websocket:10.1.34=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apache.tomcat:tomcat-annotations-api:10.1.34=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.apiguardian:apiguardian-api:1.1.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.aspectj:aspectjweaver:1.9.22.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.assertj:assertj-core:3.26.3=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
-org.bouncycastle:bcpkix-jdk18on:1.80=testRuntimeClasspath
-org.bouncycastle:bcprov-jdk18on:1.80=testRuntimeClasspath
-org.bouncycastle:bcutil-jdk18on:1.80=testRuntimeClasspath
-org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testRuntimeClasspath
-org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.hdrhistogram:HdrHistogram:2.2.2=testRuntimeClasspath
-org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
-org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
-org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
+org.bouncycastle:bcpkix-jdk18on:1.80=testFixturesRuntimeClasspath,testRuntimeClasspath
+org.bouncycastle:bcprov-jdk18on:1.80=testFixturesRuntimeClasspath,testRuntimeClasspath
+org.bouncycastle:bcutil-jdk18on:1.80=testFixturesRuntimeClasspath,testRuntimeClasspath
+org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.eclipse.angus:angus-activation:2.0.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.glassfish.jaxb:jaxb-core:4.0.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.glassfish.jaxb:jaxb-runtime:4.0.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.glassfish.jaxb:txw2:4.0.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.hamcrest:hamcrest:2.2=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.hibernate.common:hibernate-commons-annotations:7.0.3.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
+org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.jetbrains:annotations:17.0.0=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter:5.11.4=testCompileClasspath,testRuntimeClasspath
-org.junit.platform:junit-platform-commons:1.11.4=testCompileClasspath,testRuntimeClasspath
-org.junit.platform:junit-platform-engine:1.11.4=testRuntimeClasspath
+org.junit.platform:junit-platform-commons:1.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.junit.platform:junit-platform-engine:1.11.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.platform:junit-platform-launcher:1.11.4=testRuntimeClasspath
-org.junit:junit-bom:5.11.4=testCompileClasspath,testRuntimeClasspath
-org.latencyutils:LatencyUtils:2.0.3=testRuntimeClasspath
+org.junit:junit-bom:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.latencyutils:LatencyUtils:2.0.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.liquibase:liquibase-core:4.29.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
-org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
-org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.postgresql:postgresql:42.7.4=testRuntimeClasspath
-org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
+org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
+org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
+org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
-org.slf4j:jul-to-slf4j:2.0.16=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-actuator:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-dependencies:3.3.5=testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-actuator:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-json:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-logging:3.4.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-oauth2-client:3.4.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-security:3.4.1=testCompileClasspath,testRuntimeClasspath
+org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-dependencies:3.3.5=testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-data-jpa:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-jdbc:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-json:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-logging:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-oauth2-client:3.4.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-security:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-tomcat:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-validation:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter-web:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-starter:3.4.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-tomcat:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-validation:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter-web:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-starter:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-test-autoconfigure:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot-test:3.4.1=testCompileClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot-test:3.4.1=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-testcontainers:3.4.1=testCompileClasspath,testRuntimeClasspath
-org.springframework.boot:spring-boot:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.data:spring-data-commons:3.4.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.springframework.security:spring-security-config:6.4.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.security:spring-security-core:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.security:spring-security-crypto:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.security:spring-security-oauth2-client:6.4.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.security:spring-security-oauth2-core:6.4.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.security:spring-security-oauth2-jose:6.4.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework.security:spring-security-oauth2-resource-server:6.4.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springframework.boot:spring-boot:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.data:spring-data-commons:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.data:spring-data-jpa:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.security:spring-security-config:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.security:spring-security-core:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.security:spring-security-crypto:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.security:spring-security-oauth2-client:6.4.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.security:spring-security-oauth2-core:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.security:spring-security-oauth2-jose:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework.security:spring-security-oauth2-resource-server:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.security:spring-security-test:6.4.2=testCompileClasspath,testRuntimeClasspath
-org.springframework.security:spring-security-web:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-aop:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-beans:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-context:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-core:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-expression:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-jcl:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-test:6.2.1=testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-tx:6.2.1=testRuntimeClasspath
-org.springframework:spring-web:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springframework:spring-webmvc:6.2.1=testCompileClasspath,testRuntimeClasspath
-org.testcontainers:testcontainers:1.20.4=testCompileClasspath,testRuntimeClasspath
+org.springframework.security:spring-security-web:6.4.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-aop:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-aspects:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-beans:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-context:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-core:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-expression:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-jcl:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-jdbc:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-orm:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-test:6.2.1=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-tx:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-web:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springframework:spring-webmvc:6.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.testcontainers:database-commons:1.20.4=testRuntimeClasspath
+org.testcontainers:jdbc:1.20.4=testRuntimeClasspath
+org.testcontainers:postgresql:1.20.4=testRuntimeClasspath
+org.testcontainers:testcontainers:1.20.4=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.xmlunit:xmlunit-core:2.10.0=testCompileClasspath,testRuntimeClasspath
-org.yaml:snakeyaml:2.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.zalando:faux-pas:0.9.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-api:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-common:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-core:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-httpclient5:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-json:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-servlet:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-spring-boot-autoconfigure:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-spring-boot-starter:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.zalando:logbook-spring:3.10.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-empty=annotationProcessor,developmentOnly,testAndDevelopmentOnly,testAnnotationProcessor,testFixturesCompileClasspath,testFixturesRuntimeClasspath
+org.yaml:snakeyaml:2.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:faux-pas:0.9.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-api:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-common:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-core:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-httpclient5:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-json:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-servlet:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-spring-boot-autoconfigure:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-spring-boot-starter:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.zalando:logbook-spring:3.10.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+empty=annotationProcessor,developmentOnly,testAndDevelopmentOnly,testAnnotationProcessor,testFixturesAnnotationProcessor
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogArchiving.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogArchiving.java
index 8ac7613a30c1b9207fce3af4e3472b0b75b0bd93..feca211bfbeff5bbca854a245eca7629a6225b8e 100644
--- a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogArchiving.java
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogArchiving.java
@@ -8,22 +8,23 @@ package de.eshg.lib.auditlog;
 import de.eshg.auditlog.AddAuditLogFileRequest;
 import de.eshg.auditlog.AuditLogArchivingApi;
 import de.eshg.auditlog.AuditLogSource;
-import de.eshg.lib.auditlog.config.AuditLogConfig;
+import de.eshg.lib.auditlog.domain.AuditLogEntry;
+import de.eshg.lib.auditlog.domain.AuditLogEntryRepository;
 import de.eshg.lib.rest.oauth.client.commons.ModuleClientAuthenticator;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
+import de.eshg.rest.service.error.ErrorCode;
+import de.eshg.rest.service.error.ErrorResponse;
+import jakarta.transaction.Transactional;
+import java.nio.charset.StandardCharsets;
 import java.time.Clock;
+import java.time.Instant;
 import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
-import java.util.Comparator;
+import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.stream.Stream;
+import java.util.Map;
+import java.util.stream.Collectors;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
-import org.springframework.util.FileSystemUtils;
+import org.springframework.web.client.HttpClientErrorException.BadRequest;
 
 @Component
 public class AuditLogArchiving {
@@ -32,106 +33,101 @@ public class AuditLogArchiving {
       org.slf4j.LoggerFactory.getLogger(AuditLogArchiving.class);
 
   private final AuditLogArchivingApi auditLogArchivingApi;
-  private final AuditLogConfig auditLogConfig;
   private final AuditLogSource auditLogSource;
-  private final Clock clock;
   private final ModuleClientAuthenticator moduleClientAuthenticator;
+  private final AuditLogEntryRepository auditLogEntryRepository;
+  private final Clock clock;
 
   public AuditLogArchiving(
       AuditLogArchivingApi auditLogArchivingApi,
-      AuditLogConfig auditLogConfig,
       AuditLogSource auditLogSource,
-      Clock clock,
-      ModuleClientAuthenticator moduleClientAuthenticator) {
+      ModuleClientAuthenticator moduleClientAuthenticator,
+      AuditLogEntryRepository auditLogEntryRepository,
+      Clock clock) {
     this.auditLogArchivingApi = auditLogArchivingApi;
-    this.auditLogConfig = auditLogConfig;
     this.auditLogSource = auditLogSource;
-    this.clock = clock;
     this.moduleClientAuthenticator = moduleClientAuthenticator;
+    this.auditLogEntryRepository = auditLogEntryRepository;
+    this.clock = clock;
   }
 
   @Scheduled(cron = "${de.eshg.auditlog.archiving.schedule:@daily}")
+  @Transactional
   public void runArchivingJob() {
     moduleClientAuthenticator.doWithModuleClientAuthentication(this::archiveOldAuditlogFiles);
   }
 
   private void archiveOldAuditlogFiles() {
-    log.info("Starting archiving of old audit log files");
-
-    Path logOutputDir = auditLogConfig.getLogOutputDir();
-    log.debug("Using log output directory {}", logOutputDir);
-
-    List<Path> candidates = getCandidates(logOutputDir);
-
-    if (log.isInfoEnabled()) {
-      List<String> oldAuditLogFilesNames =
-          candidates.stream().map(Path::getFileName).map(Path::toString).toList();
-      log.info(
-          "Found {} audit log directories for archiving {}",
-          candidates.size(),
-          !oldAuditLogFilesNames.isEmpty() ? oldAuditLogFilesNames : "");
-    }
-
-    for (Path candidate : candidates) {
-      archive(candidate);
+    log.info("Starting archiving of old audit log entries");
+
+    Instant todayAtStartOfDay = LocalDate.now(clock).atStartOfDay(clock.getZone()).toInstant();
+    List<AuditLogEntry> toArchive =
+        auditLogEntryRepository.findByCreatedAtBeforeOrderByCreatedAtAscIdAsc(todayAtStartOfDay);
+
+    log.info("Found {} entries created before {}", toArchive.size(), todayAtStartOfDay);
+
+    Map<LocalDate, List<AuditLogEntry>> auditLogEntriesByDate =
+        toArchive.stream()
+            .collect(
+                Collectors.groupingBy(
+                    auditLogEntry ->
+                        LocalDate.ofInstant(auditLogEntry.getCreatedAt(), clock.getZone()),
+                    LinkedHashMap::new,
+                    Collectors.toList()));
+
+    for (LocalDate auditLogDate : auditLogEntriesByDate.keySet()) {
+      try {
+        List<AuditLogEntry> auditLogEntries = auditLogEntriesByDate.get(auditLogDate);
+        log.info("Found {} entries to be archived for {}", auditLogEntries.size(), auditLogDate);
+
+        archiveAuditLog(auditLogDate, auditLogEntries);
+      } catch (Exception e) {
+        log.error("Error while trying to archive audit log for {}.", auditLogDate, e);
+      }
     }
 
-    log.info("Finished archiving of old audit log files");
+    log.info("Finished archiving of old audit logs");
   }
 
-  private List<Path> getCandidates(Path logOutputDir) {
-    try (Stream<Path> paths = Files.list(logOutputDir)) {
-      return paths.filter(Files::isDirectory).filter(this::isOldAuditLogDirectory).toList();
-    } catch (IOException e) {
-      throw new AuditLoggerException("Exception occured while reading auditlog root directory.", e);
-    }
-  }
+  private void archiveAuditLog(LocalDate auditLogDate, List<AuditLogEntry> auditLogEntries) {
+    String content =
+        auditLogEntries.stream().map(AuditLogFormatter::format).collect(Collectors.joining("\n"));
 
-  private boolean isOldAuditLogDirectory(Path path) {
-    try {
-      LocalDate localDate =
-          LocalDate.parse(path.getFileName().toString(), DateTimeFormatter.ISO_LOCAL_DATE);
-      return localDate.isBefore(LocalDate.now(clock));
-    } catch (DateTimeParseException e) {
-      log.error("Failed to parse date from audit log directory name %s".formatted(path), e);
-      return false;
-    }
-  }
+    AuditLogFile auditLogFile =
+        new AuditLogFile(auditLogDate.toString(), content.getBytes(StandardCharsets.UTF_8));
 
-  private void archive(Path auditLogDirectory) {
     try {
-      final LocalDate auditLogDate =
-          LocalDate.parse(
-              auditLogDirectory.getFileName().toString(), DateTimeFormatter.ISO_LOCAL_DATE);
       auditLogArchivingApi.addAuditlogFile(
-          new AddAuditLogFileRequest(auditLogDate, auditLogSource), mergeFiles(auditLogDirectory));
-      log.info("Archived audit log directory for {}", auditLogDate);
-
-      FileSystemUtils.deleteRecursively(auditLogDirectory);
-      log.info("Deleted local audit log directory for {}", auditLogDate);
-    } catch (Exception e) {
-      log.error(
-          "Error while trying to archive audit log directory {}. Resuming...",
-          auditLogDirectory,
-          e);
+          new AddAuditLogFileRequest(auditLogDate, auditLogSource), auditLogFile);
+      log.info("Archived audit logs for {}", auditLogDate);
+
+      deleteAuditLog(auditLogDate, auditLogEntries);
+    } catch (BadRequest exception) {
+      if (isAlreadyExistsError(exception)) {
+        log.error(
+            "Audit log for {} already exists. Performing cleanup...", auditLogDate, exception);
+        deleteAuditLog(auditLogDate, auditLogEntries);
+      } else {
+        throw exception;
+      }
     }
   }
 
-  private static AuditLogFile mergeFiles(Path directory) throws IOException {
-    try (Stream<Path> originalFiles = Files.list(directory);
-        ByteArrayOutputStream mergedFileStream = new ByteArrayOutputStream()) {
-
-      for (Path originalFile : sortedByFilename(originalFiles)) {
-        Files.copy(originalFile, mergedFileStream);
+  private boolean isAlreadyExistsError(BadRequest exception) {
+    try {
+      ErrorResponse errorResponse = exception.getResponseBodyAs(ErrorResponse.class);
+      if (errorResponse != null) {
+        return ErrorCode.ALREADY_EXISTS.equals(errorResponse.errorCode());
       }
-      return new AuditLogFile(directory.getFileName().toString(), mergedFileStream.toByteArray());
+    } catch (Exception e) {
+      return false;
     }
+
+    return false;
   }
 
-  private static List<Path> sortedByFilename(Stream<Path> files) {
-    return files
-        .filter(Files::isRegularFile)
-        .sorted(Comparator.comparing(p -> p.getFileName().toString()))
-        .toList();
+  private void deleteAuditLog(LocalDate auditLogDate, List<AuditLogEntry> auditLogEntries) {
+    auditLogEntryRepository.deleteAll(auditLogEntries);
+    log.info("Deleted {} local audit entries for {}", auditLogEntries.size(), auditLogDate);
   }
 }
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogFormatter.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogFormatter.java
new file mode 100644
index 0000000000000000000000000000000000000000..8271a9daa27c7b89bdc39b9014d7e94bb3f02a7b
--- /dev/null
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogFormatter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.lib.auditlog;
+
+import de.eshg.lib.auditlog.domain.AuditLogEntry;
+import java.util.stream.Collectors;
+
+public final class AuditLogFormatter {
+
+  private AuditLogFormatter() {}
+
+  private static final String TEMPLATE =
+      """
+      Zeitstempel: %s
+      Kategorie: %s
+      Funktion: %s
+      Zusätzliche Attribute: %s
+      """;
+
+  public static String format(AuditLogEntry auditLogEntry) {
+    String formattedAdditionalData =
+        auditLogEntry.getAdditionalData().entrySet().stream()
+            .map(e -> "\t- %s: %s".formatted(e.getKey(), e.getValue()))
+            .collect(Collectors.joining(System.lineSeparator(), System.lineSeparator(), ""));
+
+    return TEMPLATE.formatted(
+        auditLogEntry.getCreatedAt(),
+        auditLogEntry.getCategory(),
+        auditLogEntry.getFunction(),
+        !formattedAdditionalData.isBlank() ? formattedAdditionalData : "-");
+  }
+}
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogTestHelperService.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogTestHelperService.java
index 49c66ff1d14e65bb793b86ad06952f46fc00ac60..d9fd9738cbfdca5f6ad06ac65430d87e15fed8bc 100644
--- a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogTestHelperService.java
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogTestHelperService.java
@@ -5,48 +5,27 @@
 
 package de.eshg.lib.auditlog;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
-import de.eshg.lib.auditlog.config.AuditLogConfig;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.testhelper.ConditionalOnTestHelperEnabled;
 import de.eshg.testhelper.environment.EnvironmentConfig;
-import java.io.IOException;
-import java.nio.file.Files;
-import org.apache.commons.io.FileUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 @ConditionalOnTestHelperEnabled
 @Service
-public class AuditLogTestHelperService implements SharedAuditLogTestHelperApi {
-
-  private static final Logger log = LoggerFactory.getLogger(AuditLogTestHelperService.class);
+public class AuditLogTestHelperService implements AuditLogClientTestHelperApi {
 
   private final AuditLogArchiving auditLogArchiving;
-  private final AuditLogConfig auditLogConfig;
   private final EnvironmentConfig environmentConfig;
 
   public AuditLogTestHelperService(
-      AuditLogArchiving auditLogArchiving,
-      AuditLogConfig auditLogConfig,
-      EnvironmentConfig environmentConfig) {
+      AuditLogArchiving auditLogArchiving, EnvironmentConfig environmentConfig) {
     environmentConfig.assertIsNotProduction();
     this.auditLogArchiving = auditLogArchiving;
-    this.auditLogConfig = auditLogConfig;
     this.environmentConfig = environmentConfig;
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    environmentConfig.assertIsNotProduction();
-    log.info("Clearing audit log storage directory");
-    if (Files.exists(auditLogConfig.getLogOutputDir())) {
-      FileUtils.cleanDirectory(auditLogConfig.getLogOutputDir().toFile());
-    }
-  }
-
-  @Override
-  public void runArchivingJob() {
+  public void runAuditLogArchivingJob() {
     environmentConfig.assertIsNotProduction();
     auditLogArchiving.runArchivingJob();
   }
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogger.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogger.java
index 99663e4e22c3d4d02e059b683248a4cce0a21a70..df852ccc9f1d770f53d24aacd2853484e88a1615 100644
--- a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogger.java
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/AuditLogger.java
@@ -5,75 +5,28 @@
 
 package de.eshg.lib.auditlog;
 
-import de.eshg.lib.auditlog.config.AuditLogConfig;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.time.Clock;
-import java.time.Instant;
-import java.time.LocalDate;
+import de.eshg.lib.auditlog.domain.AuditLogEntry;
+import de.eshg.lib.auditlog.domain.AuditLogEntryRepository;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.stream.Collectors;
+import java.util.TreeMap;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 
 @Component
-public final class AuditLogger {
+public class AuditLogger {
 
-  private static final String MESSAGE_TEMPLATE =
-      """
-      Zeitstempel: %s
-      Kategorie: %s
-      Funktion: %s
-      Zusätzliche Attribute: %s
-      """;
+  private final AuditLogEntryRepository auditLogEntryRepository;
 
-  private final Path outputDirPath;
-  private final Clock clock;
-  private final UuidProvider uuidProvider;
-
-  AuditLogger(AuditLogConfig auditLogConfig, Clock clock, UuidProvider uuidProvider) {
-    this.outputDirPath = auditLogConfig.getLogOutputDir();
-    this.clock = clock;
-    this.uuidProvider = uuidProvider;
+  AuditLogger(AuditLogEntryRepository auditLogEntryRepository) {
+    this.auditLogEntryRepository = auditLogEntryRepository;
   }
 
+  @Transactional
   public void log(String category, String function, Map<String, String> additionalData) {
-    String formattedAdditionalData =
-        additionalData.entrySet().stream()
-            .sorted(Entry.comparingByKey())
-            .map(e -> "\t- %s: %s".formatted(e.getKey(), e.getValue()))
-            .collect(Collectors.joining(System.lineSeparator(), System.lineSeparator(), ""));
-
-    final Instant now = clock.instant();
-
-    String message =
-        MESSAGE_TEMPLATE.formatted(
-            now,
-            category,
-            function,
-            !formattedAdditionalData.isBlank() ? formattedAdditionalData : "-");
-
-    try {
-      Files.writeString(
-          getLogFilePath(now),
-          message + System.lineSeparator(),
-          StandardCharsets.UTF_8,
-          StandardOpenOption.CREATE,
-          StandardOpenOption.APPEND);
-    } catch (IOException e) {
-      throw new AuditLoggerException("Exception occurred while trying to write to audit log", e);
-    }
-  }
-
-  private Path getLogFilePath(Instant now) throws IOException {
-    final Path auditLogDateBasedDirectory =
-        outputDirPath.resolve(AuditLogHelper.getAuditLogFileName(LocalDate.now(clock)));
-    Files.createDirectories(auditLogDateBasedDirectory); // create directory if it does not exist
-    return auditLogDateBasedDirectory.resolve(
-        String.format(
-            "%012d%09d-%s", now.getEpochSecond(), now.getNano(), uuidProvider.nextUuid()));
+    AuditLogEntry auditLogEntry = new AuditLogEntry();
+    auditLogEntry.setCategory(category);
+    auditLogEntry.setFunction(function);
+    auditLogEntry.setAdditionalData(new TreeMap<>(additionalData));
+    auditLogEntryRepository.save(auditLogEntry);
   }
 }
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/config/AuditLogConfig.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/config/AuditLogConfig.java
index abdcf6d92daa69f6e55367a25e8079b0a9bdde92..a4eb5aad4deb8a2990ef05e13c1108eb1c9aa20b 100644
--- a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/config/AuditLogConfig.java
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/config/AuditLogConfig.java
@@ -6,24 +6,16 @@
 package de.eshg.lib.auditlog.config;
 
 import jakarta.validation.constraints.NotNull;
-import java.nio.file.Files;
-import java.nio.file.Path;
 import org.hibernate.validator.constraints.URL;
 import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.util.Assert;
 import org.springframework.validation.annotation.Validated;
 
 @Validated
 @ConfigurationProperties(prefix = "de.eshg.auditlog")
 public class AuditLogConfig {
 
-  @NotNull private Path logOutputDir;
   @NotNull @URL private String serviceUrl;
 
-  public Path getLogOutputDir() {
-    return logOutputDir;
-  }
-
   public String getServiceUrl() {
     return serviceUrl;
   }
@@ -31,14 +23,4 @@ public class AuditLogConfig {
   public void setServiceUrl(String serviceUrl) {
     this.serviceUrl = serviceUrl;
   }
-
-  public void setLogOutputDir(Path logOutputDir) {
-    if (Files.exists(logOutputDir)) {
-      Assert.isTrue(
-          Files.isDirectory(logOutputDir), "log output dir must be a directory:" + logOutputDir);
-      Assert.isTrue(
-          Files.isWritable(logOutputDir), "log output dir must be writable:" + logOutputDir);
-    }
-    this.logOutputDir = logOutputDir;
-  }
 }
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/domain/AuditLogEntry.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/domain/AuditLogEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..ceaa0098c5666def57e50f8e29cf474514f10e0d
--- /dev/null
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/domain/AuditLogEntry.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.lib.auditlog.domain;
+
+import de.eshg.domain.model.SequencedBaseEntity;
+import de.eshg.lib.common.DataSensitivity;
+import de.eshg.lib.common.SensitivityLevel;
+import jakarta.persistence.Column;
+import jakarta.persistence.ElementCollection;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.NamedAttributeNode;
+import jakarta.persistence.NamedEntityGraph;
+import jakarta.persistence.OrderBy;
+import java.time.Instant;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+@Entity
+@EntityListeners(AuditingEntityListener.class)
+@NamedEntityGraph(
+    name = "AuditLogEntry.additionalData",
+    attributeNodes = @NamedAttributeNode("additionalData"))
+public class AuditLogEntry extends SequencedBaseEntity {
+
+  @CreatedDate
+  @Column(nullable = false)
+  @DataSensitivity(value = SensitivityLevel.PUBLIC)
+  private Instant createdAt;
+
+  @Column(nullable = false)
+  @DataSensitivity(value = SensitivityLevel.PUBLIC)
+  private String category;
+
+  @Column(nullable = false)
+  @DataSensitivity(value = SensitivityLevel.PUBLIC)
+  private String function;
+
+  @DataSensitivity(value = SensitivityLevel.SENSITIVE)
+  @ElementCollection
+  @OrderBy("additional_data_key ASC")
+  private Map<String, String> additionalData = new LinkedHashMap<>();
+
+  public Instant getCreatedAt() {
+    return createdAt;
+  }
+
+  public void setCreatedAt(Instant createdAt) {
+    this.createdAt = createdAt;
+  }
+
+  public String getCategory() {
+    return category;
+  }
+
+  public void setCategory(String category) {
+    this.category = category;
+  }
+
+  public String getFunction() {
+    return function;
+  }
+
+  public void setFunction(String function) {
+    this.function = function;
+  }
+
+  public Map<String, String> getAdditionalData() {
+    return additionalData;
+  }
+
+  public void setAdditionalData(Map<String, String> additionalData) {
+    this.additionalData = additionalData;
+  }
+}
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/domain/AuditLogEntryRepository.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/domain/AuditLogEntryRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc5cd5d7a9f762b5414c54c22a432968f1434723
--- /dev/null
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/domain/AuditLogEntryRepository.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.lib.auditlog.domain;
+
+import java.time.Instant;
+import java.util.List;
+import org.springframework.data.jpa.repository.EntityGraph;
+import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface AuditLogEntryRepository extends JpaRepository<AuditLogEntry, Long> {
+  @EntityGraph(value = "AuditLogEntry.additionalData", type = EntityGraphType.LOAD)
+  List<AuditLogEntry> findByCreatedAtBeforeOrderByCreatedAtAscIdAsc(Instant createdAt);
+}
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/spring/AuditLogAutoConfiguration.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/spring/AuditLogAutoConfiguration.java
index 0d581269a0f0315c03cb20ecb1d839afed73eb2f..aecec2a6effcfde6bbaae2f1f924789ada60657d 100644
--- a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/spring/AuditLogAutoConfiguration.java
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/spring/AuditLogAutoConfiguration.java
@@ -15,6 +15,8 @@ import de.eshg.lib.auditlog.config.AuditLogConfig;
 import de.eshg.rest.client.BearerAuthInterceptor;
 import de.eshg.rest.client.CorrelationIdForwardingInterceptor;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Import;
@@ -26,6 +28,7 @@ import org.springframework.web.service.invoker.HttpServiceProxyFactory;
 
 @AutoConfiguration
 @PropertySource("classpath:/auditlog-default.properties")
+@AutoConfigureAfter(JpaRepositoriesAutoConfiguration.class)
 @EnableConfigurationProperties(AuditLogConfig.class)
 @Import(
     value = {
diff --git a/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/spring/AuditLogLibraryDomainModelAutoConfiguration.java b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/spring/AuditLogLibraryDomainModelAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..41f19500e923bec76a4891d96fab72a024cf81fd
--- /dev/null
+++ b/backend/lib-auditlog/src/main/java/de/eshg/lib/auditlog/spring/AuditLogLibraryDomainModelAutoConfiguration.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.lib.auditlog.spring;
+
+import de.eshg.lib.auditlog.domain.AuditLogEntry;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
+import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration;
+
+@AutoConfiguration(before = JpaRepositoriesAutoConfiguration.class)
+@AutoConfigurationPackage(basePackageClasses = {AuditLogEntry.class})
+public class AuditLogLibraryDomainModelAutoConfiguration {}
diff --git a/backend/lib-auditlog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/backend/lib-auditlog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index f2df03b324d235fba602614962f45378d93fee68..8a48bd070cce99a33747bb20565e648053887a9e 100644
--- a/backend/lib-auditlog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/backend/lib-auditlog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1 +1,2 @@
 de.eshg.lib.auditlog.spring.AuditLogAutoConfiguration
+de.eshg.lib.auditlog.spring.AuditLogLibraryDomainModelAutoConfiguration
diff --git a/backend/lib-auditlog/src/main/resources/auditlog-default.properties b/backend/lib-auditlog/src/main/resources/auditlog-default.properties
index 1923ec8950bcb3609ce1d13824dcab588885d7af..f39ca32dbdc4c16ff92f42ac3a2c894bce5bcc2c 100644
--- a/backend/lib-auditlog/src/main/resources/auditlog-default.properties
+++ b/backend/lib-auditlog/src/main/resources/auditlog-default.properties
@@ -1,2 +1 @@
-de.eshg.auditlog.log-output-dir=${java.io.tmpdir}/auditlog
 de.eshg.auditlog.service-url=http://${DOCKER_HOSTNAME:localhost}:8094
diff --git a/backend/lib-base-client/gradle.lockfile b/backend/lib-base-client/gradle.lockfile
index 641b20f4d516e3118e620c5d3f7c3ecacf104b3f..a883e63e7431f2689f2817068ad32f93a5d9c22b 100644
--- a/backend/lib-base-client/gradle.lockfile
+++ b/backend/lib-base-client/gradle.lockfile
@@ -25,10 +25,10 @@ de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeCla
 de.cronn:reflection-util:2.17.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -51,10 +51,10 @@ org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -67,13 +67,14 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-calendar-api/gradle.lockfile b/backend/lib-calendar-api/gradle.lockfile
index ee716303e0142020d46d8452e822f8593dfd2ad1..6efa88853b723be73cfb4e703fa15872b40fa660 100644
--- a/backend/lib-calendar-api/gradle.lockfile
+++ b/backend/lib-calendar-api/gradle.lockfile
@@ -10,8 +10,8 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -26,10 +26,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -42,9 +42,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-calendar/gradle.lockfile b/backend/lib-calendar/gradle.lockfile
index 2a6adce6bfc95064607e3c03f8647d6c9b431335..a1752af8da4770f723d1cfa65db990024837d2e9 100644
--- a/backend/lib-calendar/gradle.lockfile
+++ b/backend/lib-calendar/gradle.lockfile
@@ -16,8 +16,8 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -33,10 +33,10 @@ org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -49,9 +49,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-central-repository-api/gradle.lockfile b/backend/lib-central-repository-api/gradle.lockfile
index d83e09eb8f12336dcd6049c085aecd0ba6098262..2e040c44f8d80d584bb6f9198fbedb8e080c0301 100644
--- a/backend/lib-central-repository-api/gradle.lockfile
+++ b/backend/lib-central-repository-api/gradle.lockfile
@@ -14,10 +14,10 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.servlet:jakarta.servlet-api:6.0.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -34,10 +34,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -50,13 +50,14 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-central-repository-client/gradle.lockfile b/backend/lib-central-repository-client/gradle.lockfile
index f8c0bd7fa3fcd325edda1427e1753a0f51d4b034..185dc9a71c80a8a7f69923c991b41608c9be2dc4 100644
--- a/backend/lib-central-repository-client/gradle.lockfile
+++ b/backend/lib-central-repository-client/gradle.lockfile
@@ -17,10 +17,10 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.servlet:jakarta.servlet-api:6.0.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -40,10 +40,10 @@ org.apiguardian:apiguardian-api:1.1.2=productionRuntimeClasspath,runtimeClasspat
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -56,13 +56,14 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-commons/gradle.lockfile b/backend/lib-commons/gradle.lockfile
index 099bd7b423bf44acf2fae0c3aec2496f5920dd45..fc7b2018a096da76f11ed5c995687aecdfabda87 100644
--- a/backend/lib-commons/gradle.lockfile
+++ b/backend/lib-commons/gradle.lockfile
@@ -8,7 +8,7 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=testCompileClasspath,testRuntimeClasspath
@@ -22,10 +22,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -38,9 +38,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-contact-api/gradle.lockfile b/backend/lib-contact-api/gradle.lockfile
index f7af9e94fd2830ba8c91f01f42aa78daf4970cac..da1f0d31c882eb0013b2658258605ac601e9a55f 100644
--- a/backend/lib-contact-api/gradle.lockfile
+++ b/backend/lib-contact-api/gradle.lockfile
@@ -9,7 +9,7 @@ com.jayway.jsonpath:json-path:2.9.0=testCompileClasspath,testRuntimeClasspath
 com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -24,10 +24,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -40,9 +40,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-contact/gradle.lockfile b/backend/lib-contact/gradle.lockfile
index 5c5583ece120621dfbe79758121a8a0411d5ab6e..48e5e580ca667be752527bafcbfaac6675bb572a 100644
--- a/backend/lib-contact/gradle.lockfile
+++ b/backend/lib-contact/gradle.lockfile
@@ -52,10 +52,10 @@ io.prometheus:prometheus-metrics-exposition-formats:1.3.5=productionRuntimeClass
 io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -90,10 +90,10 @@ org.hamcrest:hamcrest-core:2.2=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -109,15 +109,16 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
diff --git a/backend/lib-document-generator/gradle.lockfile b/backend/lib-document-generator/gradle.lockfile
index 85d59527f9eceece43f56f9e433553ce5b2ba17e..d11aa8df164026526114bdab8cb703344b68925b 100644
--- a/backend/lib-document-generator/gradle.lockfile
+++ b/backend/lib-document-generator/gradle.lockfile
@@ -28,10 +28,10 @@ io.github.openhtmltopdf:openhtmltopdf-slf4j:1.1.24=compileClasspath,productionRu
 io.github.openhtmltopdf:openhtmltopdf-svg-support:1.1.24=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -77,10 +77,10 @@ org.glassfish.jaxb:jaxb-core:4.0.5=testFixturesCompileClasspath,testFixturesRunt
 org.glassfish.jaxb:jaxb-runtime:4.0.5=testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.glassfish.jaxb:txw2:4.0.5=testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -94,13 +94,14 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.mozilla:rhino:1.7.13=testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-editor-api/gradle.lockfile b/backend/lib-editor-api/gradle.lockfile
index bb22010b53a0e81f84e4b5160f6f4cfb2ee45d66..d925e834b86343a5fdc2b0fca281b444ae9c9660 100644
--- a/backend/lib-editor-api/gradle.lockfile
+++ b/backend/lib-editor-api/gradle.lockfile
@@ -13,9 +13,9 @@ com.jayway.jsonpath:json-path:2.9.0=testCompileClasspath,testRuntimeClasspath
 com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -31,10 +31,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -47,13 +47,14 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-editor/gradle.lockfile b/backend/lib-editor/gradle.lockfile
index 25daf372f4d3b687f5c74717b907f99d54f8a596..78c0789217fec7591e0c84be99a6e460aa0e5d63 100644
--- a/backend/lib-editor/gradle.lockfile
+++ b/backend/lib-editor/gradle.lockfile
@@ -52,10 +52,10 @@ io.prometheus:prometheus-metrics-exposition-formats:1.3.5=productionRuntimeClass
 io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.persistence:jakarta.persistence-api:3.1.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -93,10 +93,10 @@ org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -113,16 +113,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-four-eyes-principle-api/gradle.lockfile b/backend/lib-four-eyes-principle-api/gradle.lockfile
index 76b87c3eff62475d07c6742acdf9500446c55c6b..77ac307ea762d83c1180438c5ce0194486dec04c 100644
--- a/backend/lib-four-eyes-principle-api/gradle.lockfile
+++ b/backend/lib-four-eyes-principle-api/gradle.lockfile
@@ -14,10 +14,10 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -33,10 +33,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -49,13 +49,14 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-four-eyes-principle/build.gradle b/backend/lib-four-eyes-principle/build.gradle
index 486c2808ff074f8c0b97886dabe1ee5dafd5e76e..adfd918b71be48f41389b9c18094511f1284a2dc 100644
--- a/backend/lib-four-eyes-principle/build.gradle
+++ b/backend/lib-four-eyes-principle/build.gradle
@@ -20,6 +20,7 @@ dependencies {
 
     testImplementation project(':test-commons')
     testImplementation testFixtures(project(':business-module-persistence-commons'))
+    testImplementation testFixtures(project(':lib-auditlog'))
     testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa'
     testRuntimeOnly 'org.postgresql:postgresql'
     testRuntimeOnly 'com.h2database:h2'
diff --git a/backend/lib-four-eyes-principle/gradle.lockfile b/backend/lib-four-eyes-principle/gradle.lockfile
index 38a9d38fa7ac925357c594fd0a0c9f441a3217de..6b0be86d0196bf7f07d169023c4dbbdab0f37afa 100644
--- a/backend/lib-four-eyes-principle/gradle.lockfile
+++ b/backend/lib-four-eyes-principle/gradle.lockfile
@@ -64,10 +64,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -118,10 +118,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -139,16 +139,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-keycloak/gradle.lockfile b/backend/lib-keycloak/gradle.lockfile
index 7d9f7ecc724928376643b70c65ce557598282f5b..41f00f17ef4df971f636979403037f112012cc27 100644
--- a/backend/lib-keycloak/gradle.lockfile
+++ b/backend/lib-keycloak/gradle.lockfile
@@ -28,10 +28,10 @@ org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -44,9 +44,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-keycloak/src/main/java/de/eshg/lib/keycloak/EmployeePermissionRole.java b/backend/lib-keycloak/src/main/java/de/eshg/lib/keycloak/EmployeePermissionRole.java
index 22a2ad98d0a3c1079f66255e1671decd816cfef1..60b325c9ea3e41e9f63de7bfa3f5e35024bbd2c6 100644
--- a/backend/lib-keycloak/src/main/java/de/eshg/lib/keycloak/EmployeePermissionRole.java
+++ b/backend/lib-keycloak/src/main/java/de/eshg/lib/keycloak/EmployeePermissionRole.java
@@ -339,6 +339,7 @@ public enum EmployeePermissionRole implements PermissionRole {
       BASE_PERSONS_WRITE,
       BASE_FACILITIES_READ,
       BASE_FACILITIES_WRITE,
+      BASE_ACCESS_CODE_USER_ADMIN,
       BASE_CALENDAR_BUSINESS_EVENTS_WRITE);
 
   private final String keycloakNameWithoutPrefix;
diff --git a/backend/lib-keycloak/src/main/java/de/eshg/lib/keycloak/EmployeeTestUser.java b/backend/lib-keycloak/src/main/java/de/eshg/lib/keycloak/EmployeeTestUser.java
index c62976212ed95b4751ec7d9002aa638ddc6807c2..017ff1d0fd87c48f67f2f6e7945343304f0efb47 100644
--- a/backend/lib-keycloak/src/main/java/de/eshg/lib/keycloak/EmployeeTestUser.java
+++ b/backend/lib-keycloak/src/main/java/de/eshg/lib/keycloak/EmployeeTestUser.java
@@ -231,7 +231,21 @@ public enum EmployeeTestUser implements KeycloakUser {
       "password",
       "Thomas",
       "Müller",
-      List.of(ModuleMemberGroup.DENTAL, ModuleLeaderGroup.DENTAL));
+      List.of(ModuleMemberGroup.DENTAL, ModuleLeaderGroup.DENTAL)),
+  STI_PROTECTION_DUMMY(
+      "sti_protection_dummy_user",
+      "+49 555 123 470",
+      "password",
+      "Klaus",
+      "Klausen",
+      List.of(ModuleMemberGroup.STI_PROTECTION)),
+  STI_PROTECTION_MODULE_LEADER(
+      "sti_protection_module_leader",
+      "+49 555 123 471",
+      "password",
+      "Max",
+      "Power",
+      List.of(ModuleMemberGroup.STI_PROTECTION, ModuleLeaderGroup.STI_PROTECTION));
 
   private final String username;
   private final String email;
diff --git a/backend/lib-lsd-api/gradle.lockfile b/backend/lib-lsd-api/gradle.lockfile
index 36580e3b61c18acec186b6ca20ee67129e8cb4ef..93e405e8689e3d9062d28f9a1641882ddea1ef50 100644
--- a/backend/lib-lsd-api/gradle.lockfile
+++ b/backend/lib-lsd-api/gradle.lockfile
@@ -54,9 +54,9 @@ de.cronn:test-utils:1.1.1=testFixturesCompileClasspath,testFixturesRuntimeClassp
 de.cronn:validation-file-assertions:0.8.0=testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.quarkus:quarkus-junit4-mock:3.17.7=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.quarkus:quarkus-junit4-mock:3.18.0=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.mail:jakarta.mail-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -98,10 +98,10 @@ org.glassfish.jaxb:txw2:4.0.5=compileClasspath,productionRuntimeClasspath,runtim
 org.glassfish.jaxb:xsom:4.0.5=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:commons-logging-jboss-logging:1.0.0.Final=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.jboss.resteasy:resteasy-client-api:6.2.9.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -131,9 +131,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.reactivestreams:reactive-streams:1.0.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
diff --git a/backend/lib-mutex/gradle.lockfile b/backend/lib-mutex/gradle.lockfile
index 50cfd1c5cd2c3b72ed9a39e104560efc72f4c680..2846446dd9d95d0b950012f431aea5646ac9152e 100644
--- a/backend/lib-mutex/gradle.lockfile
+++ b/backend/lib-mutex/gradle.lockfile
@@ -60,10 +60,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -113,10 +113,10 @@ org.hibernate.common:hibernate-commons-annotations:7.0.3.Final=productionRuntime
 org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -134,16 +134,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-notification-api/gradle.lockfile b/backend/lib-notification-api/gradle.lockfile
index ba60e82d953a18ca47ff41080e26a4d3a2a40ce0..8ffb1bdb3d8d570c709fc7eb9f33c3a7ba46e3fa 100644
--- a/backend/lib-notification-api/gradle.lockfile
+++ b/backend/lib-notification-api/gradle.lockfile
@@ -14,10 +14,10 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -33,10 +33,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -49,13 +49,14 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-notification/gradle.lockfile b/backend/lib-notification/gradle.lockfile
index 9b313d57a9cc9e8ac0d0ea1b93fc3d42a101edb1..0bfd4105058ab9f0ec06d8453ff9ef88b394613c 100644
--- a/backend/lib-notification/gradle.lockfile
+++ b/backend/lib-notification/gradle.lockfile
@@ -61,10 +61,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -115,10 +115,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -136,16 +136,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-procedures-api/gradle.lockfile b/backend/lib-procedures-api/gradle.lockfile
index fe9793307055e53c08e1b7dbbc88e3558a5851bc..a72a94f12204e142e382839551e4e7c9c9386b43 100644
--- a/backend/lib-procedures-api/gradle.lockfile
+++ b/backend/lib-procedures-api/gradle.lockfile
@@ -15,10 +15,10 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -34,10 +34,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -51,13 +51,14 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-logging:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-starter-test:3.4.1=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-procedures/build.gradle b/backend/lib-procedures/build.gradle
index b0de9ac9fcc919df9fd6ebb5d68ab5d077b33f8e..a1262af5c34f87a63c99c01d520cb6052d05304a 100644
--- a/backend/lib-procedures/build.gradle
+++ b/backend/lib-procedures/build.gradle
@@ -52,6 +52,7 @@ dependencies {
 
     testImplementation testFixtures(project(':business-module-persistence-commons'))
     testImplementation testFixtures(project(':base-api'))
+    testImplementation testFixtures(project(':lib-auditlog'))
     testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa'
     testImplementation 'org.instancio:instancio-core:latest.release'
     testImplementation 'org.apache.commons:commons-text:latest.release'
diff --git a/backend/lib-procedures/gradle.lockfile b/backend/lib-procedures/gradle.lockfile
index 9fd43ce784344924e75fc51a66d3250f9f5966c3..7fc4bc1bee3d8ace632ecb9afd0b4d6bf3db18a6 100644
--- a/backend/lib-procedures/gradle.lockfile
+++ b/backend/lib-procedures/gradle.lockfile
@@ -74,10 +74,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath,xjc
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -145,11 +145,11 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.instancio:instancio-core:5.2.1=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.instancio:instancio-core:5.3.0=testCompileClasspath,testRuntimeClasspath
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -168,16 +168,17 @@ org.mozilla:rhino:1.7.13=compileClasspath,productionRuntimeClasspath,runtimeClas
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
diff --git a/backend/lib-procedures/src/main/java/de/eshg/lib/procedure/gdpr/GdprValidationTaskController.java b/backend/lib-procedures/src/main/java/de/eshg/lib/procedure/gdpr/GdprValidationTaskController.java
index 7af9f3a5632e672468e7829a9853d6a52e2d92da..b5b425695b6a3b5b3d644921f87ee15c237197e6 100644
--- a/backend/lib-procedures/src/main/java/de/eshg/lib/procedure/gdpr/GdprValidationTaskController.java
+++ b/backend/lib-procedures/src/main/java/de/eshg/lib/procedure/gdpr/GdprValidationTaskController.java
@@ -41,6 +41,7 @@ import de.eshg.lib.procedure.procedures.ProcedureDeletionService;
 import de.eshg.rest.service.error.BadRequestException;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import java.nio.charset.StandardCharsets;
+import java.time.Period;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -240,7 +241,7 @@ public class GdprValidationTaskController<
   }
 
   @Override
-  @Transactional(readOnly = true)
+  @Transactional
   public GetGdprValidationTaskDetailsResponse getGdprValidationTaskDetails(UUID gdprId) {
     assertNewFeatureEnabled(BaseFeature.GDPR, baseFeatureTogglesApi.getFeatureToggles());
     List<UUID> fileStateIds = service.getAndValidateFileStateIds(gdprId);
@@ -304,7 +305,7 @@ public class GdprValidationTaskController<
     service.writeAuditLog(
         "Löschung Fachmodul Vorgang", mapAuditlog(validationTask, businessProcedure.get()));
 
-    procedureDeletionService.deleteAndWriteToCemetery(businessProcedure.get());
+    procedureDeletionService.deleteAndWriteToCemetery(businessProcedure.get(), Period.ZERO);
   }
 
   @Override
diff --git a/backend/lib-procedures/src/main/java/de/eshg/lib/procedure/procedures/ProcedureQuery.java b/backend/lib-procedures/src/main/java/de/eshg/lib/procedure/procedures/ProcedureQuery.java
index d1d12752d7bfeb68b3bd76cecc665f283ef38649..340cd53e500d77ac1da902c518ce2777193682bd 100644
--- a/backend/lib-procedures/src/main/java/de/eshg/lib/procedure/procedures/ProcedureQuery.java
+++ b/backend/lib-procedures/src/main/java/de/eshg/lib/procedure/procedures/ProcedureQuery.java
@@ -5,9 +5,12 @@
 
 package de.eshg.lib.procedure.procedures;
 
+import de.eshg.lib.procedure.domain.model.FacilityType;
 import de.eshg.lib.procedure.domain.model.PersonType;
 import de.eshg.lib.procedure.domain.model.Procedure;
 import de.eshg.lib.procedure.domain.model.Procedure_;
+import de.eshg.lib.procedure.domain.model.RelatedFacility;
+import de.eshg.lib.procedure.domain.model.RelatedFacility_;
 import de.eshg.lib.procedure.domain.model.RelatedPerson;
 import de.eshg.lib.procedure.domain.model.RelatedPerson_;
 import jakarta.persistence.EntityManager;
@@ -52,4 +55,29 @@ public class ProcedureQuery {
 
     return entityManager.createQuery(query).getResultList();
   }
+
+  public <
+          ProcedureT extends Procedure<ProcedureT, ?, ?, RelatedFacilityT>,
+          RelatedFacilityT extends RelatedFacility<ProcedureT>>
+      List<UUID> findAllRelatedFacilityFileStateIds(
+          Specification<ProcedureT> procedureSpecification,
+          Class<ProcedureT> procedureClass,
+          FacilityType facilityType) {
+    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+    CriteriaQuery<UUID> query = criteriaBuilder.createQuery(UUID.class);
+    Root<ProcedureT> root = query.from(procedureClass);
+
+    Join<ProcedureT, ? extends RelatedFacility<?>> relatedFacilitiesJoin =
+        root.join(Procedure_.relatedFacilities);
+    Join<ProcedureT, ? extends RelatedFacility<?>> childJoin =
+        relatedFacilitiesJoin.on(
+            criteriaBuilder.equal(
+                relatedFacilitiesJoin.get(RelatedFacility_.facilityType), facilityType));
+
+    query.select(childJoin.get(RelatedFacility_.centralFileStateId));
+
+    query.where(procedureSpecification.toPredicate(root, query, criteriaBuilder));
+
+    return entityManager.createQuery(query).getResultList();
+  }
 }
diff --git a/backend/lib-relay/gradle.lockfile b/backend/lib-relay/gradle.lockfile
index 34b364c102ddf72a33af8f6ee380f1e53ea0bc73..aa68aa2db061caf252d7f60e30c2e9775d95d71e 100644
--- a/backend/lib-relay/gradle.lockfile
+++ b/backend/lib-relay/gradle.lockfile
@@ -33,8 +33,8 @@ de.cronn:test-utils:1.1.1=testCompileClasspath,testFixturesCompileClasspath,test
 de.cronn:validation-file-assertions:0.8.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -59,10 +59,10 @@ org.bouncycastle:bcutil-jdk18on:1.80=testFixturesRuntimeClasspath,testRuntimeCla
 org.checkerframework:checker-qual:3.43.0=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
@@ -76,9 +76,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-scheduling/gradle.lockfile b/backend/lib-scheduling/gradle.lockfile
index 5e35ee6ad671c40e21cf5300b34085411fa80d9d..ed7627ab54def74ed68b05fdc52edc14dd722c9e 100644
--- a/backend/lib-scheduling/gradle.lockfile
+++ b/backend/lib-scheduling/gradle.lockfile
@@ -8,7 +8,7 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.persistence:jakarta.persistence-api:3.1.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -26,10 +26,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -42,9 +42,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-security-config-urls/gradle.lockfile b/backend/lib-security-config-urls/gradle.lockfile
index e1de784a1f2d3bbc73fbb37623b8688c015ee47e..205a9bf9ba3e7ed6cf8eda70609b6b6220bdab63 100644
--- a/backend/lib-security-config-urls/gradle.lockfile
+++ b/backend/lib-security-config-urls/gradle.lockfile
@@ -20,10 +20,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -36,9 +36,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-security-config-urls/src/main/java/de/eshg/rest/service/security/config/BaseUrls.java b/backend/lib-security-config-urls/src/main/java/de/eshg/rest/service/security/config/BaseUrls.java
index 47b639ac97fa885df0f1298e418133c7930ee4d5..a0e009a9c2140e73f5cd7d2bed26936348eff0eb 100644
--- a/backend/lib-security-config-urls/src/main/java/de/eshg/rest/service/security/config/BaseUrls.java
+++ b/backend/lib-security-config-urls/src/main/java/de/eshg/rest/service/security/config/BaseUrls.java
@@ -67,6 +67,7 @@ public final class BaseUrls {
 
     public static final class Gdpr {
       public static final String DOWNLOADS = "/{id}/downloads";
+      public static final String DELETE_DOWNLOADS = "/{id}/delete-downloads";
       public static final String FILE_STATE_IDS = "/{id}/fileStateIds";
       public static final String BY_ID = "/{id}";
       public static final String DETAILS_PAGE = "/{id}/details-page";
@@ -162,6 +163,7 @@ public final class BaseUrls {
 
   public static final class StiProtection {
     public static final String PROCEDURE_CONTROLLER = "/sti-procedures";
+    public static final String CITIZEN_PUBLIC_CONTROLLER = "/citizen/public";
 
     private StiProtection() {}
   }
diff --git a/backend/lib-security-config/gradle.lockfile b/backend/lib-security-config/gradle.lockfile
index 2022b4696d11d1c09007249d43b05829e5b9e095..4dd6164ab4f1908c376b9f6ab4071a3242cd0bd1 100644
--- a/backend/lib-security-config/gradle.lockfile
+++ b/backend/lib-security-config/gradle.lockfile
@@ -33,8 +33,8 @@ de.cronn:test-utils:1.1.1=testCompileClasspath,testRuntimeClasspath
 de.cronn:validation-file-assertions:0.8.0=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=testCompileClasspath,testRuntimeClasspath
@@ -59,12 +59,12 @@ org.bouncycastle:bcutil-jdk18on:1.80=testRuntimeClasspath
 org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest-core:2.2=testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jetbrains:annotations:17.0.0=testRuntimeClasspath
-org.jetbrains:annotations:26.0.1=compileClasspath
+org.jetbrains:annotations:26.0.2=compileClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -77,9 +77,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-security-config/src/main/java/de/eshg/rest/service/security/config/StiProtectionPublicSecurityConfig.java b/backend/lib-security-config/src/main/java/de/eshg/rest/service/security/config/StiProtectionPublicSecurityConfig.java
index 3130379204db364cc4503b00f33993afa2f9aa26..6fdf4e181de42c1267641fa895157672dcf81f4c 100644
--- a/backend/lib-security-config/src/main/java/de/eshg/rest/service/security/config/StiProtectionPublicSecurityConfig.java
+++ b/backend/lib-security-config/src/main/java/de/eshg/rest/service/security/config/StiProtectionPublicSecurityConfig.java
@@ -20,6 +20,8 @@ public final class StiProtectionPublicSecurityConfig extends AbstractPublicSecur
     grantAccessToLibProceduresUrls(
         EmployeePermissionRole.STI_PROTECTION_USER, ModuleLeaderRole.STI_PROTECTION_LEADER);
 
+    requestMatchers(BaseUrls.StiProtection.CITIZEN_PUBLIC_CONTROLLER + "/**").permitAll();
+
     requestMatchers(GET, BaseUrls.StiProtection.PROCEDURE_CONTROLLER + "/{id}/**")
         .hasAnyRole(
             EmployeePermissionRole.STI_PROTECTION_USER, EmployeePermissionRole.PROCEDURE_ARCHIVE);
diff --git a/backend/lib-service-directory-admin-api/gradle.lockfile b/backend/lib-service-directory-admin-api/gradle.lockfile
index 13e7961a685072e44409c22b2316db90a98749c6..4aaabed7687925404fb2fb0785e82858a4a0cf1a 100644
--- a/backend/lib-service-directory-admin-api/gradle.lockfile
+++ b/backend/lib-service-directory-admin-api/gradle.lockfile
@@ -33,8 +33,8 @@ de.cronn:test-utils:1.1.1=testFixturesCompileClasspath,testFixturesRuntimeClassp
 de.cronn:validation-file-assertions:0.8.0=testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -59,10 +59,10 @@ org.bouncycastle:bcutil-jdk18on:1.80=testFixturesRuntimeClasspath,testRuntimeCla
 org.checkerframework:checker-qual:3.43.0=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
@@ -76,9 +76,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-service-directory-api/gradle.lockfile b/backend/lib-service-directory-api/gradle.lockfile
index 2f34a9bbd303ac0cf4905f871d3eceb5b617397c..bca9a5c42ddffd0526e2a0d44eba7ef6722d7a68 100644
--- a/backend/lib-service-directory-api/gradle.lockfile
+++ b/backend/lib-service-directory-api/gradle.lockfile
@@ -16,8 +16,8 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -33,10 +33,10 @@ org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -49,9 +49,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-statistics-api/gradle.lockfile b/backend/lib-statistics-api/gradle.lockfile
index f7af9e94fd2830ba8c91f01f42aa78daf4970cac..da1f0d31c882eb0013b2658258605ac601e9a55f 100644
--- a/backend/lib-statistics-api/gradle.lockfile
+++ b/backend/lib-statistics-api/gradle.lockfile
@@ -9,7 +9,7 @@ com.jayway.jsonpath:json-path:2.9.0=testCompileClasspath,testRuntimeClasspath
 com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -24,10 +24,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -40,9 +40,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-statistics-api/src/main/java/de/eshg/lib/statistics/api/Attribute.java b/backend/lib-statistics-api/src/main/java/de/eshg/lib/statistics/api/Attribute.java
index bd24d08ba067859581829b6a570eaabc5bc754fa..7793d69ea517fc6220793b4a9d1e6d2d96a2b3c5 100644
--- a/backend/lib-statistics-api/src/main/java/de/eshg/lib/statistics/api/Attribute.java
+++ b/backend/lib-statistics-api/src/main/java/de/eshg/lib/statistics/api/Attribute.java
@@ -18,4 +18,5 @@ public record Attribute(
     String unit,
     @Size(min = 1) @Valid List<ValueOptionInternal> valueOptions,
     @NotBlank String category,
-    @NotNull boolean mandatory) {}
+    @NotNull boolean mandatory,
+    DataPrivacyCategory dataPrivacyCategory) {}
diff --git a/backend/lib-statistics-api/src/main/java/de/eshg/lib/statistics/api/DataPrivacyCategory.java b/backend/lib-statistics-api/src/main/java/de/eshg/lib/statistics/api/DataPrivacyCategory.java
new file mode 100644
index 0000000000000000000000000000000000000000..51705ff9559b7ca407807ab77093c88881250e05
--- /dev/null
+++ b/backend/lib-statistics-api/src/main/java/de/eshg/lib/statistics/api/DataPrivacyCategory.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.lib.statistics.api;
+
+public enum DataPrivacyCategory {
+  QUASI_IDENTIFYING,
+  SENSITIVE,
+  INSENSITIVE
+}
diff --git a/backend/lib-statistics/README.md b/backend/lib-statistics/README.md
index c9e0b808d6557ed6bd7338d02d3f8a87ef01e70a..162965c4742702e0739e6fe3f6edde77a76e3130 100644
--- a/backend/lib-statistics/README.md
+++ b/backend/lib-statistics/README.md
@@ -48,7 +48,7 @@ Based on the available data sources the user will select the wanted statistics d
 the corresponding `AttributeInfo`. `null` is also a valid value.
 
 * BOOLEAN: java.lang.Boolean (or boolean)
-* DATE: java.lang.String in the format yyyy-MMM-dd as returned by java.time.LocalDate.toString()
+* DATE: java.lang.String in the format yyyy-MM-dd as returned by java.time.LocalDate.toString()
 * DECIMAL: java.lang.Double (or double) - precision = 10, scale = 4 can be handled
 * INTEGER: java.lang.Integer (or int)
 * TEXT: java.lang.String, blank strings will be stored as null
diff --git a/backend/lib-statistics/gradle.lockfile b/backend/lib-statistics/gradle.lockfile
index 35b809823f51628cc423fb5288461947b8385096..b0116d8995b4698efeca860a969dfd7ade6b356f 100644
--- a/backend/lib-statistics/gradle.lockfile
+++ b/backend/lib-statistics/gradle.lockfile
@@ -69,10 +69,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -141,10 +141,10 @@ org.hibernate.common:hibernate-commons-annotations:7.0.3.Final=productionRuntime
 org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -163,16 +163,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testFixture
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
diff --git a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/StatisticsService.java b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/StatisticsService.java
index fcddd54ab5deae09b7a8581bb92778d856be77b0..e342c7702141e078ca079f4ea0f346b1bd0e5df0 100644
--- a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/StatisticsService.java
+++ b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/StatisticsService.java
@@ -71,7 +71,8 @@ public class StatisticsService {
         attribute.getUnit(),
         attribute.getValueOptions(),
         attribute.getCategory(),
-        attribute.isMandatory());
+        attribute.isMandatory(),
+        attribute.getDataPrivacyCategory());
   }
 
   private static ValueType mapToValueType(AttributeData attribute) {
diff --git a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/AttributeData.java b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/AttributeData.java
index d57b12ac1effd0b34c05367a93a1f161f4ebb21e..06e4543bee78ac9985705d6bda090b0d837c1cee 100644
--- a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/AttributeData.java
+++ b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/AttributeData.java
@@ -5,6 +5,7 @@
 
 package de.eshg.lib.statistics.attributes;
 
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import de.eshg.lib.statistics.api.ValueOptionInternal;
 import java.util.List;
 
@@ -25,6 +26,11 @@ public abstract sealed class AttributeData
   private final List<ValueOptionInternal> valueOptions;
   private final String category;
   private final boolean mandatory;
+  private final DataPrivacyCategory dataPrivacyCategory;
+
+  protected AttributeData(String name, String code, String category, boolean mandatory) {
+    this(name, code, null, null, category, mandatory);
+  }
 
   protected AttributeData(
       String name,
@@ -33,7 +39,7 @@ public abstract sealed class AttributeData
       ValueOptionInternal valueOption,
       String category,
       boolean mandatory) {
-    this(name, code, unit, toList(valueOption), category, mandatory);
+    this(name, code, unit, toList(valueOption), category, mandatory, null);
   }
 
   protected AttributeData(
@@ -41,12 +47,18 @@ public abstract sealed class AttributeData
       String code,
       ValueOptionInternal valueOption,
       String category,
-      boolean mandatory) {
-    this(name, code, null, toList(valueOption), category, mandatory);
+      boolean mandatory,
+      DataPrivacyCategory dataPrivacyCategory) {
+    this(name, code, null, toList(valueOption), category, mandatory, dataPrivacyCategory);
   }
 
-  protected AttributeData(String name, String code, String category, boolean mandatory) {
-    this(name, code, null, (ValueOptionInternal) null, category, mandatory);
+  protected AttributeData(
+      String name,
+      String code,
+      ValueOptionInternal valueOption,
+      String category,
+      boolean mandatory) {
+    this(name, code, null, toList(valueOption), category, mandatory, null);
   }
 
   protected AttributeData(
@@ -55,13 +67,15 @@ public abstract sealed class AttributeData
       String unit,
       List<ValueOptionInternal> valueOptions,
       String category,
-      boolean mandatory) {
+      boolean mandatory,
+      DataPrivacyCategory dataPrivacyCategory) {
     this.name = name;
     this.code = code;
     this.unit = unit;
     this.valueOptions = valueOptions;
     this.category = category;
     this.mandatory = mandatory;
+    this.dataPrivacyCategory = dataPrivacyCategory;
   }
 
   private static List<ValueOptionInternal> toList(ValueOptionInternal valueOption) {
@@ -94,4 +108,8 @@ public abstract sealed class AttributeData
   public boolean isMandatory() {
     return mandatory;
   }
+
+  public DataPrivacyCategory getDataPrivacyCategory() {
+    return dataPrivacyCategory;
+  }
 }
diff --git a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/ProcedureAttribute.java b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/ProcedureAttribute.java
index 3636f53cef70f2216d3410aebc997e86a9189e65..20d183a49ef331a6192488688c8b2e1cece82af6 100644
--- a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/ProcedureAttribute.java
+++ b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/ProcedureAttribute.java
@@ -5,8 +5,10 @@
 
 package de.eshg.lib.statistics.attributes;
 
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
+
 public final class ProcedureAttribute extends AttributeData {
   public ProcedureAttribute(String name, String category, boolean mandatory) {
-    super(name, "PROCEDURE_REFERENCE", category, mandatory);
+    super(name, "PROCEDURE_REFERENCE", null, category, mandatory, DataPrivacyCategory.INSENSITIVE);
   }
 }
diff --git a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/TextAttribute.java b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/TextAttribute.java
index eb6f391d509cb59ea5a5a00ec43946332aa68185..115e59084249c5cec6ebd5ee87401da7ef3b1147 100644
--- a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/TextAttribute.java
+++ b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/TextAttribute.java
@@ -5,11 +5,21 @@
 
 package de.eshg.lib.statistics.attributes;
 
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import de.eshg.lib.statistics.api.ValueOptionInternal;
 
 public final class TextAttribute extends AttributeData {
   public TextAttribute(String name, String code, String category, boolean mandatory) {
-    this(name, code, null, category, mandatory);
+    this(name, code, null, category, mandatory, null);
+  }
+
+  public TextAttribute(
+      String name,
+      String code,
+      String category,
+      boolean mandatory,
+      DataPrivacyCategory dataPrivacyCategory) {
+    this(name, code, null, category, mandatory, dataPrivacyCategory);
   }
 
   public TextAttribute(
@@ -17,7 +27,8 @@ public final class TextAttribute extends AttributeData {
       String code,
       ValueOptionInternal valueOption,
       String category,
-      boolean mandatory) {
-    super(name, code, valueOption, category, mandatory);
+      boolean mandatory,
+      DataPrivacyCategory dataPrivacyCategory) {
+    super(name, code, valueOption, category, mandatory, dataPrivacyCategory);
   }
 }
diff --git a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/ValueWithOptionsAttribute.java b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/ValueWithOptionsAttribute.java
index a6f384095d15b3b8c28f7544fbfc12379a4c5d10..7107402d16f305b524136ee9b68aa86a9ba1d5b9 100644
--- a/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/ValueWithOptionsAttribute.java
+++ b/backend/lib-statistics/src/main/java/de/eshg/lib/statistics/attributes/ValueWithOptionsAttribute.java
@@ -15,6 +15,6 @@ public final class ValueWithOptionsAttribute extends AttributeData {
       List<ValueOptionInternal> valueOptions,
       String category,
       boolean mandatory) {
-    super(name, code, null, valueOptions, category, mandatory);
+    super(name, code, null, valueOptions, category, mandatory, null);
   }
 }
diff --git a/backend/lib-xdomea/gradle.lockfile b/backend/lib-xdomea/gradle.lockfile
index 181c64b343fe37db8e4777b328e919c98246aa3f..8926b49613d742b069b9f662d75917172ded22a5 100644
--- a/backend/lib-xdomea/gradle.lockfile
+++ b/backend/lib-xdomea/gradle.lockfile
@@ -32,10 +32,10 @@ org.glassfish.jaxb:jaxb-xjc:4.0.5=xjc
 org.glassfish.jaxb:txw2:4.0.5=xjc
 org.glassfish.jaxb:xsom:4.0.5=xjc
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -48,9 +48,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/lib-xlsx-import/gradle.lockfile b/backend/lib-xlsx-import/gradle.lockfile
index 3d945effcd088340a8f8c6baea039da5cf4e01ee..5898d672de6eeb50da161dc3cc51a3756a24ae16 100644
--- a/backend/lib-xlsx-import/gradle.lockfile
+++ b/backend/lib-xlsx-import/gradle.lockfile
@@ -56,10 +56,10 @@ io.prometheus:prometheus-metrics-exposition-formats:1.3.5=testRuntimeClasspath
 io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.3.5=testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.mail:jakarta.mail-api:2.1.3=testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -108,10 +108,10 @@ org.hamcrest:hamcrest-core:2.2=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
@@ -128,15 +128,16 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testFixturesRuntimeClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testFixturesRuntimeClasspath,testRuntimeClasspath
diff --git a/backend/lib-xlsx-import/src/main/java/de/eshg/lib/xlsximport/RowReader.java b/backend/lib-xlsx-import/src/main/java/de/eshg/lib/xlsximport/RowReader.java
index 57fd51c31ea793e365ffb5b926b52f438ea78964..b3c7070985f960dac14a0f793547afedad74b166 100644
--- a/backend/lib-xlsx-import/src/main/java/de/eshg/lib/xlsximport/RowReader.java
+++ b/backend/lib-xlsx-import/src/main/java/de/eshg/lib/xlsximport/RowReader.java
@@ -10,36 +10,48 @@ import de.eshg.base.SalutationDto;
 import de.eshg.lib.common.CountryCode;
 import de.eshg.lib.xlsximport.model.AddressData;
 import de.eshg.lib.xlsximport.util.XlsxUtil;
+import java.time.Clock;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.Arrays;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.UUID;
+import java.util.function.Function;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
 import org.apache.poi.ss.usermodel.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.util.StringUtils;
 
 public abstract class RowReader<R extends RowData<R>, C extends XlsxColumn> {
 
+  private static final Logger log = LoggerFactory.getLogger(RowReader.class);
+
   private static final DataFormatter DATA_FORMATTER = new DataFormatter();
 
   private final List<C> actualColumns;
-  private final CellStyle errorCellStyle;
+  private final Map<CellStyle, CellStyle> errorCellStyles = new LinkedHashMap<>();
   private final Drawing<?> drawing;
   private final CreationHelper factory;
   private final Supplier<R> resultRowSupplier;
+  private final Clock clock;
+  private final Function<CellStyle, CellStyle> createErrorCellStyle;
 
-  protected RowReader(Sheet sheet, List<C> actualColumns, Supplier<R> resultRowSupplier) {
+  protected RowReader(
+      Sheet sheet, List<C> actualColumns, Supplier<R> resultRowSupplier, Clock clock) {
     Workbook workbook = sheet.getWorkbook();
 
     this.actualColumns = actualColumns;
-    this.errorCellStyle = createErrorStyle(workbook);
     this.drawing = sheet.createDrawingPatriarch();
     this.factory = workbook.getCreationHelper();
     this.resultRowSupplier = resultRowSupplier;
+    this.clock = clock;
+    this.createErrorCellStyle = cellStyle -> createErrorCellStyle(cellStyle, workbook);
   }
 
   public R readRow(Row xlsxRow) {
@@ -95,17 +107,19 @@ public abstract class RowReader<R extends RowData<R>, C extends XlsxColumn> {
   }
 
   protected void addCellError(Cell cell, String errorMessage) {
+    CellStyle errorCellStyle =
+        errorCellStyles.computeIfAbsent(cell.getCellStyle(), createErrorCellStyle);
     cell.setCellStyle(errorCellStyle);
     if (cell.getCellComment() == null) {
       cell.setCellComment(createComment(cell, errorMessage));
     }
   }
 
-  private CellStyle createErrorStyle(Workbook workbook) {
+  private CellStyle createErrorCellStyle(CellStyle cellStyle, Workbook workbook) {
     CellStyle errorStyle = workbook.createCellStyle();
+    errorStyle.cloneStyleFrom(cellStyle);
     errorStyle.setFillForegroundColor(XlsxUtil.newColor(255, 215, 215));
     errorStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
-
     return errorStyle;
   }
 
@@ -267,13 +281,40 @@ public abstract class RowReader<R extends RowData<R>, C extends XlsxColumn> {
     return true;
   }
 
+  protected LocalDate cellAsDateOfBirth(
+      ColumnAccessor<C> col, C column, ErrorHandler errorHandler) {
+    Cell cell = col.get(column);
+    LocalDate dateOfBirth = cellAsDate(cell, errorHandler);
+    if (dateOfBirth != null) {
+      validateDateOfBirth(cell, dateOfBirth, errorHandler);
+    }
+    return dateOfBirth;
+  }
+
+  private void validateDateOfBirth(Cell cell, LocalDate dateOfBirth, ErrorHandler errorHandler) {
+    LocalDate today = LocalDate.now(clock);
+    LocalDate minDateOfBirth = today.minusYears(150);
+    LocalDate maxDateOfBirth = today.plusYears(1);
+    if (dateOfBirth.isBefore(minDateOfBirth) || dateOfBirth.isAfter(maxDateOfBirth)) {
+      log.debug(
+          "Date of birth {} is outside the valid range: {} - {}",
+          dateOfBirth,
+          minDateOfBirth,
+          maxDateOfBirth);
+      errorHandler.handleError(cell, "Ungültiges Geburtsdatum");
+    }
+  }
+
   protected LocalDate cellAsDate(ColumnAccessor<C> col, C column, ErrorHandler errorHandler) {
     return cellAsDate(col.get(column), errorHandler);
   }
 
   public static LocalDate cellAsDate(Cell cell, ErrorHandler errorHandler) {
     LocalDateTime localDateTime = cellAsDateTime(cell, errorHandler);
-    return localDateTime != null ? localDateTime.toLocalDate() : null;
+    if (localDateTime == null) {
+      return null;
+    }
+    return localDateTime.toLocalDate();
   }
 
   protected LocalDateTime cellAsDateTime(
diff --git a/backend/local-service-directory/gradle.lockfile b/backend/local-service-directory/gradle.lockfile
index b5129525daf217ccb87e0c8fc5bcc22a01796f4d..6dd02d202e4be0d0cf0fc99be210a1e9b8c9257d 100644
--- a/backend/local-service-directory/gradle.lockfile
+++ b/backend/local-service-directory/gradle.lockfile
@@ -64,10 +64,10 @@ io.prometheus:prometheus-metrics-exposition-formats:1.3.5=productionRuntimeClass
 io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.mail:jakarta.mail-api:2.1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -120,10 +120,10 @@ org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:commons-logging-jboss-logging:1.0.0.Final=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jboss.resteasy:resteasy-client-api:6.2.9.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -151,17 +151,18 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.reactivestreams:reactive-streams:1.0.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/logging-commons/gradle.lockfile b/backend/logging-commons/gradle.lockfile
index e1de784a1f2d3bbc73fbb37623b8688c015ee47e..205a9bf9ba3e7ed6cf8eda70609b6b6220bdab63 100644
--- a/backend/logging-commons/gradle.lockfile
+++ b/backend/logging-commons/gradle.lockfile
@@ -20,10 +20,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -36,9 +36,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/measles-protection/build.gradle b/backend/measles-protection/build.gradle
index ffee8193bb3e271d0eb627572b80120a70f53450..8d31bb87238b74d3757f581aa07e7930f5a9e24e 100644
--- a/backend/measles-protection/build.gradle
+++ b/backend/measles-protection/build.gradle
@@ -23,6 +23,7 @@ dependencies {
     testImplementation testFixtures(project(':business-module-persistence-commons'))
     testImplementation testFixtures(project(':lib-document-generator'))
     testImplementation testFixtures(project(':lib-procedures'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 }
 
 dockerCompose {
diff --git a/backend/measles-protection/gradle.lockfile b/backend/measles-protection/gradle.lockfile
index 38ff6ee8cbe737531c5bbd6e578aace06c58c950..89edbacc475035ce593d8559971d3d782445a0b0 100644
--- a/backend/measles-protection/gradle.lockfile
+++ b/backend/measles-protection/gradle.lockfile
@@ -75,10 +75,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -169,10 +169,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -191,16 +191,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/measles-protection/openApi.json b/backend/measles-protection/openApi.json
index 9ea20e99d3f82674e93f1158ffef1959d866dd25..fe5c93144a61e7aee235faf042af836d7a7341f7 100644
--- a/backend/measles-protection/openApi.json
+++ b/backend/measles-protection/openApi.json
@@ -3348,18 +3348,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
-        "responses" : {
-          "200" : {
-            "description" : "OK"
-          }
-        },
-        "tags" : [ "TestHelper" ]
-      }
-    },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -4166,9 +4155,9 @@
             "format" : "uuid"
           },
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
@@ -7445,9 +7434,9 @@
         "type" : "object",
         "properties" : {
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
diff --git a/backend/measles-protection/src/main/java/de/eshg/measlesprotection/testhelper/ProtectionProcedureTestHelperController.java b/backend/measles-protection/src/main/java/de/eshg/measlesprotection/testhelper/ProtectionProcedureTestHelperController.java
index fe07287a3ed91efff384eb4772f4e25db9a8ee96..bcde5f4e1ac5535d21a478a9cdc7e9972d5082b6 100644
--- a/backend/measles-protection/src/main/java/de/eshg/measlesprotection/testhelper/ProtectionProcedureTestHelperController.java
+++ b/backend/measles-protection/src/main/java/de/eshg/measlesprotection/testhelper/ProtectionProcedureTestHelperController.java
@@ -5,7 +5,7 @@
 
 package de.eshg.measlesprotection.testhelper;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.lib.auditlog.AuditLogTestHelperService;
 import de.eshg.measlesprotection.api.MeaslesProtectionProcedurePopulationResult;
 import de.eshg.measlesprotection.api.draft.OpenProcedureResponse;
@@ -17,7 +17,6 @@ import de.eshg.testhelper.api.PopulationRequest;
 import de.eshg.testhelper.environment.EnvironmentConfig;
 import de.eshg.testhelper.population.ListWithTotalNumber;
 import jakarta.validation.Valid;
-import java.io.IOException;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
@@ -26,7 +25,7 @@ import org.springframework.web.service.annotation.PostExchange;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class ProtectionProcedureTestHelperController extends TestHelperController
-    implements SharedAuditLogTestHelperApi {
+    implements AuditLogClientTestHelperApi {
 
   private final ProtectionProcedurePopulator populator;
   private final AuditLogTestHelperService auditLogTestHelperService;
@@ -60,12 +59,7 @@ public class ProtectionProcedureTestHelperController extends TestHelperControlle
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
-  }
-
-  @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 }
diff --git a/backend/measles-protection/src/main/resources/migrations/0046_add_auditlog_entry.xml b/backend/measles-protection/src/main/resources/migrations/0046_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..28652f29b57ec0315a42976d18deee225ec7f99e
--- /dev/null
+++ b/backend/measles-protection/src/main/resources/migrations/0046_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/measles-protection/src/main/resources/migrations/0047_convert_duration_columns_to_interval.xml b/backend/measles-protection/src/main/resources/migrations/0047_convert_duration_columns_to_interval.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b823d445751a347a9bd4f46b15ce1307647cc
--- /dev/null
+++ b/backend/measles-protection/src/main/resources/migrations/0047_convert_duration_columns_to_interval.xml
@@ -0,0 +1,30 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="use_interval_for_durations">
+    <sql>
+      ALTER TABLE appointment_type_config
+      ALTER COLUMN standard_duration_in_minutes TYPE interval second(6)
+      USING (standard_duration_in_minutes * INTERVAL '1 minute');
+    </sql>
+    <renameColumn tableName="appointment_type_config"
+                  oldColumnName="standard_duration_in_minutes"
+                  newColumnName="standard_duration"/>
+
+    <sql>
+      ALTER TABLE appointment_block_group
+      ALTER COLUMN slot_duration_in_minutes TYPE interval second(6)
+      USING (slot_duration_in_minutes * INTERVAL '1 minute');
+    </sql>
+    <renameColumn tableName="appointment_block_group"
+                  oldColumnName="slot_duration_in_minutes"
+                  newColumnName="slot_duration"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/measles-protection/src/main/resources/migrations/changelog.xml b/backend/measles-protection/src/main/resources/migrations/changelog.xml
index e99690d0be44647fb35f8908a9518d747645b8be..df3deeecf28713814751020b6b6765edc0f8b7a7 100644
--- a/backend/measles-protection/src/main/resources/migrations/changelog.xml
+++ b/backend/measles-protection/src/main/resources/migrations/changelog.xml
@@ -53,5 +53,7 @@
   <include file="migrations/0043_make_appointment_block_users_non_nullable.xml"/>
   <include file="migrations/0044_add_cemetery_delete_at.xml"/>
   <include file="migrations/0045_add_previous_file_state_id_to_system_progress_entry.xml"/>
+  <include file="migrations/0046_add_auditlog_entry.xml"/>
+  <include file="migrations/0047_convert_duration_columns_to_interval.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/medical-registry/build.gradle b/backend/medical-registry/build.gradle
index 56c79dc08257bab7178987f2a1c3d7cb06e036f3..550e09cd221c374740be8215d95fadecaadb3e63 100644
--- a/backend/medical-registry/build.gradle
+++ b/backend/medical-registry/build.gradle
@@ -22,6 +22,7 @@ dependencies {
     testImplementation testFixtures(project(':business-module-persistence-commons'))
     testImplementation testFixtures(project(':lib-procedures'))
     testImplementation testFixtures(project(':lib-xlsx-import'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 }
 
 dockerCompose {
diff --git a/backend/medical-registry/gradle.lockfile b/backend/medical-registry/gradle.lockfile
index 1f90bae6a0794b3b83ae2d54bbcc7bc6da3fc6ba..ddf6f487af6e2cd25b6b8deead13f247479eaec8 100644
--- a/backend/medical-registry/gradle.lockfile
+++ b/backend/medical-registry/gradle.lockfile
@@ -71,10 +71,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -146,10 +146,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -168,16 +168,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/medical-registry/openApi.json b/backend/medical-registry/openApi.json
index 3a88f01e48740905391486818032224be97700ec..0ea7433fb2636d2274b8704bc5aaaa9f5c5339d0 100644
--- a/backend/medical-registry/openApi.json
+++ b/backend/medical-registry/openApi.json
@@ -2523,18 +2523,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
-        "responses" : {
-          "200" : {
-            "description" : "OK"
-          }
-        },
-        "tags" : [ "TestHelper" ]
-      }
-    },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/MedicalRegistryController.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/MedicalRegistryController.java
index 0dc823d3af415d172de75826926fb3247bcafcc8..f13638eafe4039ff7d2d851b17b28833f7ae7c37 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/MedicalRegistryController.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/MedicalRegistryController.java
@@ -347,7 +347,7 @@ public class MedicalRegistryController {
   }
 
   @GetMapping("/{procedureId}")
-  @Transactional(readOnly = true)
+  @Transactional
   @Operation(summary = "Get medical registry procedure by id.")
   public GetProcedureResponse getProcedure(@PathVariable("procedureId") UUID procedureId) {
     MedicalRegistryProcedure medicalRegistryProcedure =
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/MedicalRegistryImportController.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/MedicalRegistryImportController.java
index db3fb971ce84e91c62fec8fa1e147a1679a081f6..234bdaf1c340d810533b4fd6f6fd6f3b56443f68 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/MedicalRegistryImportController.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/MedicalRegistryImportController.java
@@ -82,7 +82,7 @@ public class MedicalRegistryImportController {
             (sheet, actualColumns) -> {
               MedicalRegistryImporter importer =
                   new MedicalRegistryImporter(
-                      sheet, actualColumns, medicalRegistryService, IMPORTER_BATCH_SIZE);
+                      sheet, actualColumns, medicalRegistryService, clock, IMPORTER_BATCH_SIZE);
               return importer.process();
             });
     log.info(
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/PersonService.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/PersonService.java
index bc078aeac10517e2109bb0a0334dabdc886c6c5e..73b297e77e1a133e1291dc1e472f0a8bf77d5193 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/PersonService.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/PersonService.java
@@ -15,7 +15,6 @@ import de.eshg.base.centralfile.api.person.ExternalAddPersonFileStateRequest;
 import de.eshg.base.centralfile.api.person.GetPersonFileStateResponse;
 import de.eshg.base.centralfile.api.person.GetPersonFileStatesRequest;
 import de.eshg.base.centralfile.api.person.PersonDetails;
-import de.eshg.base.centralfile.api.person.PersonDetailsDto;
 import de.eshg.base.centralfile.api.person.UpdatePersonRequest;
 import de.eshg.base.centralfile.api.person.UpdateReferencePersonRequest;
 import de.eshg.lib.procedure.MapperHelper;
@@ -130,7 +129,7 @@ public class PersonService {
 
     return personApi
         .updatePersonFileStateAndReference(
-            personFileState.id(), new UpdatePersonRequest(new PersonDetailsDto(personFileState)))
+            personFileState.id(), new UpdatePersonRequest(personFileState))
         .id();
   }
 
@@ -153,8 +152,9 @@ public class PersonService {
     return updatedFileState.id();
   }
 
-  private PersonDetailsDto enrich(PersonDetails newPersonDetails, PersonDetails oldPersonDetails) {
-    return new PersonDetailsDto(
+  private UpdatePersonRequest enrich(
+      PersonDetails newPersonDetails, PersonDetails oldPersonDetails) {
+    return new UpdatePersonRequest(
         EnrichmentHelper.enrich(PersonDetails::title, newPersonDetails, oldPersonDetails),
         EnrichmentHelper.enrich(PersonDetails::salutation, newPersonDetails, oldPersonDetails),
         EnrichmentHelper.enrich(PersonDetails::gender, newPersonDetails, oldPersonDetails),
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/ApplicantDto.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/ApplicantDto.java
index c4e8176631f89507dd8d00c9a8c772989121b8d6..b1d06e2977938c04ac3b9c9aa88f5633c572cccd 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/ApplicantDto.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/ApplicantDto.java
@@ -5,9 +5,9 @@
 
 package de.eshg.medicalregistry.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotEmpty;
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/CreateApplicantDto.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/CreateApplicantDto.java
index de27df8f1dcfefcb5a92a9dcef3dfa70733b1df9..c1e3faaa13915a2061c7855e32de9b606d923fcb 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/CreateApplicantDto.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/CreateApplicantDto.java
@@ -5,9 +5,9 @@
 
 package de.eshg.medicalregistry.api;
 
-import de.eshg.CustomValidations.EmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.EmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/CreatePracticeDto.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/CreatePracticeDto.java
index da2e4f6787f8cc16ff277967673b87f2b20638c7..d90c0fa3b5f3d6df5b7a0b9d3d95eeabbeeeafc5 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/CreatePracticeDto.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/CreatePracticeDto.java
@@ -5,7 +5,7 @@
 
 package de.eshg.medicalregistry.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/PracticeDto.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/PracticeDto.java
index e69597d4f9766f5b8889d304647b007b7b907b42..e61865296427cb24b6f5268f4199662ef9ab7c04 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/PracticeDto.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/PracticeDto.java
@@ -5,7 +5,7 @@
 
 package de.eshg.medicalregistry.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotEmpty;
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/PracticeReferenceFacilityDto.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/PracticeReferenceFacilityDto.java
index 68a71180b7ed2887fc418ddb11c6c331a7b0e5c4..d340e3e496830156c358c718bc854337b6380126 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/PracticeReferenceFacilityDto.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/PracticeReferenceFacilityDto.java
@@ -5,10 +5,10 @@
 
 package de.eshg.medicalregistry.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.facility.FacilityContactPersonDto;
 import de.eshg.base.centralfile.api.facility.FacilityDetails;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/ProfessionalReferencePersonDto.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/ProfessionalReferencePersonDto.java
index 569df5e160fd1c19bc228c0a36d891de4d3377cd..6f7ad22dd8b31205d448c7e4d26b6c77fff718c4 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/ProfessionalReferencePersonDto.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/api/ProfessionalReferencePersonDto.java
@@ -5,12 +5,12 @@
 
 package de.eshg.medicalregistry.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.person.PersonDetails;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/importer/MedicalRegistryImporter.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/importer/MedicalRegistryImporter.java
index e1b56915f10168c0866bf3d09d03a27166b95028..104078f4edcac947ba2ee55758a494ccddce4a49 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/importer/MedicalRegistryImporter.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/importer/MedicalRegistryImporter.java
@@ -10,6 +10,7 @@ import de.eshg.lib.xlsximport.ImportStatus;
 import de.eshg.lib.xlsximport.Importer;
 import de.eshg.lib.xlsximport.RowData;
 import de.eshg.medicalregistry.MedicalRegistryService;
+import java.time.Clock;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
@@ -28,8 +29,12 @@ public class MedicalRegistryImporter extends Importer<MedicalRegistryRow, Medica
       XSSFSheet sheet,
       List<MedicalRegistryColumn> actualColumns,
       MedicalRegistryService medicalRegistryService,
+      Clock clock,
       int batchSize) {
-    super(sheet, new MedicalRegistryRowReader(sheet), new FeedbackColumnAccessor(actualColumns));
+    super(
+        sheet,
+        new MedicalRegistryRowReader(sheet, clock),
+        new FeedbackColumnAccessor(actualColumns));
     this.medicalRegistryService = medicalRegistryService;
     if (batchSize < 1 || batchSize > 10_000) {
       throw new IllegalArgumentException("batchSize must be between 1 and 10_000");
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/importer/MedicalRegistryRowReader.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/importer/MedicalRegistryRowReader.java
index f43776cf7369ed7e155f71a10e0affd878964f37..860eee79bcab171853885d93fceebcc7caeac73d 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/importer/MedicalRegistryRowReader.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/importer/MedicalRegistryRowReader.java
@@ -24,6 +24,7 @@ import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Pattern;
 import jakarta.validation.constraints.Size;
 import jakarta.validation.metadata.ConstraintDescriptor;
+import java.time.Clock;
 import java.util.Arrays;
 import java.util.Set;
 import org.apache.poi.ss.usermodel.Cell;
@@ -34,8 +35,8 @@ class MedicalRegistryRowReader extends RowReader<MedicalRegistryRow, MedicalRegi
   private static final ValidatorFactory validatorFactory =
       Validation.buildDefaultValidatorFactory();
 
-  MedicalRegistryRowReader(Sheet sheet) {
-    super(sheet, Arrays.asList(MedicalRegistryColumn.values()), MedicalRegistryRow::new);
+  MedicalRegistryRowReader(Sheet sheet, Clock clock) {
+    super(sheet, Arrays.asList(MedicalRegistryColumn.values()), MedicalRegistryRow::new, clock);
   }
 
   @Override
diff --git a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/testhelper/MedicalRegistryTestHelperController.java b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/testhelper/MedicalRegistryTestHelperController.java
index 3890dc463769306baf084fa9b74fb775bd9fdaae..c132a9d3f6dfd92afd378b4532db7695f3db0d94 100644
--- a/backend/medical-registry/src/main/java/de/eshg/medicalregistry/testhelper/MedicalRegistryTestHelperController.java
+++ b/backend/medical-registry/src/main/java/de/eshg/medicalregistry/testhelper/MedicalRegistryTestHelperController.java
@@ -5,7 +5,7 @@
 
 package de.eshg.medicalregistry.testhelper;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.lib.auditlog.AuditLogTestHelperService;
 import de.eshg.medicalregistry.featuretoggle.MedicalRegistryFeature;
 import de.eshg.medicalregistry.featuretoggle.MedicalRegistryFeatureToggle;
@@ -13,7 +13,6 @@ import de.eshg.testhelper.ConditionalOnTestHelperEnabled;
 import de.eshg.testhelper.TestHelperController;
 import de.eshg.testhelper.TestHelperWithDatabaseService;
 import de.eshg.testhelper.environment.EnvironmentConfig;
-import java.io.IOException;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.service.annotation.DeleteExchange;
@@ -22,7 +21,7 @@ import org.springframework.web.service.annotation.PostExchange;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class MedicalRegistryTestHelperController extends TestHelperController
-    implements SharedAuditLogTestHelperApi {
+    implements AuditLogClientTestHelperApi {
 
   private final AuditLogTestHelperService auditLogTestHelperService;
   private final MedicalRegistryFeatureToggle medicalRegistryFeatureToggle;
@@ -50,12 +49,7 @@ public class MedicalRegistryTestHelperController extends TestHelperController
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
-  }
-
-  @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 }
diff --git a/backend/medical-registry/src/main/resources/migrations/0008_add_auditlog_entry.xml b/backend/medical-registry/src/main/resources/migrations/0008_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ebb946b32565da731dd06d7f947f2ed09deef45b
--- /dev/null
+++ b/backend/medical-registry/src/main/resources/migrations/0008_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: Apache-2.0
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/medical-registry/src/main/resources/migrations/changelog.xml b/backend/medical-registry/src/main/resources/migrations/changelog.xml
index 1fbc0d57613f2e17040037dd2588b817f89c38bd..15661d472d3296884ace2de3258040eeee3848d0 100644
--- a/backend/medical-registry/src/main/resources/migrations/changelog.xml
+++ b/backend/medical-registry/src/main/resources/migrations/changelog.xml
@@ -15,5 +15,6 @@
   <include file="migrations/0005_add_cemetery_delete_at.xml"/>
   <include file="migrations/0006_add_countrycodes.xml"/>
   <include file="migrations/0007_add_previous_file_state_id_to_system_progress_entry.xml"/>
+  <include file="migrations/0008_add_auditlog_entry.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/official-medical-service/build.gradle b/backend/official-medical-service/build.gradle
index e5dace08de0e8e96a2c1684a053e6a85af534767..a9f36344dc377478ac96b918b351e10ab333c443 100644
--- a/backend/official-medical-service/build.gradle
+++ b/backend/official-medical-service/build.gradle
@@ -19,6 +19,7 @@ dependencies {
 
     testImplementation testFixtures(project(':business-module-persistence-commons'))
     testImplementation testFixtures(project(':lib-procedures'))
+    testImplementation testFixtures(project(':base-api'))
 }
 
 dockerCompose {
diff --git a/backend/official-medical-service/gradle.lockfile b/backend/official-medical-service/gradle.lockfile
index e30023385d586f7bd7de4790780dc92f8464b416..974f15435702970efe405ee4e675285820d09cba 100644
--- a/backend/official-medical-service/gradle.lockfile
+++ b/backend/official-medical-service/gradle.lockfile
@@ -67,10 +67,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -136,10 +136,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -158,16 +158,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/official-medical-service/openApi.json b/backend/official-medical-service/openApi.json
index 1e966204134af62ee2d8a61aa0ab57539d7f40b7..fee8858e51531665a6e37081af8dab5758c571b6 100644
--- a/backend/official-medical-service/openApi.json
+++ b/backend/official-medical-service/openApi.json
@@ -679,6 +679,187 @@
         "tags" : [ "Concern" ]
       }
     },
+    "/employee/document/{id}" : {
+      "delete" : {
+        "operationId" : "deleteDocumentEmployee",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "summary" : "Deletes a document along with all files associated with it",
+        "tags" : [ "OmsDocument" ]
+      },
+      "patch" : {
+        "operationId" : "patchDocumentInformation",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/PatchDocumentInformationRequest"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "summary" : "Updates information of one oms document",
+        "tags" : [ "OmsDocument" ]
+      }
+    },
+    "/employee/document/{id}/complete-file-upload" : {
+      "patch" : {
+        "operationId" : "patchCompleteDocumentFileUpload",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "multipart/form-data" : {
+              "schema" : {
+                "type" : "object",
+                "properties" : {
+                  "files" : {
+                    "type" : "array",
+                    "items" : {
+                      "type" : "string",
+                      "format" : "binary"
+                    }
+                  }
+                },
+                "required" : [ "files" ]
+              }
+            }
+          }
+        },
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "summary" : "Completes file upload of one oms document",
+        "tags" : [ "OmsDocument" ]
+      }
+    },
+    "/employee/document/{id}/note" : {
+      "patch" : {
+        "operationId" : "patchDocumentNote",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/PatchDocumentNoteRequest"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "summary" : "Updates note of one oms document",
+        "tags" : [ "OmsDocument" ]
+      }
+    },
+    "/employee/document/{id}/review" : {
+      "patch" : {
+        "operationId" : "patchDocumentReview",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/PatchDocumentReviewRequest"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "summary" : "Accepts or rejects a submitted document",
+        "tags" : [ "OmsDocument" ]
+      }
+    },
+    "/employee/file/{fileId}" : {
+      "get" : {
+        "operationId" : "getDownloadFile",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "fileId",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "responses" : {
+          "200" : {
+            "content" : {
+              "application/octet-stream" : {
+                "schema" : {
+                  "type" : "string",
+                  "format" : "binary"
+                }
+              }
+            },
+            "description" : "OK"
+          }
+        },
+        "summary" : "Download file from oms document.",
+        "tags" : [ "OmsFile" ]
+      }
+    },
     "/employee/procedures" : {
       "get" : {
         "operationId" : "getAllEmployeeProcedures",
@@ -848,6 +1029,13 @@
         } ],
         "responses" : {
           "200" : {
+            "content" : {
+              "application/json" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/AcceptDraftProcedureResponse"
+                }
+              }
+            },
             "description" : "OK"
           }
         },
@@ -974,6 +1162,117 @@
         "tags" : [ "EmployeeOmsProcedure" ]
       }
     },
+    "/employee/procedures/{id}/document" : {
+      "get" : {
+        "operationId" : "getAllDocuments",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "responses" : {
+          "200" : {
+            "content" : {
+              "application/json" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/GetDocumentsResponse"
+                }
+              }
+            },
+            "description" : "OK"
+          }
+        },
+        "summary" : "Get all documents for one oms procedure",
+        "tags" : [ "EmployeeOmsProcedure" ]
+      },
+      "post" : {
+        "operationId" : "postDocument",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "multipart/form-data" : {
+              "schema" : {
+                "type" : "object",
+                "properties" : {
+                  "files" : {
+                    "type" : "array",
+                    "items" : {
+                      "type" : "string",
+                      "format" : "binary"
+                    }
+                  },
+                  "note" : {
+                    "type" : "string"
+                  },
+                  "postDocumentRequest" : {
+                    "$ref" : "#/components/schemas/PostDocumentRequest"
+                  }
+                },
+                "required" : [ "postDocumentRequest" ]
+              }
+            }
+          }
+        },
+        "responses" : {
+          "200" : {
+            "content" : {
+              "application/json" : {
+                "schema" : {
+                  "type" : "string",
+                  "format" : "uuid"
+                }
+              }
+            },
+            "description" : "OK"
+          }
+        },
+        "summary" : "Add a document to an oms procedure",
+        "tags" : [ "EmployeeOmsProcedure" ]
+      }
+    },
+    "/employee/procedures/{id}/email-notifications" : {
+      "patch" : {
+        "operationId" : "patchEmailNotifications",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/PatchEmployeeOmsProcedureEmailNotificationsRequest"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "summary" : "Updates the whether or not email notifications will be sent",
+        "tags" : [ "EmployeeOmsProcedure" ]
+      }
+    },
     "/employee/procedures/{id}/facility" : {
       "patch" : {
         "operationId" : "patchFacility",
@@ -1070,6 +1369,37 @@
         "tags" : [ "EmployeeOmsProcedure" ]
       }
     },
+    "/employee/procedures/{id}/medical-opinion-status" : {
+      "patch" : {
+        "operationId" : "patchMedicalOpinionStatus",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/MedicalOpinionStatus"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "summary" : "Updates the medical opinion status of a oms procedure",
+        "tags" : [ "EmployeeOmsProcedure" ]
+      }
+    },
     "/employee/procedures/{id}/physician" : {
       "patch" : {
         "operationId" : "patchPhysician",
@@ -1140,6 +1470,37 @@
         "tags" : [ "EmployeeOmsProcedure" ]
       }
     },
+    "/employee/procedures/{id}/waiting-room" : {
+      "patch" : {
+        "operationId" : "patchWaitingRoom",
+        "parameters" : [ {
+          "in" : "path",
+          "name" : "id",
+          "required" : true,
+          "schema" : {
+            "type" : "string",
+            "format" : "uuid"
+          }
+        } ],
+        "requestBody" : {
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/WaitingRoom"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "description" : "OK"
+          }
+        },
+        "summary" : "Update waiting room details for a procedure",
+        "tags" : [ "EmployeeOmsProcedure" ]
+      }
+    },
     "/employee/procedures/{procedureId}/affected-person" : {
       "patch" : {
         "operationId" : "updateAffectedPerson",
@@ -1198,8 +1559,60 @@
             "description" : "OK"
           }
         },
-        "summary" : "Synchronize affected person data",
-        "tags" : [ "EmployeeOmsProcedure" ]
+        "summary" : "Synchronize affected person data",
+        "tags" : [ "EmployeeOmsProcedure" ]
+      }
+    },
+    "/employee/waiting-room" : {
+      "get" : {
+        "operationId" : "getWaitingRoomProcedures",
+        "parameters" : [ {
+          "in" : "query",
+          "name" : "sortKey",
+          "required" : false,
+          "schema" : {
+            "$ref" : "#/components/schemas/WaitingRoomSortKey"
+          }
+        }, {
+          "in" : "query",
+          "name" : "sortDirection",
+          "required" : false,
+          "schema" : {
+            "$ref" : "#/components/schemas/SortDirection"
+          }
+        }, {
+          "in" : "query",
+          "name" : "pageNumber",
+          "required" : false,
+          "schema" : {
+            "minimum" : 0,
+            "type" : "integer",
+            "format" : "int32"
+          }
+        }, {
+          "in" : "query",
+          "name" : "pageSize",
+          "required" : false,
+          "schema" : {
+            "minimum" : 1,
+            "type" : "integer",
+            "format" : "int32"
+          }
+        } ],
+        "responses" : {
+          "200" : {
+            "content" : {
+              "application/json" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/GetWaitingRoomProceduresResponse"
+                }
+              }
+            },
+            "description" : "OK"
+          }
+        },
+        "summary" : "Get all procedures in waiting room.",
+        "tags" : [ "WaitingRoom" ]
       }
     },
     "/files/{fileId}" : {
@@ -2920,18 +3333,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
-        "responses" : {
-          "200" : {
-            "description" : "OK"
-          }
-        },
-        "tags" : [ "TestHelper" ]
-      }
-    },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -3238,6 +3640,15 @@
           "propertyName" : "@type"
         }
       },
+      "AcceptDraftProcedureResponse" : {
+        "required" : [ "accessCode" ],
+        "type" : "object",
+        "properties" : {
+          "accessCode" : {
+            "type" : "string"
+          }
+        }
+      },
       "AddBarrierTestHelperResponse" : {
         "required" : [ "barrierId" ],
         "type" : "object",
@@ -3431,9 +3842,9 @@
             "format" : "uuid"
           },
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
@@ -4005,6 +4416,84 @@
           }
         }
       },
+      "Document" : {
+        "required" : [ "documentStatus", "documentTypeDe", "files", "id", "mandatoryDocument", "uploadInCitizenPortal" ],
+        "type" : "object",
+        "properties" : {
+          "documentStatus" : {
+            "$ref" : "#/components/schemas/DocumentStatus"
+          },
+          "documentTypeDe" : {
+            "type" : "string"
+          },
+          "documentTypeEn" : {
+            "type" : "string"
+          },
+          "files" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/components/schemas/OmsFile"
+            }
+          },
+          "helpTextDe" : {
+            "type" : "string"
+          },
+          "helpTextEn" : {
+            "type" : "string"
+          },
+          "id" : {
+            "type" : "string",
+            "format" : "uuid"
+          },
+          "lastDocumentUpload" : {
+            "type" : "string",
+            "format" : "date-time"
+          },
+          "mandatoryDocument" : {
+            "type" : "boolean"
+          },
+          "note" : {
+            "type" : "string"
+          },
+          "reasonForRejection" : {
+            "type" : "string"
+          },
+          "uploadInCitizenPortal" : {
+            "type" : "boolean"
+          }
+        }
+      },
+      "DocumentPopulation" : {
+        "required" : [ "key", "request" ],
+        "type" : "object",
+        "properties" : {
+          "files" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/components/schemas/FileTestDataConfig"
+            }
+          },
+          "key" : {
+            "type" : "string"
+          },
+          "note" : {
+            "type" : "string"
+          },
+          "reasonForRejection" : {
+            "type" : "string"
+          },
+          "request" : {
+            "$ref" : "#/components/schemas/PostDocumentRequest"
+          },
+          "targetState" : {
+            "$ref" : "#/components/schemas/DocumentStatus"
+          }
+        }
+      },
+      "DocumentStatus" : {
+        "type" : "string",
+        "enum" : [ "MISSING", "SUBMITTED", "REJECTED", "ACCEPTED" ]
+      },
       "DomesticAddress" : {
         "required" : [ "city", "country", "postalCode", "street" ],
         "type" : "object",
@@ -4063,7 +4552,7 @@
         } ]
       },
       "EmployeeOmsProcedureDetails" : {
-        "required" : [ "affectedPerson", "appointments", "id", "status" ],
+        "required" : [ "affectedPerson", "appointments", "id", "medicalOpinionStatus", "sendEmailNotifications", "status", "waitingRoom" ],
         "type" : "object",
         "properties" : {
           "affectedPerson" : {
@@ -4075,6 +4564,10 @@
               "$ref" : "#/components/schemas/OmsAppointment"
             }
           },
+          "citizenUserId" : {
+            "type" : "string",
+            "format" : "uuid"
+          },
           "concern" : {
             "$ref" : "#/components/schemas/Concern"
           },
@@ -4085,11 +4578,20 @@
             "type" : "string",
             "format" : "uuid"
           },
+          "medicalOpinionStatus" : {
+            "$ref" : "#/components/schemas/MedicalOpinionStatus"
+          },
           "physician" : {
             "$ref" : "#/components/schemas/User"
           },
+          "sendEmailNotifications" : {
+            "type" : "boolean"
+          },
           "status" : {
             "$ref" : "#/components/schemas/ProcedureStatus"
+          },
+          "waitingRoom" : {
+            "$ref" : "#/components/schemas/WaitingRoom"
           }
         }
       },
@@ -4117,7 +4619,7 @@
         }
       },
       "EmployeeOmsProcedureOverview" : {
-        "required" : [ "id", "status" ],
+        "required" : [ "id", "medicalOpinionStatus", "status" ],
         "type" : "object",
         "properties" : {
           "concern" : {
@@ -4140,6 +4642,9 @@
           "lastName" : {
             "type" : "string"
           },
+          "medicalOpinionStatus" : {
+            "$ref" : "#/components/schemas/MedicalOpinionStatus"
+          },
           "nextAppointment" : {
             "type" : "string",
             "format" : "date-time"
@@ -4298,6 +4803,10 @@
           }
         }
       },
+      "FileTestDataConfig" : {
+        "type" : "string",
+        "enum" : [ "PDF", "JPG", "PNG" ]
+      },
       "FileType" : {
         "type" : "string",
         "enum" : [ "JPEG", "PNG", "PDF", "EML" ]
@@ -4753,6 +5262,18 @@
           }
         }
       },
+      "GetDocumentsResponse" : {
+        "required" : [ "documents" ],
+        "type" : "object",
+        "properties" : {
+          "documents" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/components/schemas/Document"
+            }
+          }
+        }
+      },
       "GetEmployeeOmsProcedureOverviewResponse" : {
         "required" : [ "elements", "totalNumberOfElements" ],
         "type" : "object",
@@ -5368,6 +5889,22 @@
         "default" : "ASC",
         "enum" : [ "ASC", "DESC" ]
       },
+      "GetWaitingRoomProceduresResponse" : {
+        "required" : [ "elements", "totalNumberOfElements" ],
+        "type" : "object",
+        "properties" : {
+          "elements" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/components/schemas/WaitingRoomProcedure"
+            }
+          },
+          "totalNumberOfElements" : {
+            "type" : "integer",
+            "format" : "int64"
+          }
+        }
+      },
       "HttpMethod" : {
         "type" : "string",
         "enum" : [ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "TRACE" ]
@@ -5690,6 +6227,10 @@
         "type" : "string",
         "enum" : [ "LETTER", "PHONE_CALL", "NOTE", "EMAIL", "IMAGE", "DOCUMENT" ]
       },
+      "MedicalOpinionStatus" : {
+        "type" : "string",
+        "enum" : [ "IN_PROGRESS", "ACCOMPLISHED" ]
+      },
       "MetaData" : {
         "required" : [ "@type" ],
         "type" : "object",
@@ -5751,6 +6292,30 @@
           }
         }
       },
+      "OmsFile" : {
+        "required" : [ "creationDate", "fileType", "id", "name", "size" ],
+        "type" : "object",
+        "properties" : {
+          "creationDate" : {
+            "type" : "string",
+            "format" : "date-time"
+          },
+          "fileType" : {
+            "$ref" : "#/components/schemas/FileType"
+          },
+          "id" : {
+            "type" : "string",
+            "format" : "uuid"
+          },
+          "name" : {
+            "type" : "string"
+          },
+          "size" : {
+            "type" : "integer",
+            "format" : "int32"
+          }
+        }
+      },
       "Operation" : {
         "type" : "string",
         "enum" : [ "DELETE" ]
@@ -5773,6 +6338,59 @@
           }
         }
       },
+      "PatchDocumentInformationRequest" : {
+        "required" : [ "documentTypeDe", "mandatoryDocument", "uploadInCitizenPortal" ],
+        "type" : "object",
+        "properties" : {
+          "documentTypeDe" : {
+            "type" : "string"
+          },
+          "documentTypeEn" : {
+            "type" : "string"
+          },
+          "helpTextDe" : {
+            "type" : "string"
+          },
+          "helpTextEn" : {
+            "type" : "string"
+          },
+          "mandatoryDocument" : {
+            "type" : "boolean"
+          },
+          "uploadInCitizenPortal" : {
+            "type" : "boolean"
+          }
+        }
+      },
+      "PatchDocumentNoteRequest" : {
+        "type" : "object",
+        "properties" : {
+          "note" : {
+            "type" : "string"
+          }
+        }
+      },
+      "PatchDocumentReviewRequest" : {
+        "required" : [ "result" ],
+        "type" : "object",
+        "properties" : {
+          "reasonForRejection" : {
+            "type" : "string"
+          },
+          "result" : {
+            "$ref" : "#/components/schemas/ReviewResult"
+          }
+        }
+      },
+      "PatchEmployeeOmsProcedureEmailNotificationsRequest" : {
+        "required" : [ "sendEmailNotifications" ],
+        "type" : "object",
+        "properties" : {
+          "sendEmailNotifications" : {
+            "type" : "boolean"
+          }
+        }
+      },
       "PatchEmployeeOmsProcedureFacilityRequest" : {
         "required" : [ "updatedFacility" ],
         "type" : "object",
@@ -5873,6 +6491,30 @@
           }
         }
       },
+      "PostDocumentRequest" : {
+        "required" : [ "documentTypeDe", "mandatoryDocument", "uploadInCitizenPortal" ],
+        "type" : "object",
+        "properties" : {
+          "documentTypeDe" : {
+            "type" : "string"
+          },
+          "documentTypeEn" : {
+            "type" : "string"
+          },
+          "helpTextDe" : {
+            "type" : "string"
+          },
+          "helpTextEn" : {
+            "type" : "string"
+          },
+          "mandatoryDocument" : {
+            "type" : "boolean"
+          },
+          "uploadInCitizenPortal" : {
+            "type" : "boolean"
+          }
+        }
+      },
       "PostEmployeeOmsProcedureFacilityRequest" : {
         "required" : [ "facility" ],
         "type" : "object",
@@ -5939,6 +6581,9 @@
               "type" : "string"
             }
           },
+          "citizenUserId" : {
+            "type" : "string"
+          },
           "closedAppointments" : {
             "type" : "array",
             "items" : {
@@ -5948,9 +6593,18 @@
           "concern" : {
             "$ref" : "#/components/schemas/ConcernTestDataConfig"
           },
+          "documents" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/components/schemas/DocumentPopulation"
+            }
+          },
           "facility" : {
             "$ref" : "#/components/schemas/PostEmployeeOmsProcedureFacilityRequest"
           },
+          "medicalOpinionStatus" : {
+            "$ref" : "#/components/schemas/MedicalOpinionStatus"
+          },
           "physician" : {
             "type" : "string",
             "format" : "uuid"
@@ -5958,8 +6612,14 @@
           "procedureData" : {
             "$ref" : "#/components/schemas/PostEmployeeOmsProcedureRequest"
           },
+          "sendEmailNotifications" : {
+            "type" : "boolean"
+          },
           "targetState" : {
             "$ref" : "#/components/schemas/ProcedureStatus"
+          },
+          "waitingRoom" : {
+            "$ref" : "#/components/schemas/WaitingRoom"
           }
         }
       },
@@ -5974,6 +6634,13 @@
               "format" : "uuid"
             }
           },
+          "documentMap" : {
+            "type" : "object",
+            "additionalProperties" : {
+              "type" : "string",
+              "format" : "uuid"
+            }
+          },
           "facilityId" : {
             "type" : "string",
             "format" : "uuid"
@@ -6229,6 +6896,10 @@
         "default" : "ASC",
         "enum" : [ "ASC", "DESC" ]
       },
+      "ReviewResult" : {
+        "type" : "string",
+        "enum" : [ "ACCEPTED", "REJECTED" ]
+      },
       "Salutation" : {
         "type" : "string",
         "enum" : [ "NOT_SPECIFIED", "NEUTRAL", "FEMALE", "MALE" ]
@@ -6518,9 +7189,9 @@
         "type" : "object",
         "properties" : {
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
@@ -6590,6 +7261,58 @@
             }
           }
         }
+      },
+      "WaitingRoom" : {
+        "type" : "object",
+        "properties" : {
+          "info" : {
+            "type" : "string"
+          },
+          "status" : {
+            "$ref" : "#/components/schemas/WaitingStatus"
+          }
+        }
+      },
+      "WaitingRoomProcedure" : {
+        "required" : [ "dateOfBirth", "facilityName", "firstName", "id", "lastName", "modifiedAt", "waitingRoom" ],
+        "type" : "object",
+        "properties" : {
+          "dateOfBirth" : {
+            "type" : "string",
+            "format" : "date"
+          },
+          "facilityName" : {
+            "type" : "string"
+          },
+          "firstName" : {
+            "type" : "string"
+          },
+          "id" : {
+            "type" : "string",
+            "format" : "uuid"
+          },
+          "lastName" : {
+            "type" : "string"
+          },
+          "modifiedAt" : {
+            "type" : "string",
+            "format" : "date-time"
+          },
+          "physicianName" : {
+            "type" : "string"
+          },
+          "waitingRoom" : {
+            "$ref" : "#/components/schemas/WaitingRoom"
+          }
+        }
+      },
+      "WaitingRoomSortKey" : {
+        "type" : "string",
+        "enum" : [ "ID", "FIRSTNAME", "LASTNAME", "DATE_OF_BIRTH", "FACILITY", "PHYSICIAN", "STATUS", "INFO", "MODIFIED_AT" ]
+      },
+      "WaitingStatus" : {
+        "type" : "string",
+        "enum" : [ "WAITING_FOR_CONSULTATION", "IN_CONSULTATION", "DONE" ]
       }
     }
   }
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/OfficialMedicalServiceApplication.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/OfficialMedicalServiceApplication.java
index 141d856b4933c7349d137f24d570601696319b7f..a947dc88e667020972d07eb4f4b126c9456eb4be 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/OfficialMedicalServiceApplication.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/OfficialMedicalServiceApplication.java
@@ -8,6 +8,7 @@ package de.eshg.officialmedicalservice;
 import de.eshg.lib.common.BusinessModule;
 import de.eshg.officialmedicalservice.citizenpublic.DepartmentInfoProperties;
 import de.eshg.officialmedicalservice.citizenpublic.OpeningHoursProperties;
+import de.eshg.officialmedicalservice.notification.NotificationProperties;
 import de.eshg.rest.service.security.config.OfficialMedicalServicePublicSecurityConfig;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -17,7 +18,11 @@ import org.springframework.context.annotation.Import;
 
 @SpringBootApplication
 @Import(OfficialMedicalServicePublicSecurityConfig.class)
-@EnableConfigurationProperties({OpeningHoursProperties.class, DepartmentInfoProperties.class})
+@EnableConfigurationProperties({
+  OpeningHoursProperties.class,
+  DepartmentInfoProperties.class,
+  NotificationProperties.class
+})
 public class OfficialMedicalServiceApplication {
 
   @Bean
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/appointment/OmsAppointmentService.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/appointment/OmsAppointmentService.java
index 38bc715d85b23eabe1ba8e43196fc27f1ec281ec..99ae7a29f9a92840a13672e4223480e2a7cb5a4a 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/appointment/OmsAppointmentService.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/appointment/OmsAppointmentService.java
@@ -15,6 +15,7 @@ import de.eshg.officialmedicalservice.appointment.persistence.OmsAppointmentRepo
 import de.eshg.officialmedicalservice.appointment.persistence.entity.AppointmentState;
 import de.eshg.officialmedicalservice.appointment.persistence.entity.BookingState;
 import de.eshg.officialmedicalservice.appointment.persistence.entity.OmsAppointment;
+import de.eshg.officialmedicalservice.procedure.ProgressEntryService;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedureRepository;
 import de.eshg.rest.service.error.BadRequestException;
@@ -35,16 +36,19 @@ public class OmsAppointmentService {
 
   private static final List<AppointmentTypeDto> supportedAppointmentTypes =
       List.of(AppointmentTypeDto.OFFICIAL_MEDICAL_SERVICE);
+  private final ProgressEntryService progressEntryService;
 
   public OmsAppointmentService(
       OmsProcedureRepository omsProcedureRepository,
       OmsAppointmentRepository omsAppointmentRepository,
       OmsAppointmentMapper omsAppointmentMapper,
-      AppointmentBlockSlotUtil appointmentBlockSlotUtil) {
+      AppointmentBlockSlotUtil appointmentBlockSlotUtil,
+      ProgressEntryService progressEntryService) {
     this.omsProcedureRepository = omsProcedureRepository;
     this.omsAppointmentRepository = omsAppointmentRepository;
     this.omsAppointmentMapper = omsAppointmentMapper;
     this.appointmentBlockSlotUtil = appointmentBlockSlotUtil;
+    this.progressEntryService = progressEntryService;
   }
 
   @Transactional
@@ -74,6 +78,12 @@ public class OmsAppointmentService {
 
     omsAppointmentRepository.save(appointment);
 
+    if (bookingInfo != null) {
+      progressEntryService.createProgressEntryForAddingAppointmentWithBooking(procedure, request);
+    } else {
+      progressEntryService.createProgressEntryForAddingSelfBookingAppointment(procedure);
+    }
+
     return appointment.getExternalId();
   }
 
@@ -90,6 +100,14 @@ public class OmsAppointmentService {
       throw new BadRequestException("Appointment is withdrawn");
     }
 
+    if (BookingState.BOOKED == appointment.getBookingState()) {
+      progressEntryService.createProgressEntryForRebookedAppointment(
+          appointment.getProcedure(), appointment, request);
+    } else {
+      progressEntryService.createProgressEntryForBookingAppointment(
+          appointment.getProcedure(), request);
+    }
+
     processBooking(request, appointment);
   }
 
@@ -111,6 +129,8 @@ public class OmsAppointmentService {
     appointment.setBookingType(null);
     appointment.setDuration(null);
     appointment.setAppointment(null); // to unlock appointment block
+    progressEntryService.createProgressEntryForCancelingAppointment(
+        appointment.getProcedure(), appointment);
   }
 
   @Transactional
@@ -126,6 +146,12 @@ public class OmsAppointmentService {
 
     if (BookingState.BOOKABLE == appointment.getBookingState()) {
       appointment.setBookingState(BookingState.WITHDRAWN);
+
+      progressEntryService.createProgressEntryForWithdrawingAppointmentOption(
+          appointment.getProcedure());
+    } else {
+      progressEntryService.createProgressEntryForClosingAppointment(
+          appointment.getProcedure(), appointment);
     }
 
     appointment.setAppointmentState(AppointmentState.CLOSED);
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/appointment/persistence/entity/AppointmentState.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/appointment/persistence/entity/AppointmentState.java
index bc405ef860592b970b32fd447af0353d247b5d4b..7c23e4838ba09041db91d643c109ea84d2ad88fa 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/appointment/persistence/entity/AppointmentState.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/appointment/persistence/entity/AppointmentState.java
@@ -6,6 +6,17 @@
 package de.eshg.officialmedicalservice.appointment.persistence.entity;
 
 public enum AppointmentState {
-  OPEN,
-  CLOSED
+  OPEN("OFFEN"),
+  CLOSED("GESCHLOSSEN"),
+  ;
+
+  private final String germanName;
+
+  AppointmentState(String germanName) {
+    this.germanName = germanName;
+  }
+
+  public String getGermanName() {
+    return germanName;
+  }
 }
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentController.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentController.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3224e9ea795a72ee91790a2b2a567b70b28de16
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentController.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document;
+
+import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
+
+import de.eshg.officialmedicalservice.document.api.PatchDocumentInformationRequest;
+import de.eshg.officialmedicalservice.document.api.PatchDocumentNoteRequest;
+import de.eshg.officialmedicalservice.document.api.PatchDocumentReviewRequest;
+import de.eshg.rest.service.security.config.BaseUrls;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import java.util.List;
+import java.util.UUID;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PatchMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+@RestController
+@RequestMapping(path = OmsDocumentController.BASE_URL, produces = MediaType.APPLICATION_JSON_VALUE)
+@Tag(name = "OmsDocument")
+public class OmsDocumentController {
+  public static final String BASE_URL = BaseUrls.OfficialMedicalService.EMPLOYEE_API;
+  public static final String DOCUMENT_URL = "/document";
+  public static final String COMPLETE_FILE_UPLOAD_URL = "/complete-file-upload";
+  public static final String NOTE_URL = "/note";
+  public static final String REVIEW_URL = "/review";
+
+  private final OmsDocumentService omsDocumentService;
+
+  public OmsDocumentController(OmsDocumentService omsDocumentService) {
+    this.omsDocumentService = omsDocumentService;
+  }
+
+  @PatchMapping(path = DOCUMENT_URL + "/{id}")
+  @Operation(summary = "Updates information of one oms document")
+  public void patchDocumentInformation(
+      @PathVariable("id") UUID documentId,
+      @Valid @RequestBody PatchDocumentInformationRequest request) {
+    omsDocumentService.updateDocumentInformationEmployee(documentId, request);
+  }
+
+  @PatchMapping(
+      path = DOCUMENT_URL + "/{id}" + COMPLETE_FILE_UPLOAD_URL,
+      consumes = MULTIPART_FORM_DATA_VALUE)
+  @Operation(summary = "Completes file upload of one oms document")
+  public void patchCompleteDocumentFileUpload(
+      @PathVariable("id") UUID documentId,
+      @RequestPart(value = "files") List<MultipartFile> files) {
+    omsDocumentService.completeDocumentFileUploadEmployee(documentId, files);
+  }
+
+  @DeleteMapping(path = DOCUMENT_URL + "/{id}")
+  @Operation(summary = "Deletes a document along with all files associated with it")
+  public void deleteDocumentEmployee(@PathVariable("id") UUID documentId) {
+    omsDocumentService.deleteDocumentEmployee(documentId);
+  }
+
+  @PatchMapping(path = DOCUMENT_URL + "/{id}" + NOTE_URL)
+  @Operation(summary = "Updates note of one oms document")
+  public void patchDocumentNote(
+      @PathVariable("id") UUID documentId, @Valid @RequestBody PatchDocumentNoteRequest request) {
+    omsDocumentService.updateDocumentNoteEmployee(documentId, request);
+  }
+
+  @PatchMapping(path = DOCUMENT_URL + "/{id}" + REVIEW_URL)
+  @Operation(summary = "Accepts or rejects a submitted document")
+  public void patchDocumentReview(
+      @PathVariable("id") UUID documentId, @Valid @RequestBody PatchDocumentReviewRequest request) {
+    omsDocumentService.reviewDocumentEmployee(documentId, request);
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentMapper.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e87f1c6a3a2a4c176aec96c444cb60bfec9fafa
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentMapper.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document;
+
+import de.eshg.officialmedicalservice.document.api.DocumentDto;
+import de.eshg.officialmedicalservice.document.api.DocumentStatusDto;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocument;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocumentStatus;
+import de.eshg.officialmedicalservice.file.OmsFileMapper;
+import java.util.Collections;
+import java.util.List;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OmsDocumentMapper {
+  private final OmsFileMapper omsFileMapper;
+
+  public OmsDocumentMapper(OmsFileMapper omsFileMapper) {
+    this.omsFileMapper = omsFileMapper;
+  }
+
+  public List<DocumentDto> toInterfaceType(List<OmsDocument> documentList) {
+    if (documentList == null) {
+      return Collections.emptyList();
+    }
+    return documentList.stream()
+        .sorted(
+            (doc1, doc2) -> doc1.getDocumentTypeDe().compareToIgnoreCase(doc2.getDocumentTypeDe()))
+        .map(this::toInterfaceType)
+        .toList();
+  }
+
+  public DocumentDto toInterfaceType(OmsDocument document) {
+    if (document == null) {
+      return null;
+    }
+    return new DocumentDto(
+        document.getId(),
+        document.getDocumentTypeDe(),
+        document.getDocumentTypeEn(),
+        document.getHelpTextDe(),
+        document.getHelpTextEn(),
+        toInterfaceType(document.getDocumentStatus()),
+        document.getLastDocumentUpload(),
+        omsFileMapper.toInterfaceType(document.getFiles()),
+        document.getNote(),
+        document.isMandatoryDocument(),
+        document.isUploadInCitizenPortal(),
+        document.getReasonForRejection());
+  }
+
+  public DocumentStatusDto toInterfaceType(OmsDocumentStatus documentStatus) {
+    if (documentStatus == null) {
+      return null;
+    }
+    return DocumentStatusDto.valueOf(documentStatus.name());
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentService.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentService.java
new file mode 100644
index 0000000000000000000000000000000000000000..10987c63bee05d45f92d127c72a8f770dd31b537
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/OmsDocumentService.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document;
+
+import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.springframework.http.MediaType.APPLICATION_PDF_VALUE;
+import static org.springframework.http.MediaType.IMAGE_JPEG_VALUE;
+import static org.springframework.http.MediaType.IMAGE_PNG_VALUE;
+
+import de.eshg.lib.procedure.model.FileTypeDto;
+import de.eshg.officialmedicalservice.document.api.PatchDocumentInformationRequest;
+import de.eshg.officialmedicalservice.document.api.PatchDocumentNoteRequest;
+import de.eshg.officialmedicalservice.document.api.PatchDocumentReviewRequest;
+import de.eshg.officialmedicalservice.document.api.PostDocumentRequest;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocument;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocumentRepository;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocumentStatus;
+import de.eshg.officialmedicalservice.file.persistence.entity.OmsFile;
+import de.eshg.officialmedicalservice.file.persistence.entity.OmsFileRepository;
+import de.eshg.officialmedicalservice.procedure.OmsProgressEntryType;
+import de.eshg.officialmedicalservice.procedure.ProgressEntryService;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedureRepository;
+import de.eshg.rest.service.error.BadRequestException;
+import de.eshg.rest.service.error.NotFoundException;
+import java.io.IOException;
+import java.time.Clock;
+import java.time.Instant;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+@Service
+public class OmsDocumentService {
+  private final OmsProcedureRepository omsProcedureRepository;
+  private final OmsDocumentRepository omsDocumentRepository;
+  private final OmsFileRepository omsFileRepository;
+  private final ProgressEntryService progressEntryService;
+  private final Clock clock;
+
+  private static final Logger logger = LoggerFactory.getLogger(OmsDocumentService.class);
+
+  public OmsDocumentService(
+      OmsProcedureRepository omsProcedureRepository,
+      OmsDocumentRepository omsDocumentRepository,
+      OmsFileRepository omsFileRepository,
+      ProgressEntryService progressEntryService,
+      Clock clock) {
+    this.omsProcedureRepository = omsProcedureRepository;
+    this.omsDocumentRepository = omsDocumentRepository;
+    this.omsFileRepository = omsFileRepository;
+    this.progressEntryService = progressEntryService;
+    this.clock = clock;
+  }
+
+  @Transactional
+  public UUID addDocumentEmployee(
+      UUID externalId, PostDocumentRequest request, List<MultipartFile> files, String note) {
+    OmsProcedure omsProcedure = loadOmsProcedure(externalId);
+
+    if (omsProcedure.isFinalized()) {
+      throw new BadRequestException("Document cannot be added when the procedure is finalized.");
+    }
+    validateFileTypes(files);
+
+    OmsDocument document = new OmsDocument();
+    document.setDocumentTypeDe(request.documentTypeDe());
+    document.setDocumentTypeEn(request.documentTypeEn());
+    document.setHelpTextDe(request.helpTextDe());
+    document.setHelpTextEn(request.helpTextEn());
+
+    if (!files.isEmpty()) {
+      document.setReasonForRejection(null);
+      document.setDocumentStatus(OmsDocumentStatus.ACCEPTED);
+      document.setLastDocumentUpload(Instant.now(clock));
+      document.setNote(note);
+    } else {
+      document.setDocumentStatus(OmsDocumentStatus.MISSING);
+    }
+
+    document.setMandatoryDocument(request.mandatoryDocument());
+    document.setUploadInCitizenPortal(request.uploadInCitizenPortal());
+
+    document.setOmsProcedure(omsProcedure);
+    omsDocumentRepository.save(document);
+
+    saveFiles(document, files);
+
+    if (document.isUploadInCitizenPortal() && document.getFiles().isEmpty()) {
+      progressEntryService.createProgressEntryAddDocumentEmployee(
+          omsProcedure, OmsProgressEntryType.DOCUMENT_MISSING_BY_CITIZEN, document);
+    } else if (!document.isUploadInCitizenPortal() && document.getFiles().isEmpty()) {
+      progressEntryService.createProgressEntryAddDocumentEmployee(
+          omsProcedure, OmsProgressEntryType.DOCUMENT_MISSING_BY_EMPLOYEE, document);
+    } else if (!document.isUploadInCitizenPortal() && !document.getFiles().isEmpty()) {
+      progressEntryService.createProgressEntryAddDocumentEmployee(
+          omsProcedure, OmsProgressEntryType.DOCUMENT_ACCEPTED, document);
+    }
+
+    return document.getExternalId();
+  }
+
+  @Transactional
+  public void updateDocumentInformationEmployee(
+      UUID documentId, PatchDocumentInformationRequest request) {
+    OmsDocument omsDocument = loadOmsDocument(documentId);
+
+    if (omsDocument.getOmsProcedure().isFinalized()) {
+      throw new BadRequestException(
+          "Document information cannot be updated when the procedure is finalized.");
+    }
+    if (omsDocument.getDocumentStatus() != OmsDocumentStatus.MISSING) {
+      throw new BadRequestException("Document information can only be updated in MISSING status");
+    }
+
+    String oldDocumentTypeDe = omsDocument.getDocumentTypeDe();
+    String oldHelpTextDe = omsDocument.getHelpTextDe();
+    omsDocument.setDocumentTypeDe(request.documentTypeDe());
+    omsDocument.setDocumentTypeEn(request.documentTypeEn());
+    omsDocument.setHelpTextDe(request.helpTextDe());
+    omsDocument.setHelpTextEn(request.helpTextEn());
+    omsDocument.setMandatoryDocument(request.mandatoryDocument());
+    omsDocument.setUploadInCitizenPortal(request.uploadInCitizenPortal());
+
+    if (!Objects.equals(oldDocumentTypeDe, request.documentTypeDe())
+        || !Objects.equals(oldHelpTextDe, request.helpTextDe())) {
+      OmsProcedure omsProcedure = omsDocument.getOmsProcedure();
+      progressEntryService.createProgressEntryUpdateDocumentInformation(
+          omsProcedure, omsDocument, oldDocumentTypeDe, oldHelpTextDe);
+    }
+  }
+
+  @Transactional
+  public void completeDocumentFileUploadEmployee(UUID documentId, List<MultipartFile> files) {
+    OmsDocument omsDocument = loadOmsDocument(documentId);
+
+    if (omsDocument.getOmsProcedure().isFinalized()) {
+      throw new BadRequestException(
+          "File upload cannot be completed when the procedure is finalized.");
+    }
+    if (omsDocument.getDocumentStatus() == OmsDocumentStatus.ACCEPTED) {
+      throw new BadRequestException("Files can not be uploaded twice");
+    }
+    validateFileTypes(files);
+
+    saveFiles(omsDocument, files);
+    omsDocument.setReasonForRejection(null);
+    omsDocument.setDocumentStatus(OmsDocumentStatus.ACCEPTED);
+    omsDocument.setLastDocumentUpload(Instant.now(clock));
+
+    OmsProcedure omsProcedure = omsDocument.getOmsProcedure();
+    progressEntryService.createProgressEntryCompleteDocumentFileUploadEmployee(
+        omsProcedure, omsDocument);
+  }
+
+  @Transactional
+  public void deleteDocumentEmployee(UUID documentId) {
+    OmsDocument omsDocument = loadOmsDocument(documentId);
+
+    OmsProcedure omsProcedure = omsDocument.getOmsProcedure();
+    if (omsProcedure.isFinalized()) {
+      throw new BadRequestException("Documents cannot be deleted when the procedure is finalized.");
+    }
+
+    deleteDocument(omsDocument);
+    progressEntryService.createProgressEntryForDocumentDeletion(omsProcedure, omsDocument);
+  }
+
+  @Transactional
+  public void updateDocumentNoteEmployee(UUID documentId, PatchDocumentNoteRequest request) {
+    OmsDocument omsDocument = loadOmsDocument(documentId);
+
+    if (omsDocument.getOmsProcedure().isFinalized()) {
+      throw new BadRequestException(
+          "Document note can not be updated when the procedure is finalized.");
+    }
+    if (omsDocument.getFiles().isEmpty()) {
+      throw new BadRequestException("Document note can not be updated when no files are uploaded");
+    }
+
+    omsDocument.setNote(request.note());
+  }
+
+  @Transactional
+  public void reviewDocumentEmployee(UUID documentId, PatchDocumentReviewRequest request) {
+    OmsDocument document = loadOmsDocument(documentId);
+
+    if (document.getOmsProcedure().isFinalized()) {
+      throw new BadRequestException("Document cannot be reviewed when the procedure is finalized.");
+    }
+    if (document.getDocumentStatus() != OmsDocumentStatus.SUBMITTED) {
+      throw new BadRequestException("Only submitted documents can be reviewed");
+    }
+
+    switch (request.result()) {
+      case ACCEPTED:
+        if (!isBlank(request.reasonForRejection())) {
+          logger.warn(
+              "Ignoring reasonForRejection for accepted document: {}",
+              request.reasonForRejection());
+        }
+        document.setReasonForRejection(null);
+        document.setDocumentStatus(OmsDocumentStatus.ACCEPTED);
+        break;
+      case REJECTED:
+        if (isBlank(request.reasonForRejection())) {
+          throw new BadRequestException("reasonForRejection must not be blank");
+        }
+        deleteAllFiles(document);
+        document.setReasonForRejection(request.reasonForRejection());
+        document.setDocumentStatus(OmsDocumentStatus.REJECTED);
+    }
+  }
+
+  private void deleteAllFiles(OmsDocument document) {
+    omsFileRepository.deleteAll(document.getFiles());
+    document.getFiles().clear();
+  }
+
+  private OmsProcedure loadOmsProcedure(UUID externalId) {
+    return omsProcedureRepository
+        .findByExternalId(externalId)
+        .orElseThrow(() -> new NotFoundException("Procedure not found"));
+  }
+
+  private OmsDocument loadOmsDocument(UUID externalId) {
+    return omsDocumentRepository
+        .findById(externalId)
+        .orElseThrow(() -> new NotFoundException("Document not found"));
+  }
+
+  private void validateFileTypes(List<MultipartFile> files) {
+    List<String> allowedFileTypes =
+        List.of(APPLICATION_PDF_VALUE, IMAGE_JPEG_VALUE, IMAGE_PNG_VALUE);
+
+    for (MultipartFile file : files) {
+      String contentType = file.getContentType();
+      if (!allowedFileTypes.contains(contentType)) {
+        throw new BadRequestException(
+            "Invalid file type: " + contentType + ". Only PDF, JPG, and PNG are allowed.");
+      }
+    }
+  }
+
+  private byte[] getBytes(MultipartFile file) {
+    try {
+      return file.getBytes();
+    } catch (IOException e) {
+      throw new BadRequestException("Corrupt file content");
+    }
+  }
+
+  private void saveFiles(OmsDocument omsDocument, List<MultipartFile> files) {
+    for (MultipartFile file : files) {
+      OmsFile omsFile = new OmsFile();
+      omsFile.setFileName(file.getOriginalFilename());
+      omsFile.setContent(getBytes(file));
+      omsFile.setFileType(getFileType(file.getContentType()));
+      omsFile.setCreatedDate(Instant.now(clock));
+      omsFile.setDocument(omsDocument);
+
+      omsFileRepository.save(omsFile);
+      omsDocument.getFiles().add(omsFile);
+    }
+  }
+
+  private FileTypeDto getFileType(String contentType) {
+    if (contentType == null || contentType.isBlank()) {
+      throw new BadRequestException("Content type is missing or empty.");
+    }
+
+    return switch (contentType) {
+      case APPLICATION_PDF_VALUE -> FileTypeDto.PDF;
+      case IMAGE_JPEG_VALUE -> FileTypeDto.JPEG;
+      case IMAGE_PNG_VALUE -> FileTypeDto.PNG;
+      default ->
+          throw new BadRequestException(
+              "Invalid file type: " + contentType + ". Only PDF, JPG, and PNG are allowed.");
+    };
+  }
+
+  private void deleteDocument(OmsDocument omsDocument) {
+    OmsProcedure omsProcedure = omsDocument.getOmsProcedure();
+    omsDocument.setOmsProcedure(null);
+    omsProcedure.getDocuments().remove(omsDocument);
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/DocumentDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/DocumentDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..daa9376874b073b2798a7a40bbc7a2925208496b
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/DocumentDto.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.api;
+
+import de.eshg.officialmedicalservice.file.api.OmsFileDto;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import java.time.Instant;
+import java.util.List;
+import java.util.UUID;
+
+@Schema(name = "Document")
+public record DocumentDto(
+    @NotNull UUID id,
+    @NotNull String documentTypeDe,
+    String documentTypeEn,
+    String helpTextDe,
+    String helpTextEn,
+    @NotNull DocumentStatusDto documentStatus,
+    Instant lastDocumentUpload,
+    @NotNull @Valid List<OmsFileDto> files,
+    String note,
+    @NotNull boolean mandatoryDocument,
+    @NotNull boolean uploadInCitizenPortal,
+    String reasonForRejection) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/DocumentStatusDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/DocumentStatusDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd428be5b0b079adec992a0da95e797c6b422a95
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/DocumentStatusDto.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.api;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(name = "DocumentStatus")
+public enum DocumentStatusDto {
+  MISSING,
+  SUBMITTED,
+  REJECTED,
+  ACCEPTED,
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/GetDocumentsResponse.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/GetDocumentsResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..201d5c5dd611dcba3fb66a2de31524db5536cf8a
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/GetDocumentsResponse.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.api;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import java.util.List;
+
+public record GetDocumentsResponse(@NotNull @Valid List<DocumentDto> documents) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentInformationRequest.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentInformationRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..84d590de203e2a75c7eb0d854963ec72a35ec296
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentInformationRequest.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.api;
+
+import jakarta.validation.constraints.NotNull;
+
+public record PatchDocumentInformationRequest(
+    @NotNull String documentTypeDe,
+    String documentTypeEn,
+    String helpTextDe,
+    String helpTextEn,
+    @NotNull boolean mandatoryDocument,
+    @NotNull boolean uploadInCitizenPortal) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentNoteRequest.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentNoteRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..845c1516adf9b4e416a84e973ad4f3dd32af86e3
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentNoteRequest.java
@@ -0,0 +1,8 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.api;
+
+public record PatchDocumentNoteRequest(String note) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentReviewRequest.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentReviewRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cf34016fcb1d33a93e739e38a4217521f789294
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PatchDocumentReviewRequest.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.api;
+
+import jakarta.validation.constraints.NotNull;
+
+public record PatchDocumentReviewRequest(
+    @NotNull ReviewResultDto result, String reasonForRejection) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PostDocumentRequest.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PostDocumentRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5266ec8cb892b498948680069d9d1736e65d2931
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/PostDocumentRequest.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.api;
+
+import jakarta.validation.constraints.NotNull;
+
+public record PostDocumentRequest(
+    @NotNull String documentTypeDe,
+    String documentTypeEn,
+    String helpTextDe,
+    String helpTextEn,
+    @NotNull boolean mandatoryDocument,
+    @NotNull boolean uploadInCitizenPortal) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/ReviewResultDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/ReviewResultDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..72602a0752aee459c5d32c40917b0529e8e041ff
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/api/ReviewResultDto.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.api;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(name = "ReviewResult")
+public enum ReviewResultDto {
+  ACCEPTED,
+  REJECTED
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocument.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocument.java
new file mode 100644
index 0000000000000000000000000000000000000000..7cf239e4df0b35e85b6119b2a5d4f97ca383d3fa
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocument.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.persistence.entity;
+
+import de.eshg.domain.model.GloballyUniqueEntityBase;
+import de.eshg.lib.common.DataSensitivity;
+import de.eshg.lib.common.SensitivityLevel;
+import de.eshg.officialmedicalservice.file.persistence.entity.OmsFile;
+import de.eshg.officialmedicalservice.file.persistence.entity.OmsFile_;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.OrderBy;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.NotNull;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import org.hibernate.annotations.JdbcType;
+import org.hibernate.dialect.PostgreSQLEnumJdbcType;
+
+@Entity
+@Table(indexes = @Index(columnList = "oms_procedure_id"))
+public class OmsDocument extends GloballyUniqueEntityBase {
+
+  @ManyToOne(optional = false)
+  @JoinColumn(name = "oms_procedure_id")
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private OmsProcedure omsProcedure;
+
+  @Column(nullable = false)
+  @NotNull
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private String documentTypeDe;
+
+  @Column
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private String documentTypeEn;
+
+  @Column
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private String helpTextDe;
+
+  @Column
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private String helpTextEn;
+
+  @Column(nullable = false)
+  @NotNull
+  @JdbcType(PostgreSQLEnumJdbcType.class)
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private OmsDocumentStatus documentStatus;
+
+  @Column
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private Instant lastDocumentUpload;
+
+  @Column
+  @OneToMany(
+      mappedBy = OmsFile_.DOCUMENT,
+      cascade = {CascadeType.PERSIST, CascadeType.REMOVE},
+      orphanRemoval = true)
+  @OrderBy("createdDate")
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private final List<OmsFile> files = new ArrayList<>();
+
+  @Column
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private String note;
+
+  @Column(nullable = false)
+  @NotNull
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private boolean mandatoryDocument;
+
+  @Column(nullable = false)
+  @NotNull
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private boolean uploadInCitizenPortal;
+
+  @Column
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private String reasonForRejection;
+
+  public OmsProcedure getOmsProcedure() {
+    return omsProcedure;
+  }
+
+  public void setOmsProcedure(OmsProcedure omsProcedure) {
+    this.omsProcedure = omsProcedure;
+  }
+
+  public String getDocumentTypeDe() {
+    return documentTypeDe;
+  }
+
+  public void setDocumentTypeDe(String documentTypeDe) {
+    this.documentTypeDe = documentTypeDe;
+  }
+
+  public String getDocumentTypeEn() {
+    return documentTypeEn;
+  }
+
+  public void setDocumentTypeEn(String documentTypeEn) {
+    this.documentTypeEn = documentTypeEn;
+  }
+
+  public String getHelpTextDe() {
+    return helpTextDe;
+  }
+
+  public void setHelpTextDe(String helpTextDe) {
+    this.helpTextDe = helpTextDe;
+  }
+
+  public String getHelpTextEn() {
+    return helpTextEn;
+  }
+
+  public void setHelpTextEn(String helpTextEn) {
+    this.helpTextEn = helpTextEn;
+  }
+
+  public OmsDocumentStatus getDocumentStatus() {
+    return documentStatus;
+  }
+
+  public void setDocumentStatus(OmsDocumentStatus documentStatus) {
+    this.documentStatus = documentStatus;
+  }
+
+  public Instant getLastDocumentUpload() {
+    return lastDocumentUpload;
+  }
+
+  public void setLastDocumentUpload(Instant lastDocumentUpload) {
+    this.lastDocumentUpload = lastDocumentUpload;
+  }
+
+  public List<OmsFile> getFiles() {
+    return files;
+  }
+
+  public String getNote() {
+    return note;
+  }
+
+  public void setNote(String note) {
+    this.note = note;
+  }
+
+  public boolean isMandatoryDocument() {
+    return mandatoryDocument;
+  }
+
+  public void setMandatoryDocument(boolean mandatoryDocument) {
+    this.mandatoryDocument = mandatoryDocument;
+  }
+
+  public boolean isUploadInCitizenPortal() {
+    return uploadInCitizenPortal;
+  }
+
+  public void setUploadInCitizenPortal(boolean uploadInCitizenPortal) {
+    this.uploadInCitizenPortal = uploadInCitizenPortal;
+  }
+
+  public String getReasonForRejection() {
+    return reasonForRejection;
+  }
+
+  public void setReasonForRejection(String reasonForRejection) {
+    this.reasonForRejection = reasonForRejection;
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocumentRepository.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocumentRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..96c4bc5f2f93fcb9b383032edfdc59be8d434f67
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocumentRepository.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.persistence.entity;
+
+import java.util.UUID;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface OmsDocumentRepository extends JpaRepository<OmsDocument, UUID> {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocumentStatus.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocumentStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..30fc9e6fa8b7f4ae2da12bbac2ad721b05fb5642
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/document/persistence/entity/OmsDocumentStatus.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.document.persistence.entity;
+
+public enum OmsDocumentStatus {
+  MISSING,
+  SUBMITTED,
+  REJECTED,
+  ACCEPTED,
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileController.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileController.java
new file mode 100644
index 0000000000000000000000000000000000000000..033fe94c57c36aa9cc7c305efff53f9fb2f332dc
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileController.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.file;
+
+import de.eshg.rest.service.security.config.BaseUrls;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.UUID;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(path = OmsFileController.BASE_URL, produces = MediaType.APPLICATION_JSON_VALUE)
+@Tag(name = "OmsFile")
+public class OmsFileController {
+  public static final String BASE_URL = BaseUrls.OfficialMedicalService.EMPLOYEE_API;
+  public static final String FILE_URL = "/file";
+
+  private final OmsFileService omsFileService;
+
+  public OmsFileController(OmsFileService omsFileService) {
+    this.omsFileService = omsFileService;
+  }
+
+  @GetMapping(path = FILE_URL + "/{fileId}")
+  @Operation(summary = "Download file from oms document.")
+  @Transactional(readOnly = true)
+  @ApiResponse(
+      responseCode = "200",
+      content =
+          @Content(
+              mediaType = MediaType.APPLICATION_OCTET_STREAM_VALUE,
+              schema = @Schema(format = "binary")))
+  public ResponseEntity<byte[]> getDownloadFile(@PathVariable("fileId") UUID fileId) {
+    return omsFileService.downloadDocumentFileEmployee(fileId);
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileMapper.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..332757b6735a96e8d582645790e2daf0bfe765a8
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileMapper.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.file;
+
+import de.eshg.officialmedicalservice.file.api.OmsFileDto;
+import de.eshg.officialmedicalservice.file.persistence.entity.OmsFile;
+import java.util.Collections;
+import java.util.List;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OmsFileMapper {
+
+  public List<OmsFileDto> toInterfaceType(List<OmsFile> files) {
+    if (files == null) {
+      return Collections.emptyList();
+    }
+    return files.stream()
+        .sorted((file1, file2) -> file1.getFileName().compareToIgnoreCase(file2.getFileName()))
+        .map(this::toInterfaceType)
+        .toList();
+  }
+
+  public OmsFileDto toInterfaceType(OmsFile file) {
+    if (file == null) {
+      return null;
+    }
+    return new OmsFileDto(
+        file.getExternalId(),
+        file.getFileName(),
+        file.getFileType(),
+        file.getContent().length,
+        file.getCreatedDate());
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileService.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1dc6010d014f2b064512adb272be8eb4cb6abe74
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/OmsFileService.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.file;
+
+import de.eshg.lib.procedure.model.FileTypeDto;
+import de.eshg.officialmedicalservice.file.persistence.entity.OmsFile;
+import de.eshg.officialmedicalservice.file.persistence.entity.OmsFileRepository;
+import de.eshg.rest.service.error.BadRequestException;
+import de.eshg.rest.service.error.NotFoundException;
+import java.nio.charset.StandardCharsets;
+import java.util.UUID;
+import org.springframework.http.ContentDisposition;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class OmsFileService {
+
+  private final OmsFileRepository omsFileRepository;
+
+  public OmsFileService(OmsFileRepository omsFileRepository) {
+    this.omsFileRepository = omsFileRepository;
+  }
+
+  @Transactional
+  public ResponseEntity<byte[]> downloadDocumentFileEmployee(UUID fileId) {
+    OmsFile omsFile = loadOmsFile(fileId);
+
+    ContentDisposition contentDisposition =
+        ContentDisposition.attachment()
+            .filename(omsFile.getFileName(), StandardCharsets.UTF_8)
+            .build();
+
+    return ResponseEntity.ok()
+        .contentType(getMediaType(omsFile.getFileType()))
+        .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString())
+        .body(omsFile.getContent());
+  }
+
+  private OmsFile loadOmsFile(UUID fileId) {
+    return omsFileRepository
+        .findById(fileId)
+        .orElseThrow(() -> new NotFoundException("File not found"));
+  }
+
+  private MediaType getMediaType(FileTypeDto fileType) {
+    return switch (fileType) {
+      case JPEG -> MediaType.IMAGE_JPEG;
+      case PNG -> MediaType.IMAGE_PNG;
+      case PDF -> MediaType.APPLICATION_PDF;
+      default -> throw new BadRequestException("Invalid file type");
+    };
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/api/OmsFileDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/api/OmsFileDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..f09ae8fe2ea27c8e3aaefdfcba97ab2956dd359d
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/api/OmsFileDto.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.file.api;
+
+import de.eshg.lib.procedure.model.FileTypeDto;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import java.time.Instant;
+import java.util.UUID;
+
+@Schema(name = "OmsFile")
+public record OmsFileDto(
+    @NotNull UUID id,
+    @NotNull String name,
+    @NotNull FileTypeDto fileType,
+    @NotNull int size,
+    @NotNull Instant creationDate) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/persistence/entity/OmsFile.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/persistence/entity/OmsFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..427d1d1d0b391b3cf0fb6c79d09b6daadffe0b2d
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/persistence/entity/OmsFile.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.file.persistence.entity;
+
+import de.eshg.domain.model.GloballyUniqueEntityBase;
+import de.eshg.lib.common.DataSensitivity;
+import de.eshg.lib.common.SensitivityLevel;
+import de.eshg.lib.procedure.model.FileTypeDto;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocument;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.validation.constraints.NotNull;
+import java.time.Instant;
+import org.hibernate.annotations.JdbcType;
+import org.hibernate.dialect.PostgreSQLEnumJdbcType;
+
+@Entity
+@Table(indexes = @Index(columnList = "document_id"))
+public class OmsFile extends GloballyUniqueEntityBase {
+
+  @ManyToOne(optional = false)
+  @JoinColumn(name = "document_id")
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private OmsDocument document;
+
+  @Column(nullable = false)
+  @NotNull
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private String fileName;
+
+  @Column(nullable = false)
+  @NotNull
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private byte[] content;
+
+  @Column(nullable = false)
+  @NotNull
+  @JdbcType(PostgreSQLEnumJdbcType.class)
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private FileTypeDto fileType;
+
+  @Column(nullable = false)
+  @NotNull
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private Instant createdDate;
+
+  public OmsDocument getDocument() {
+    return document;
+  }
+
+  public void setDocument(OmsDocument document) {
+    this.document = document;
+  }
+
+  public String getFileName() {
+    return fileName;
+  }
+
+  public void setFileName(String fileName) {
+    this.fileName = fileName;
+  }
+
+  public byte[] getContent() {
+    return content;
+  }
+
+  public void setContent(byte[] content) {
+    this.content = content;
+  }
+
+  public FileTypeDto getFileType() {
+    return fileType;
+  }
+
+  public void setFileType(FileTypeDto fileType) {
+    this.fileType = fileType;
+  }
+
+  public Instant getCreatedDate() {
+    return createdDate;
+  }
+
+  public void setCreatedDate(Instant createdDate) {
+    this.createdDate = createdDate;
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/persistence/entity/OmsFileRepository.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/persistence/entity/OmsFileRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..74c06b5e9c6346652c5c4a648b0e707c0475cd5c
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/file/persistence/entity/OmsFileRepository.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.file.persistence.entity;
+
+import java.util.UUID;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface OmsFileRepository extends JpaRepository<OmsFile, UUID> {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/MailClient.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/MailClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..77ff8f8f2e5d065caf202afd3cc2eb50903961d1
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/MailClient.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.notification;
+
+import de.eshg.base.mail.MailApi;
+import de.eshg.base.mail.SendEmailRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MailClient {
+  private static final Logger log = LoggerFactory.getLogger(MailClient.class);
+
+  private final MailApi mailApi;
+
+  public MailClient(MailApi mailApi) {
+    this.mailApi = mailApi;
+  }
+
+  void sendMail(String to, String from, String subject, String text) {
+    log.info("Sending E-Mail notification");
+
+    SendEmailRequest sendEmailRequest = new SendEmailRequest(to, from, subject, text);
+    mailApi.sendEmail(sendEmailRequest);
+
+    log.info("E-Mail notification sent");
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationProperties.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..54c844465eefe720a63709b22b10ee4c45d2b39e
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationProperties.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.notification;
+
+import jakarta.validation.constraints.NotNull;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.validation.annotation.Validated;
+
+@Validated
+@ConfigurationProperties(prefix = "de.eshg.official-medical-service.notification")
+public record NotificationProperties(@NotNull String fromAddress, @NotNull String greeting) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationService.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationService.java
new file mode 100644
index 0000000000000000000000000000000000000000..65a59066fdc688091cd1fb8f1f00f23dee249c07
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationService.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.notification;
+
+import de.eshg.lib.rest.oauth.client.commons.ModuleClientAuthenticator;
+import de.eshg.officialmedicalservice.procedure.api.AffectedPersonDto;
+import java.util.List;
+import java.util.function.IntSupplier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.context.SecurityContextHolderStrategy;
+import org.springframework.stereotype.Service;
+import org.springframework.web.util.UriComponentsBuilder;
+
+@Service
+public class NotificationService {
+
+  private static final Logger log = LoggerFactory.getLogger(NotificationService.class);
+
+  private static final String NOTIFICATION_IS_DISABLED =
+      "Für diesen Vorgang ist der Mailversand deaktiviert.";
+  private static final String MISSING_ADDRESSES =
+      "Für diese Person sind keine Mailadressen erfasst.";
+
+  public record NotificationSummary(String subject, int numSentMails, String notSentBecause) {
+    @Override
+    public String toString() {
+      return "Benachrichtigung mit Betreff '"
+          + subject
+          + "': "
+          + (notSentBecause == null
+              ? "gesendet an " + numSentMails + " Mailadresse(n)"
+              : "nicht versendet: " + notSentBecause);
+    }
+  }
+
+  private static final String CITIZEN_PORTAL_OMS_LOGIN_PATH =
+      "amtsärztlichegutachten/allesnurgeraten/meine-termine";
+
+  private final ModuleClientAuthenticator moduleClientAuthenticator;
+  private final MailClient mailClient;
+  private final NotificationProperties notificationProperties;
+  private final NotificationText notificationText;
+  private final String citizenPortalUrl;
+  private final SecurityContextHolderStrategy securityContextHolderStrategy =
+      SecurityContextHolder.getContextHolderStrategy();
+
+  @FunctionalInterface
+  public interface MailEnabledProvider {
+    boolean isSendEmailNotifications();
+  }
+
+  public NotificationService(
+      ModuleClientAuthenticator moduleClientAuthenticator,
+      MailClient mailClient,
+      NotificationProperties notificationProperties,
+      NotificationText notificationText,
+      @Value("${eshg.citizen-portal.reverse-proxy.url}") String citizenPortalUrl) {
+    this.moduleClientAuthenticator = moduleClientAuthenticator;
+    this.mailClient = mailClient;
+    this.notificationProperties = notificationProperties;
+    this.notificationText = notificationText;
+    this.citizenPortalUrl = citizenPortalUrl;
+  }
+
+  public NotificationSummary notifyNewCitizenUser(
+      MailEnabledProvider mailEnabledProvider, AffectedPersonDto person, String accessCode) {
+
+    String newCitizenUserSubject = notificationText.getNewCitizenUserSubject();
+    String newCitizenUserBody =
+        notificationText.assembleNewCitizenUserBody(
+            person.firstName(),
+            person.lastName(),
+            buildLoginUrl(accessCode),
+            accessCode,
+            notificationProperties.greeting());
+    return doNotification(
+        mailEnabledProvider,
+        person,
+        newCitizenUserSubject,
+        () ->
+            sendMailWithModuleClientAuthentication(
+                newCitizenUserSubject, newCitizenUserBody, person));
+  }
+
+  private final NotificationSummary doNotification(
+      MailEnabledProvider procedure,
+      AffectedPersonDto person,
+      String subject,
+      IntSupplier sendMail) {
+
+    if (!procedure.isSendEmailNotifications()) {
+      return new NotificationSummary(subject, 0, NOTIFICATION_IS_DISABLED);
+    }
+    List<String> mailAddresses = person.emailAddresses();
+    if (mailAddresses.isEmpty()) {
+      return new NotificationSummary(subject, 0, MISSING_ADDRESSES);
+    }
+
+    int numSentMails = sendMail.getAsInt();
+    return new NotificationSummary(subject, numSentMails, null);
+  }
+
+  private final int sendMailWithModuleClientAuthentication(
+      String subject, String body, AffectedPersonDto personDto) {
+    SecurityContext previousContext = securityContextHolderStrategy.getContext();
+    try {
+      securityContextHolderStrategy.clearContext();
+      return moduleClientAuthenticator.doWithModuleClientAuthentication(
+          () -> doSendMail(subject, body, personDto));
+    } finally {
+      securityContextHolderStrategy.setContext(previousContext);
+    }
+  }
+
+  private final int doSendMail(String subject, String body, AffectedPersonDto personDto) {
+    log.info("send mail(s): " + subject);
+
+    for (String emailAddress : personDto.emailAddresses()) {
+      mailClient.sendMail(emailAddress, notificationProperties.fromAddress(), subject, body);
+    }
+    return personDto.emailAddresses().size();
+  }
+
+  private String buildLoginUrl(String accessCode) {
+    return UriComponentsBuilder.fromUriString(citizenPortalUrl)
+        .pathSegment(CITIZEN_PORTAL_OMS_LOGIN_PATH)
+        .queryParam("access_code", accessCode)
+        .build()
+        .toUriString();
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationText.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationText.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4cfeee6386a71a3ce422b393c543c7e46a60813
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/notification/NotificationText.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.notification;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+import org.springframework.util.FileCopyUtils;
+
+@Component
+public class NotificationText {
+
+  private final DateTimeFormatter appointmentStartFormat =
+      DateTimeFormatter.ofPattern("dd.MM.yyyy, HH:mm", Locale.GERMAN);
+
+  @Value("${de.eshg.official-medical-service.notification.template.new_citizen_user.subject}")
+  private String newCitizenUserSubject;
+
+  @Value("${de.eshg.official-medical-service.notification.template.new_citizen_user.body}")
+  private Resource newCitizenUserBodyTemplate;
+
+  public String getNewCitizenUserSubject() {
+    return newCitizenUserSubject;
+  }
+
+  public String assembleNewCitizenUserBody(
+      String firstName, String lastName, String loginUrl, String accessCode, String greeting) {
+
+    String templateBody = readTemplateBody(newCitizenUserBodyTemplate);
+
+    return String.format(templateBody, firstName, lastName, loginUrl, accessCode, greeting);
+  }
+
+  private static String readTemplateBody(Resource bodyTemplateResource) {
+    try (Reader reader =
+        new InputStreamReader(bodyTemplateResource.getInputStream(), StandardCharsets.UTF_8)) {
+      return FileCopyUtils.copyToString(reader);
+    } catch (IOException e) {
+      throw new UncheckedIOException(e);
+    }
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/person/PersonClient.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/person/PersonClient.java
index 138e2d696486c0fa195eae48d418ac18409524ac..c0f7b352f7fae81fcbf66a0ab34e822c558c8019 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/person/PersonClient.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/person/PersonClient.java
@@ -8,17 +8,20 @@ package de.eshg.officialmedicalservice.person;
 import de.eshg.base.centralfile.PersonApi;
 import de.eshg.base.centralfile.api.person.AddPersonFileStateRequest;
 import de.eshg.base.centralfile.api.person.AddPersonFileStateResponse;
+import de.eshg.base.centralfile.api.person.ExternalAddPersonFileStateRequest;
 import de.eshg.base.centralfile.api.person.GetPersonDiffResponse;
 import de.eshg.base.centralfile.api.person.GetPersonFileStateResponse;
 import de.eshg.base.centralfile.api.person.GetPersonFileStatesRequest;
 import de.eshg.base.centralfile.api.person.GetPersonFileStatesResponse;
 import de.eshg.base.centralfile.api.person.SyncFileStateRequest;
 import de.eshg.base.centralfile.api.person.UpdatePersonRequest;
+import de.eshg.officialmedicalservice.procedure.api.AffectedPersonDto;
 import de.eshg.rest.service.error.BadRequestException;
 import de.eshg.rest.service.error.ErrorCode;
 import de.eshg.rest.service.error.ErrorResponse;
 import java.util.UUID;
 import java.util.function.Supplier;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.HttpClientErrorException;
@@ -58,6 +61,27 @@ public class PersonClient {
     return doAndForwardErrorCodes(() -> personApi.getPersonDiff(fileStateId));
   }
 
+  public UUID createPersonFromExternalSource(AffectedPersonDto person) {
+    ExternalAddPersonFileStateRequest request =
+        new ExternalAddPersonFileStateRequest(
+            StringUtils.trimToNull(person.title()),
+            person.salutation(),
+            person.gender(),
+            person.firstName().trim(),
+            person.lastName().trim(),
+            person.dateOfBirth(),
+            StringUtils.trimToNull(person.nameAtBirth()),
+            StringUtils.trimToNull(person.placeOfBirth()),
+            person.countryOfBirth(),
+            person.emailAddresses(),
+            person.phoneNumbers(),
+            person.contactAddress(),
+            null);
+    AddPersonFileStateResponse personFromExternalSource =
+        personApi.addPersonFromExternalSource(request);
+    return personFromExternalSource.id();
+  }
+
   private <T> T doAndForwardErrorCodes(Supplier<T> action) {
     try {
       return action.get();
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/EmployeeOmsProcedureController.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/EmployeeOmsProcedureController.java
index 5ce09297d1be886b703fa14f5c89167573ece778..13d991b2a66a57e69fddac1be36889b177c97993 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/EmployeeOmsProcedureController.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/EmployeeOmsProcedureController.java
@@ -5,28 +5,41 @@
 
 package de.eshg.officialmedicalservice.procedure;
 
+import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
+
 import de.eshg.api.commons.InlineParameterObject;
 import de.eshg.lib.procedure.api.ProcedureSearchParameters;
 import de.eshg.officialmedicalservice.appointment.OmsAppointmentService;
 import de.eshg.officialmedicalservice.appointment.api.PostOmsAppointmentRequest;
+import de.eshg.officialmedicalservice.document.OmsDocumentService;
+import de.eshg.officialmedicalservice.document.api.GetDocumentsResponse;
+import de.eshg.officialmedicalservice.document.api.PostDocumentRequest;
+import de.eshg.officialmedicalservice.procedure.api.AcceptDraftProcedureResponse;
 import de.eshg.officialmedicalservice.procedure.api.EmployeeOmsProcedureDetailsDto;
 import de.eshg.officialmedicalservice.procedure.api.EmployeeOmsProcedureHeaderDto;
 import de.eshg.officialmedicalservice.procedure.api.EmployeeOmsProcedurePaginationAndSortParameters;
 import de.eshg.officialmedicalservice.procedure.api.EmployeePagedOmsProcedures;
 import de.eshg.officialmedicalservice.procedure.api.GetEmployeeOmsProcedureOverviewResponse;
 import de.eshg.officialmedicalservice.procedure.api.GetOmsProceduresFilterOptionsDto;
+import de.eshg.officialmedicalservice.procedure.api.MedicalOpinionStatusDto;
 import de.eshg.officialmedicalservice.procedure.api.PatchAffectedPersonRequest;
 import de.eshg.officialmedicalservice.procedure.api.PatchConcernRequest;
+import de.eshg.officialmedicalservice.procedure.api.PatchEmployeeOmsProcedureEmailNotificationsRequest;
 import de.eshg.officialmedicalservice.procedure.api.PatchEmployeeOmsProcedureFacilityRequest;
 import de.eshg.officialmedicalservice.procedure.api.PatchEmployeeOmsProcedurePhysicianRequest;
 import de.eshg.officialmedicalservice.procedure.api.PostEmployeeOmsProcedureFacilityRequest;
 import de.eshg.officialmedicalservice.procedure.api.PostEmployeeOmsProcedureRequest;
 import de.eshg.officialmedicalservice.procedure.api.SyncAffectedPersonRequest;
 import de.eshg.officialmedicalservice.procedure.api.SyncFacilityRequest;
+import de.eshg.officialmedicalservice.waitingroom.WaitingRoomService;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomDto;
 import de.eshg.rest.service.security.config.BaseUrls;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.validation.Valid;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
 import java.util.UUID;
 import org.springdoc.core.annotations.ParameterObject;
 import org.springframework.http.MediaType;
@@ -38,7 +51,9 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestPart;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 @RestController
 @RequestMapping(
@@ -56,15 +71,25 @@ public class EmployeeOmsProcedureController {
   public static final String CLOSE_PROCEDURE_URL = "/close";
   public static final String PHYSICIAN_URL = "/physician";
   public static final String APPOINTMENT_URL = "/appointment";
+  public static final String DOCUMENT_URL = "/document";
+  public static final String MEDICAL_OPINION_STATUS_URL = "/medical-opinion-status";
+  public static final String EMAIL_NOTIFICATIONS_URL = "/email-notifications";
+  public static final String WAITING_ROOM_URL = "/waiting-room";
 
   private final EmployeeOmsProcedureService employeeOmsProcedureService;
   private final OmsAppointmentService omsAppointmentService;
+  private final OmsDocumentService omsDocumentService;
+  private final WaitingRoomService waitingRoomService;
 
   public EmployeeOmsProcedureController(
       EmployeeOmsProcedureService employeeOmsProcedureService,
-      OmsAppointmentService omsAppointmentService) {
+      OmsAppointmentService omsAppointmentService,
+      OmsDocumentService omsDocumentService,
+      WaitingRoomService waitingRoomService) {
     this.employeeOmsProcedureService = employeeOmsProcedureService;
     this.omsAppointmentService = omsAppointmentService;
+    this.omsDocumentService = omsDocumentService;
+    this.waitingRoomService = waitingRoomService;
   }
 
   @PostMapping(path = PROCEDURES_URL)
@@ -155,8 +180,8 @@ public class EmployeeOmsProcedureController {
 
   @PatchMapping(path = PROCEDURES_URL + "/{id}" + ACCEPT_DRAFT_URL)
   @Operation(summary = "Accept draft oms procedure")
-  public void acceptDraftProcedure(@PathVariable("id") UUID procedureId) {
-    employeeOmsProcedureService.acceptDraftProcedure(procedureId);
+  public AcceptDraftProcedureResponse acceptDraftProcedure(@PathVariable("id") UUID procedureId) {
+    return employeeOmsProcedureService.acceptDraftProcedure(procedureId);
   }
 
   @PatchMapping(path = PROCEDURES_URL + "/{id}" + CLOSE_PROCEDURE_URL)
@@ -179,4 +204,43 @@ public class EmployeeOmsProcedureController {
       @PathVariable("id") UUID procedureId, @Valid @RequestBody PostOmsAppointmentRequest request) {
     return omsAppointmentService.addAppointmentEmployee(procedureId, request);
   }
+
+  @PostMapping(path = PROCEDURES_URL + "/{id}" + DOCUMENT_URL, consumes = MULTIPART_FORM_DATA_VALUE)
+  @Operation(summary = "Add a document to an oms procedure")
+  public UUID postDocument(
+      @PathVariable("id") UUID id,
+      @RequestPart("postDocumentRequest") @Valid PostDocumentRequest request,
+      @RequestPart(value = "files", required = false) List<MultipartFile> files,
+      @RequestPart(value = "note", required = false) String note) {
+    return omsDocumentService.addDocumentEmployee(
+        id, request, Optional.ofNullable(files).orElse(Collections.emptyList()), note);
+  }
+
+  @GetMapping(path = PROCEDURES_URL + "/{id}" + DOCUMENT_URL)
+  @Operation(summary = "Get all documents for one oms procedure")
+  public GetDocumentsResponse getAllDocuments(@PathVariable("id") UUID id) {
+    return employeeOmsProcedureService.getAllDocuments(id);
+  }
+
+  @PatchMapping(path = PROCEDURES_URL + "/{id}" + MEDICAL_OPINION_STATUS_URL)
+  @Operation(summary = "Updates the medical opinion status of a oms procedure")
+  public void patchMedicalOpinionStatus(
+      @PathVariable("id") UUID externalId, @Valid @RequestBody MedicalOpinionStatusDto request) {
+    employeeOmsProcedureService.updateMedicalOpinionStatus(externalId, request);
+  }
+
+  @PatchMapping(path = PROCEDURES_URL + "/{id}" + EMAIL_NOTIFICATIONS_URL)
+  @Operation(summary = "Updates the whether or not email notifications will be sent")
+  public void patchEmailNotifications(
+      @PathVariable("id") UUID externalId,
+      @Valid @RequestBody PatchEmployeeOmsProcedureEmailNotificationsRequest request) {
+    employeeOmsProcedureService.patchEmailNotifications(externalId, request);
+  }
+
+  @PatchMapping(path = PROCEDURES_URL + "/{id}" + WAITING_ROOM_URL)
+  @Operation(summary = "Update waiting room details for a procedure")
+  public void patchWaitingRoom(
+      @PathVariable("id") UUID id, @Valid @RequestBody WaitingRoomDto request) {
+    waitingRoomService.updateWaitingRoom(id, request);
+  }
 }
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/EmployeeOmsProcedureService.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/EmployeeOmsProcedureService.java
index a0e4df6147057722fddd1d4e9e4e186bad46b279..a304053128191eb3f3d281b1368548faf24e2ea7 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/EmployeeOmsProcedureService.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/EmployeeOmsProcedureService.java
@@ -22,6 +22,7 @@ import de.eshg.base.centralfile.api.person.AddPersonFileStateResponse;
 import de.eshg.base.centralfile.api.person.GetPersonFileStateResponse;
 import de.eshg.base.centralfile.api.person.GetPersonFileStatesRequest;
 import de.eshg.base.centralfile.api.person.GetPersonFileStatesResponse;
+import de.eshg.base.citizenuser.api.CitizenAccessCodeUserDto;
 import de.eshg.base.user.api.UserDto;
 import de.eshg.lib.auditlog.AuditLogger;
 import de.eshg.lib.procedure.api.ProcedureSearchParameters;
@@ -34,15 +35,20 @@ import de.eshg.lib.procedure.mapping.ProcedureMapper;
 import de.eshg.lib.procedure.model.ProcedureStatusDto;
 import de.eshg.lib.procedure.procedures.ProcedureSearchService;
 import de.eshg.lib.procedure.util.ProcedureValidator;
+import de.eshg.lib.rest.oauth.client.commons.ModuleClientAuthenticator;
 import de.eshg.officialmedicalservice.appointment.OmsAppointmentMapper;
 import de.eshg.officialmedicalservice.appointment.persistence.entity.AppointmentState;
 import de.eshg.officialmedicalservice.appointment.persistence.entity.OmsAppointment;
 import de.eshg.officialmedicalservice.appointment.persistence.entity.OmsAppointment_;
 import de.eshg.officialmedicalservice.concern.ConcernMapper;
+import de.eshg.officialmedicalservice.document.OmsDocumentMapper;
+import de.eshg.officialmedicalservice.document.api.GetDocumentsResponse;
 import de.eshg.officialmedicalservice.facility.FacilityClient;
 import de.eshg.officialmedicalservice.facility.FacilityMapper;
+import de.eshg.officialmedicalservice.notification.NotificationService;
 import de.eshg.officialmedicalservice.person.PersonClient;
 import de.eshg.officialmedicalservice.person.PersonMapper;
+import de.eshg.officialmedicalservice.procedure.api.AcceptDraftProcedureResponse;
 import de.eshg.officialmedicalservice.procedure.api.AffectedPersonDto;
 import de.eshg.officialmedicalservice.procedure.api.EmployeeOmsProcedureDetailsDto;
 import de.eshg.officialmedicalservice.procedure.api.EmployeeOmsProcedureHeaderDto;
@@ -52,8 +58,10 @@ import de.eshg.officialmedicalservice.procedure.api.EmployeeOmsProcedureSortKey;
 import de.eshg.officialmedicalservice.procedure.api.EmployeePagedOmsProcedures;
 import de.eshg.officialmedicalservice.procedure.api.FacilityDto;
 import de.eshg.officialmedicalservice.procedure.api.GetOmsProceduresFilterOptionsDto;
+import de.eshg.officialmedicalservice.procedure.api.MedicalOpinionStatusDto;
 import de.eshg.officialmedicalservice.procedure.api.PatchAffectedPersonRequest;
 import de.eshg.officialmedicalservice.procedure.api.PatchConcernRequest;
+import de.eshg.officialmedicalservice.procedure.api.PatchEmployeeOmsProcedureEmailNotificationsRequest;
 import de.eshg.officialmedicalservice.procedure.api.PatchEmployeeOmsProcedureFacilityRequest;
 import de.eshg.officialmedicalservice.procedure.api.PatchEmployeeOmsProcedurePhysicianRequest;
 import de.eshg.officialmedicalservice.procedure.api.PostEmployeeOmsProcedureFacilityRequest;
@@ -63,12 +71,15 @@ import de.eshg.officialmedicalservice.procedure.api.SyncFacilityRequest;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.Concern;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.Concern_;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.Facility;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.MedicalOpinionStatus;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedureRepository;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedureView;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure_;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.Person;
+import de.eshg.officialmedicalservice.user.CitizenAccessCodeUserClient;
 import de.eshg.officialmedicalservice.user.UserClient;
+import de.eshg.officialmedicalservice.waitingroom.WaitingRoomMapper;
 import de.eshg.rest.service.error.BadRequestException;
 import de.eshg.rest.service.error.NotFoundException;
 import de.eshg.rest.service.security.CurrentUserHelper;
@@ -98,8 +109,12 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.UUID;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.context.SecurityContextHolderStrategy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -116,6 +131,12 @@ public class EmployeeOmsProcedureService {
   private final ProgressEntryService progressEntryService;
   private final EntityManager entityManager;
   private final ProcedureSearchService<OmsProcedure> procedureSearchService;
+  private final OmsDocumentMapper omsDocumentMapper;
+  private final NotificationService notificationService;
+  private final SecurityContextHolderStrategy securityContextHolderStrategy =
+      SecurityContextHolder.getContextHolderStrategy();
+  private final ModuleClientAuthenticator moduleClientAuthenticator;
+  private final CitizenAccessCodeUserClient citizenAccessCodeUserClient;
 
   public EmployeeOmsProcedureService(
       OmsProcedureRepository omsProcedureRepository,
@@ -128,7 +149,11 @@ public class EmployeeOmsProcedureService {
       UserClient userClient,
       ProgressEntryService progressEntryService,
       EntityManager entityManager,
-      ProcedureSearchService<OmsProcedure> procedureSearchService) {
+      ProcedureSearchService<OmsProcedure> procedureSearchService,
+      OmsDocumentMapper omsDocumentMapper,
+      NotificationService notificationService,
+      ModuleClientAuthenticator moduleClientAuthenticator,
+      CitizenAccessCodeUserClient citizenAccessCodeUserClient) {
     this.omsProcedureRepository = omsProcedureRepository;
     this.omsProcedureOverviewMapper = omsProcedureOverviewMapper;
     this.omsAppointmentMapper = omsAppointmentMapper;
@@ -140,6 +165,10 @@ public class EmployeeOmsProcedureService {
     this.progressEntryService = progressEntryService;
     this.entityManager = entityManager;
     this.procedureSearchService = procedureSearchService;
+    this.omsDocumentMapper = omsDocumentMapper;
+    this.notificationService = notificationService;
+    this.moduleClientAuthenticator = moduleClientAuthenticator;
+    this.citizenAccessCodeUserClient = citizenAccessCodeUserClient;
   }
 
   @Transactional
@@ -193,12 +222,17 @@ public class EmployeeOmsProcedureService {
         omsProcedureAndAffectedPerson.omsProcedure.getExternalId(),
         ProcedureMapper.toInterfaceType(
             omsProcedureAndAffectedPerson.omsProcedure.getProcedureStatus()),
+        MedicalOpinionStatusDto.valueOf(
+            omsProcedureAndAffectedPerson.omsProcedure.getMedicalOpinionStatus().name()),
+        WaitingRoomMapper.mapToDto(omsProcedureAndAffectedPerson.omsProcedure.getWaitingRoom()),
         omsProcedureAndAffectedPerson.affectedPerson,
         facility,
         mapToConcernDto(omsProcedureAndAffectedPerson.omsProcedure.getConcern()),
         physician.orElse(null),
         omsAppointmentMapper.toInterfaceType(
-            omsProcedureAndAffectedPerson.omsProcedure.getAppointments()));
+            omsProcedureAndAffectedPerson.omsProcedure.getAppointments()),
+        omsProcedureAndAffectedPerson.omsProcedure.isSendEmailNotifications(),
+        omsProcedureAndAffectedPerson.omsProcedure.getCitizenUserId());
   }
 
   @Transactional(readOnly = true)
@@ -255,6 +289,17 @@ public class EmployeeOmsProcedureService {
     return new EmployeePagedOmsProcedures(result, omsProcedureOverviewDtos.size());
   }
 
+  // temporarily skip the current authentication
+  private <T> T disabledCurrentAuthentication(Supplier<T> supplier) {
+    SecurityContext oldContext = securityContextHolderStrategy.getContext();
+    try {
+      securityContextHolderStrategy.clearContext();
+      return supplier.get();
+    } finally {
+      securityContextHolderStrategy.setContext(oldContext);
+    }
+  }
+
   private Stream<OmsProcedureView> convertToProcedureViewStream(OmsProcedure procedure) {
     Concern concern = procedure.getConcern();
     List<OmsAppointment> appointments = procedure.getAppointments();
@@ -427,7 +472,7 @@ public class EmployeeOmsProcedureService {
 
   @Transactional
   public void abortDraftProcedure(UUID externalId) {
-    OmsProcedure omsProcedure = loadOmsProcedure(externalId);
+    OmsProcedure omsProcedure = loadOmsProcedureForUpdate(externalId);
 
     if (omsProcedure.getProcedureStatus() != ProcedureStatus.DRAFT) {
       throw new BadRequestException("Procedure is not in DRAFT status");
@@ -437,19 +482,43 @@ public class EmployeeOmsProcedureService {
   }
 
   @Transactional
-  public void acceptDraftProcedure(UUID externalId) {
-    OmsProcedure omsProcedure = loadOmsProcedureForUpdate(externalId);
+  public AcceptDraftProcedureResponse acceptDraftProcedure(UUID externalId) {
+    OmsProcedureAndAffectedPerson omsProcedureAndAffectedPerson =
+        getOmsProcedureAndAffectedPerson(externalId);
 
+    OmsProcedure omsProcedure = omsProcedureAndAffectedPerson.omsProcedure();
     if (omsProcedure.getProcedureStatus() != ProcedureStatus.DRAFT) {
       throw new BadRequestException("Procedure is not in DRAFT status");
     }
     requireFacility(omsProcedure);
     requireConcern(omsProcedure);
 
+    AffectedPersonDto affectedPersonDto = omsProcedureAndAffectedPerson.affectedPerson();
+    UUID personFileStateId = personClient.createPersonFromExternalSource(affectedPersonDto);
+
+    // temporarily skip the access token authentication (and use a module authentication
+    // instead) in order to create a citizen keycloak user
+    CitizenAccessCodeUserDto citizenAccessCodeUser =
+        disabledCurrentAuthentication(
+            () ->
+                moduleClientAuthenticator.doWithModuleClientAuthentication(
+                    () -> citizenAccessCodeUserClient.addCitizenAccessCodeUser(personFileStateId)));
+    String accessCode = citizenAccessCodeUser.accessCode();
+
+    omsProcedure.setCitizenUserId(citizenAccessCodeUser.userId());
     omsProcedure.updateProcedureStatus(ProcedureStatus.OPEN, clock, auditLogger);
+
+    NotificationService.NotificationSummary notificationSummary =
+        notificationService.notifyNewCitizenUser(
+            omsProcedure::isSendEmailNotifications, affectedPersonDto, accessCode);
+
     omsProcedure.addProgressEntry(
         createSystemProgressEntry(
-            OmsProgressEntryType.PROCEDURE_STARTED.name(), TriggerType.EMPLOYEE));
+            OmsProgressEntryType.PROCEDURE_STARTED.name(),
+            notificationSummary.toString(),
+            TriggerType.EMPLOYEE));
+
+    return new AcceptDraftProcedureResponse(accessCode);
   }
 
   @Transactional
@@ -457,7 +526,7 @@ public class EmployeeOmsProcedureService {
     OmsProcedure omsProcedure = loadOmsProcedureForUpdate(externalID);
 
     if (omsProcedure.isFinalized()) {
-      throw new BadRequestException("Procedure is already in CLOSED status");
+      throw new BadRequestException("Procedure is already finalized.");
     }
     if (omsProcedure.getProcedureStatus() != ProcedureStatus.OPEN) {
       throw new BadRequestException("Procedure is not in OPEN status");
@@ -474,7 +543,8 @@ public class EmployeeOmsProcedureService {
     OmsProcedure omsProcedure = loadOmsProcedureForUpdate(externalId);
 
     if (omsProcedure.isFinalized()) {
-      throw new BadRequestException("Affected person can not be edited in CLOSED status");
+      throw new BadRequestException(
+          "Affected person can not be edited when the procedure is finalized.");
     }
 
     Person person = omsProcedure.findAffectedPerson();
@@ -509,7 +579,8 @@ public class EmployeeOmsProcedureService {
     OmsProcedure procedure = loadOmsProcedureForUpdate(externalId);
 
     if (procedure.isFinalized()) {
-      throw new BadRequestException("Affected person can not be synced in CLOSED status");
+      throw new BadRequestException(
+          "Affected person can not be synced when the procedure is finalized.");
     }
 
     Person person = procedure.getRelatedPersons().getFirst();
@@ -523,7 +594,7 @@ public class EmployeeOmsProcedureService {
 
   @Transactional
   public UUID addFacility(UUID externalId, PostEmployeeOmsProcedureFacilityRequest request) {
-    OmsProcedure procedure = loadOmsProcedure(externalId);
+    OmsProcedure procedure = loadOmsProcedureForUpdate(externalId);
 
     if (procedure.getProcedureStatus() != ProcedureStatus.DRAFT) {
       throw new BadRequestException("Facility can only be added in DRAFT status");
@@ -548,7 +619,7 @@ public class EmployeeOmsProcedureService {
     OmsProcedure procedure = loadOmsProcedureForUpdate(externalId);
 
     if (procedure.isFinalized()) {
-      throw new BadRequestException("Facility can not be edited in CLOSED status");
+      throw new BadRequestException("Facility can not be edited when the procedure is finalized.");
     }
     if (procedure.getProcedureStatus() != ProcedureStatus.DRAFT) {
       throw new BadRequestException("Facility can only be synced in DRAFT status");
@@ -584,7 +655,7 @@ public class EmployeeOmsProcedureService {
     OmsProcedure procedure = loadOmsProcedureForUpdate(externalId);
 
     if (procedure.isFinalized()) {
-      throw new BadRequestException("Facility can not be synced in CLOSED status");
+      throw new BadRequestException("Facility can not be synced when the procedure is finalized.");
     }
     if (procedure.getProcedureStatus() != ProcedureStatus.DRAFT) {
       throw new BadRequestException("Facility can only be synced in DRAFT status");
@@ -605,10 +676,10 @@ public class EmployeeOmsProcedureService {
 
   @Transactional
   public UUID modifyPhysician(UUID externalId, PatchEmployeeOmsProcedurePhysicianRequest request) {
-    OmsProcedure procedure = loadOmsProcedure(externalId);
+    OmsProcedure procedure = loadOmsProcedureForUpdate(externalId);
 
     if (procedure.isFinalized()) {
-      throw new BadRequestException("A physician can not be set in CLOSED status");
+      throw new BadRequestException("A physician can not be set when the procedure is finalized.");
     }
 
     UUID newPhysicianId = request.physicianId();
@@ -625,7 +696,7 @@ public class EmployeeOmsProcedureService {
     OmsProcedure omsProcedure = loadOmsProcedureForUpdate(externalId);
 
     if (omsProcedure.isFinalized()) {
-      throw new BadRequestException("Concern can not be edited in CLOSED status");
+      throw new BadRequestException("Concern can not be edited when the procedure is finalized.");
     }
     if (omsProcedure.getProcedureStatus() != ProcedureStatus.DRAFT) {
       throw new BadRequestException("Procedure is not in DRAFT status");
@@ -641,6 +712,33 @@ public class EmployeeOmsProcedureService {
     }
   }
 
+  @Transactional(readOnly = true)
+  public GetDocumentsResponse getAllDocuments(UUID externalId) {
+    OmsProcedure omsProcedure = loadOmsProcedure(externalId);
+    return new GetDocumentsResponse(omsDocumentMapper.toInterfaceType(omsProcedure.getDocuments()));
+  }
+
+  @Transactional
+  public void updateMedicalOpinionStatus(
+      UUID externalId, MedicalOpinionStatusDto medicalOpinionStatus) {
+    OmsProcedure procedure = loadOmsProcedureForUpdate(externalId);
+
+    if (procedure.isFinalized()) {
+      throw new BadRequestException(
+          "Medical opinion status can not be updated when the procedure is finalized.");
+    }
+
+    procedure.setMedicalOpinionStatus(MedicalOpinionStatus.valueOf(medicalOpinionStatus.name()));
+  }
+
+  @Transactional
+  public void patchEmailNotifications(
+      UUID externalId, PatchEmployeeOmsProcedureEmailNotificationsRequest request) {
+    OmsProcedure procedure = loadOmsProcedureForUpdate(externalId);
+
+    procedure.setSendEmailNotifications(request.sendEmailNotifications());
+  }
+
   private OmsProcedure loadOmsProcedure(UUID externalId) {
     return omsProcedureRepository
         .findByExternalId(externalId)
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/OmsProcedureOverviewMapper.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/OmsProcedureOverviewMapper.java
index d4f915c270b27e2739f3db757918a9f662416136..f371150707a9652cf28daaa580834394a69f896f 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/OmsProcedureOverviewMapper.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/OmsProcedureOverviewMapper.java
@@ -18,10 +18,13 @@ import de.eshg.lib.procedure.domain.model.TaskType;
 import de.eshg.lib.procedure.mapping.ProcedureMapper;
 import de.eshg.officialmedicalservice.concern.ConcernMapper;
 import de.eshg.officialmedicalservice.procedure.api.EmployeeOmsProcedureOverviewDto;
+import de.eshg.officialmedicalservice.procedure.api.MedicalOpinionStatusDto;
 import de.eshg.officialmedicalservice.procedure.api.PostEmployeeOmsProcedureRequest;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.MedicalOpinionStatus;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsTask;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.Person;
+import de.eshg.officialmedicalservice.waitingroom.persistence.entity.WaitingRoom;
 import java.time.Clock;
 import java.time.Instant;
 import java.time.LocalDate;
@@ -48,6 +51,8 @@ public class OmsProcedureOverviewMapper {
 
     procedure.setProcedureType(ProcedureType.OFFICIAL_MEDICAL_SERVICE);
     procedure.updateProcedureStatus(ProcedureStatus.DRAFT, clock, auditLogger);
+    procedure.setMedicalOpinionStatus(MedicalOpinionStatus.IN_PROGRESS);
+    procedure.setWaitingRoom(new WaitingRoom());
 
     OmsTask omsTask = new OmsTask();
     if (currentUserId != null) {
@@ -94,6 +99,7 @@ public class OmsProcedureOverviewMapper {
     return new EmployeeOmsProcedureOverviewDto(
         procedure.getExternalId(),
         ProcedureMapper.toInterfaceType(procedure.getProcedureStatus()),
+        MedicalOpinionStatusDto.valueOf(procedure.getMedicalOpinionStatus().name()),
         firstName,
         lastName,
         dateOfBirth,
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/OmsProgressEntryType.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/OmsProgressEntryType.java
index c947331e212e1f59105400cb19e730fc61d14048..1423ce0e94f18aa09b76a31c071942cc450569f5 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/OmsProgressEntryType.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/OmsProgressEntryType.java
@@ -10,5 +10,18 @@ public enum OmsProgressEntryType {
   SYNC_AFFECTED_PERSON,
   SYNC_FACILITY,
   PHYSICIAN_CHANGED,
-  PROCEDURE_STARTED
+  PROCEDURE_STARTED,
+  DOCUMENT_DELETED,
+  APPOINTMENT_FOR_SELF_BOOKING_ADDED,
+  APPOINTMENT_ADDED_WITH_BOOKING,
+  APPOINTMENT_BOOKED,
+  APPOINTMENT_REBOOKED,
+  APPOINTMENT_CANCELED,
+  APPOINTMENT_OPTION_WITHDRAWN,
+  APPOINTMENT_CLOSED,
+  DOCUMENT_MISSING_BY_CITIZEN,
+  DOCUMENT_MISSING_BY_EMPLOYEE,
+  DOCUMENT_ACCEPTED,
+  DOCUMENT_INFORMATION_CHANGED,
+  DOCUMENT_STATUS_CHANGE_ACCEPTED
 }
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/ProgressEntryService.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/ProgressEntryService.java
index 6d85cca935dd5b1d27737fba580306ddc7f2c9f5..46851359404ec6fa38a79287c1d247716dd136c9 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/ProgressEntryService.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/ProgressEntryService.java
@@ -5,29 +5,32 @@
 
 package de.eshg.officialmedicalservice.procedure;
 
-import de.eshg.base.user.UserApi;
 import de.eshg.base.user.api.UserDto;
 import de.eshg.lib.procedure.domain.factory.SystemProgressEntryFactory;
 import de.eshg.lib.procedure.domain.model.SystemProgressEntry;
 import de.eshg.lib.procedure.domain.model.TriggerType;
+import de.eshg.officialmedicalservice.appointment.api.BookingInfoDto;
+import de.eshg.officialmedicalservice.appointment.api.PostOmsAppointmentRequest;
+import de.eshg.officialmedicalservice.appointment.persistence.entity.OmsAppointment;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocument;
 import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
 import java.time.Clock;
 import java.time.format.DateTimeFormatter;
 import java.util.UUID;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
 @Service
 public class ProgressEntryService {
 
   private final Clock clock;
-  private final UserApi userApi;
   private final DateTimeFormatter dateTimeFormatter =
       DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
   private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
+  private final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
 
-  public ProgressEntryService(Clock clock, UserApi userApi) {
+  public ProgressEntryService(Clock clock) {
     this.clock = clock;
-    this.userApi = userApi;
   }
 
   public void createProgressEntryForUpdateAffectedPerson(
@@ -72,4 +75,197 @@ public class ProgressEntryService {
     progressEntry.setProcedureId(procedure.getId());
     procedure.addProgressEntry(progressEntry);
   }
+
+  public void createProgressEntryForAddingSelfBookingAppointment(OmsProcedure procedure) {
+    String note = "Ein neuer Termin zum Selbstbuchen wurde hinzugefügt.";
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.APPOINTMENT_FOR_SELF_BOOKING_ADDED.name(),
+            note,
+            TriggerType.EMPLOYEE);
+    progressEntry.setProcedureId(procedure.getId());
+    procedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryForAddingAppointmentWithBooking(
+      OmsProcedure procedure, PostOmsAppointmentRequest appointment) {
+
+    String note =
+        "Ein neuer Termin mit Buchung für den "
+            + dateFormatter.format(appointment.bookingInfo().start().atZone(clock.getZone()))
+            + " um "
+            + timeFormatter.format(appointment.bookingInfo().start().atZone(clock.getZone()))
+            + " Uhr wurde hinzugefügt.";
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.APPOINTMENT_ADDED_WITH_BOOKING.name(), note, TriggerType.EMPLOYEE);
+    progressEntry.setProcedureId(procedure.getId());
+    procedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryForRebookedAppointment(
+      OmsProcedure procedure, OmsAppointment oldAppointment, BookingInfoDto bookingInfo) {
+    String note =
+        "Der Termin vom "
+            + dateFormatter.format(oldAppointment.getStart().atZone(clock.getZone()))
+            + " um "
+            + timeFormatter.format(oldAppointment.getStart().atZone(clock.getZone()))
+            + " Uhr wurde auf "
+            + dateFormatter.format(bookingInfo.start().atZone(clock.getZone()))
+            + " um "
+            + timeFormatter.format(bookingInfo.start().atZone(clock.getZone()))
+            + " Uhr umgebucht.";
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.APPOINTMENT_REBOOKED.name(), note, TriggerType.EMPLOYEE);
+    progressEntry.setProcedureId(procedure.getId());
+    procedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryForBookingAppointment(
+      OmsProcedure procedure, BookingInfoDto bookingInfo) {
+    String note =
+        "Ein Termin wurde für "
+            + dateFormatter.format(bookingInfo.start().atZone(clock.getZone()))
+            + " um "
+            + timeFormatter.format(bookingInfo.start().atZone(clock.getZone()))
+            + " Uhr gebucht.";
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.APPOINTMENT_BOOKED.name(), note, TriggerType.EMPLOYEE);
+    progressEntry.setProcedureId(procedure.getId());
+    procedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryForCancelingAppointment(
+      OmsProcedure procedure, OmsAppointment appointment) {
+    String note =
+        "Der Termin vom "
+            + dateFormatter.format(appointment.getStart().atZone(clock.getZone()))
+            + " um "
+            + timeFormatter.format(appointment.getStart().atZone(clock.getZone()))
+            + " Uhr wurde abgesagt.";
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.APPOINTMENT_CANCELED.name(), note, TriggerType.EMPLOYEE);
+    progressEntry.setProcedureId(procedure.getId());
+    procedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryForWithdrawingAppointmentOption(OmsProcedure procedure) {
+    String note = "Eine Terminoption wurde zurückgezogen.";
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.APPOINTMENT_OPTION_WITHDRAWN.name(), note, TriggerType.EMPLOYEE);
+    progressEntry.setProcedureId(procedure.getId());
+    procedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryForClosingAppointment(
+      OmsProcedure procedure, OmsAppointment omsAppointment) {
+    String note =
+        "Der Termin vom "
+            + dateFormatter.format(omsAppointment.getStart().atZone(clock.getZone()))
+            + " um "
+            + timeFormatter.format(omsAppointment.getStart().atZone(clock.getZone()))
+            + " wurde im Buchungsstatus "
+            + omsAppointment.getAppointmentState().getGermanName()
+            + " abgeschlossen.";
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.APPOINTMENT_CLOSED.name(), note, TriggerType.EMPLOYEE);
+    progressEntry.setProcedureId(procedure.getId());
+    procedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryAddDocumentEmployee(
+      OmsProcedure omsProcedure,
+      OmsProgressEntryType omsProgressEntryType,
+      OmsDocument omsDocument) {
+
+    String action = "";
+    if (omsProgressEntryType == OmsProgressEntryType.DOCUMENT_MISSING_BY_CITIZEN) {
+      action = "für Upload durch Bürger:In hinzugefügt.";
+    } else if (omsProgressEntryType == OmsProgressEntryType.DOCUMENT_MISSING_BY_EMPLOYEE) {
+      action = "hinzugefügt.";
+    } else if (omsProgressEntryType == OmsProgressEntryType.DOCUMENT_ACCEPTED) {
+      action = "hinzugefügt und Dateie(n) hochgeladen.";
+    }
+
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            omsProgressEntryType.name(),
+            "Dokument %s %s %s"
+                .formatted(
+                    omsDocument.getDocumentTypeDe(),
+                    !StringUtils.isBlank(omsDocument.getHelpTextDe())
+                        ? "- " + omsDocument.getHelpTextDe()
+                        : "",
+                    action),
+            TriggerType.EMPLOYEE);
+    omsProcedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryUpdateDocumentInformation(
+      OmsProcedure omsProcedure,
+      OmsDocument omsDocument,
+      String oldDocumentTypeDe,
+      String oldHelpTextDe) {
+
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.DOCUMENT_INFORMATION_CHANGED.name(),
+            "Dokument %s %s wurde in %s %s umbenannt."
+                .formatted(
+                    oldDocumentTypeDe,
+                    !StringUtils.isBlank(oldHelpTextDe) ? "- " + oldHelpTextDe : "",
+                    omsDocument.getDocumentTypeDe(),
+                    !StringUtils.isBlank(omsDocument.getHelpTextDe())
+                        ? "- " + omsDocument.getHelpTextDe()
+                        : ""),
+            TriggerType.EMPLOYEE);
+    omsProcedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryCompleteDocumentFileUploadEmployee(
+      OmsProcedure omsProcedure, OmsDocument omsDocument) {
+
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.DOCUMENT_STATUS_CHANGE_ACCEPTED.name(),
+            "Für Dokument %s %s wurden Dateien hinzugefügt."
+                .formatted(
+                    omsDocument.getDocumentTypeDe(),
+                    !StringUtils.isBlank(omsDocument.getHelpTextDe())
+                        ? "- " + omsDocument.getHelpTextDe()
+                        : ""),
+            TriggerType.EMPLOYEE);
+    omsProcedure.addProgressEntry(progressEntry);
+  }
+
+  public void createProgressEntryForDocumentDeletion(OmsProcedure procedure, OmsDocument document) {
+    String changeDescription =
+        new StringBuilder()
+            .append("Dokument ")
+            .append(assembleDocumentDescription(document))
+            .append(" gelöscht.")
+            .toString();
+
+    SystemProgressEntry progressEntry =
+        SystemProgressEntryFactory.createSystemProgressEntry(
+            OmsProgressEntryType.DOCUMENT_DELETED.name(),
+            changeDescription,
+            TriggerType.SYSTEM_AUTOMATIC);
+    progressEntry.setProcedureId(procedure.getId());
+    procedure.addProgressEntry(progressEntry);
+  }
+
+  private String assembleDocumentDescription(OmsDocument document) {
+    StringBuilder documentDescription = new StringBuilder();
+    documentDescription.append(document.getDocumentTypeDe());
+    String helpTextDe = document.getHelpTextDe();
+    if (helpTextDe != null && !helpTextDe.isEmpty())
+      documentDescription.append(" - ").append(helpTextDe);
+    return documentDescription.toString();
+  }
 }
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/AcceptDraftProcedureResponse.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/AcceptDraftProcedureResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f880b5252e32e126799cf11801dd7df47ce4369
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/AcceptDraftProcedureResponse.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.procedure.api;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+
+@Schema(name = "AcceptDraftProcedureResponse")
+public record AcceptDraftProcedureResponse(@NotNull String accessCode) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/EmployeeOmsProcedureDetailsDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/EmployeeOmsProcedureDetailsDto.java
index 19b3c676cd6ab453a1fbf2fcc80bbde488e46683..b5c719966e4c1262bb2fb1f9c4d0bf8858985112 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/EmployeeOmsProcedureDetailsDto.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/EmployeeOmsProcedureDetailsDto.java
@@ -8,6 +8,7 @@ package de.eshg.officialmedicalservice.procedure.api;
 import de.eshg.base.user.api.UserDto;
 import de.eshg.lib.procedure.model.ProcedureStatusDto;
 import de.eshg.officialmedicalservice.appointment.api.OmsAppointmentDto;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomDto;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
@@ -18,8 +19,12 @@ import java.util.UUID;
 public record EmployeeOmsProcedureDetailsDto(
     @NotNull UUID id,
     @NotNull ProcedureStatusDto status,
+    @NotNull MedicalOpinionStatusDto medicalOpinionStatus,
+    @NotNull @Valid WaitingRoomDto waitingRoom,
     @NotNull @Valid AffectedPersonDto affectedPerson,
     @Valid FacilityDto facility,
     @Valid ConcernDto concern,
     @Valid UserDto physician,
-    @NotNull @Valid List<OmsAppointmentDto> appointments) {}
+    @NotNull @Valid List<OmsAppointmentDto> appointments,
+    @NotNull boolean sendEmailNotifications,
+    UUID citizenUserId) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/EmployeeOmsProcedureOverviewDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/EmployeeOmsProcedureOverviewDto.java
index b2e1824d7c50db28718f7524753931d4bf176038..9f64ed0bba8405d47ed5ae5f3d70237c44a3d985 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/EmployeeOmsProcedureOverviewDto.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/EmployeeOmsProcedureOverviewDto.java
@@ -17,6 +17,7 @@ import java.util.UUID;
 public record EmployeeOmsProcedureOverviewDto(
     @NotNull UUID id,
     @NotNull ProcedureStatusDto status,
+    @NotNull MedicalOpinionStatusDto medicalOpinionStatus,
     String firstName,
     String lastName,
     LocalDate dateOfBirth,
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/FacilityDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/FacilityDto.java
index 72b658cbbcc48db80e0d6d3be5b553662886935a..80c1af83fcb37fcc1fd9ec61bf9ea99cf1799597 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/FacilityDto.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/FacilityDto.java
@@ -5,9 +5,9 @@
 
 package de.eshg.officialmedicalservice.procedure.api;
 
-import de.eshg.CustomValidations.MandatoryEmailAddressConstraint;
 import de.eshg.base.address.AddressDto;
 import de.eshg.base.centralfile.api.facility.FacilityContactPersonDto;
+import de.eshg.validation.constraints.MandatoryEmailAddressConstraint;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/MedicalOpinionStatusDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/MedicalOpinionStatusDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d4499f29d5254eab939dec35e6b74a22a516b20
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/MedicalOpinionStatusDto.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.procedure.api;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(name = "MedicalOpinionStatus")
+public enum MedicalOpinionStatusDto {
+  IN_PROGRESS,
+  ACCOMPLISHED,
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/PatchEmployeeOmsProcedureEmailNotificationsRequest.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/PatchEmployeeOmsProcedureEmailNotificationsRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a031e63ecd33631aaeb3c4bdb9b518bb63bddbd3
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/api/PatchEmployeeOmsProcedureEmailNotificationsRequest.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.procedure.api;
+
+import jakarta.validation.constraints.NotNull;
+
+public record PatchEmployeeOmsProcedureEmailNotificationsRequest(
+    @NotNull boolean sendEmailNotifications) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/MedicalOpinionStatus.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/MedicalOpinionStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..74465fb6321be0477a9f1800323fd0d34699d685
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/MedicalOpinionStatus.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.procedure.persistence.entity;
+
+public enum MedicalOpinionStatus {
+  IN_PROGRESS,
+  ACCOMPLISHED,
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/OmsProcedure.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/OmsProcedure.java
index afe5c74b7b497c3b16a10a8834e7e5d5771ea6fa..400d3d88329b53a3d87b059bab0395446fa794e0 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/OmsProcedure.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/OmsProcedure.java
@@ -5,12 +5,18 @@
 
 package de.eshg.officialmedicalservice.procedure.persistence.entity;
 
+import static de.eshg.lib.common.SensitivityLevel.PSEUDONYMIZED;
+
 import de.cronn.commons.lang.StreamUtil;
 import de.eshg.lib.common.DataSensitivity;
 import de.eshg.lib.common.SensitivityLevel;
 import de.eshg.lib.procedure.domain.model.Procedure;
 import de.eshg.officialmedicalservice.appointment.persistence.entity.OmsAppointment;
 import de.eshg.officialmedicalservice.appointment.persistence.entity.OmsAppointment_;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocument;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocument_;
+import de.eshg.officialmedicalservice.waitingroom.persistence.entity.WaitingRoom;
+import de.eshg.officialmedicalservice.waitingroom.persistence.entity.WaitingRoom_;
 import jakarta.persistence.CascadeType;
 import jakarta.persistence.Column;
 import jakarta.persistence.Entity;
@@ -19,11 +25,14 @@ import jakarta.persistence.OneToMany;
 import jakarta.persistence.OneToOne;
 import jakarta.persistence.OrderBy;
 import jakarta.persistence.Transient;
+import jakarta.validation.constraints.NotNull;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
 import org.hibernate.annotations.BatchSize;
+import org.hibernate.annotations.JdbcType;
+import org.hibernate.dialect.PostgreSQLEnumJdbcType;
 
 @Entity
 public class OmsProcedure extends Procedure<OmsProcedure, OmsTask, Person, Facility> {
@@ -45,6 +54,37 @@ public class OmsProcedure extends Procedure<OmsProcedure, OmsTask, Person, Facil
   @Column
   private UUID physicianId;
 
+  @OneToMany(
+      mappedBy = OmsDocument_.OMS_PROCEDURE,
+      cascade = {CascadeType.PERSIST, CascadeType.REMOVE},
+      orphanRemoval = true)
+  @OrderBy
+  @BatchSize(size = 100)
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  private final List<OmsDocument> documents = new ArrayList<>();
+
+  @Column(nullable = false)
+  @NotNull
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  @JdbcType(PostgreSQLEnumJdbcType.class)
+  private MedicalOpinionStatus medicalOpinionStatus;
+
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  @Column(nullable = false)
+  private boolean sendEmailNotifications = true;
+
+  @OneToOne(
+      optional = false,
+      cascade = {CascadeType.PERSIST, CascadeType.REMOVE},
+      mappedBy = WaitingRoom_.PROCEDURE,
+      orphanRemoval = true)
+  @DataSensitivity(PSEUDONYMIZED)
+  private WaitingRoom waitingRoom;
+
+  @DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+  @Column
+  private UUID citizenUserId;
+
   public Person findAffectedPerson() {
     if (getRelatedPersons().isEmpty()) {
       return null;
@@ -76,4 +116,41 @@ public class OmsProcedure extends Procedure<OmsProcedure, OmsTask, Person, Facil
   public List<OmsAppointment> getAppointments() {
     return appointments;
   }
+
+  public List<OmsDocument> getDocuments() {
+    return documents;
+  }
+
+  public MedicalOpinionStatus getMedicalOpinionStatus() {
+    return medicalOpinionStatus;
+  }
+
+  public void setMedicalOpinionStatus(MedicalOpinionStatus medicalOpinionStatus) {
+    this.medicalOpinionStatus = medicalOpinionStatus;
+  }
+
+  public boolean isSendEmailNotifications() {
+    return sendEmailNotifications;
+  }
+
+  public void setSendEmailNotifications(boolean sendEmailNotifications) {
+    this.sendEmailNotifications = sendEmailNotifications;
+  }
+
+  public WaitingRoom getWaitingRoom() {
+    return waitingRoom;
+  }
+
+  public void setWaitingRoom(WaitingRoom waitingRoom) {
+    this.waitingRoom = waitingRoom;
+    waitingRoom.setProcedure(this);
+  }
+
+  public UUID getCitizenUserId() {
+    return citizenUserId;
+  }
+
+  public void setCitizenUserId(UUID citizenUserId) {
+    this.citizenUserId = citizenUserId;
+  }
 }
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/OmsProcedureRepository.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/OmsProcedureRepository.java
index 88a320e19d215d9799079c451b70c5efd82910aa..84d711233b1d4eedd2cd630d469a6f0e6c05902b 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/OmsProcedureRepository.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/procedure/persistence/entity/OmsProcedureRepository.java
@@ -6,5 +6,47 @@
 package de.eshg.officialmedicalservice.procedure.persistence.entity;
 
 import de.eshg.lib.procedure.domain.repository.ProcedureRepository;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Stream;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
 
-public interface OmsProcedureRepository extends ProcedureRepository<OmsProcedure> {}
+public interface OmsProcedureRepository extends ProcedureRepository<OmsProcedure> {
+  @Query(
+      """
+    select o from OmsProcedure o
+    where exists (
+        select 1 from o.relatedPersons p
+        where p.centralFileStateId in :centralFileStateIds
+    )
+    order by o.id
+    """)
+  Stream<OmsProcedure> findByRelatedPersons(
+      @Param("centralFileStateIds") List<UUID> centralFileStateIds);
+
+  @Query(
+      """
+    select o from OmsProcedure o
+    where exists (
+        select 1 from o.relatedFacilities f
+        where f.centralFileStateId in :centralFileStateIds
+    )
+    order by o.id
+    """)
+  Stream<OmsProcedure> findByRelatedFacility(
+      @Param("centralFileStateIds") List<UUID> centralFileStateIds);
+
+  @Query(
+      """
+    select distinct o.physicianId from OmsProcedure o where o.physicianId is not null
+    """)
+  List<UUID> findDistinctPhysicianIds();
+
+  @Query(
+      """
+    select o from OmsProcedure o
+    where o.waitingRoom.status in ('WAITING_FOR_CONSULTATION', 'IN_CONSULTATION')
+    """)
+  Stream<OmsProcedure> findAllByWaitingRoomStatusInWaitingOrInConsultation();
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/OmsDocumentTestHelperFile.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/OmsDocumentTestHelperFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..56d855ec601feb8c26792380d58412af6aa084b9
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/OmsDocumentTestHelperFile.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.testhelper;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import org.springframework.web.multipart.MultipartFile;
+
+public class OmsDocumentTestHelperFile implements MultipartFile {
+  private final String name;
+  private final String contentType;
+  private final File file;
+
+  public OmsDocumentTestHelperFile(String name, String contentType, File file) {
+    this.name = name;
+    this.contentType = contentType;
+    this.file = file;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getOriginalFilename() {
+    return file.getName();
+  }
+
+  @Override
+  public String getContentType() {
+    return contentType;
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return file.length() == 0;
+  }
+
+  @Override
+  public long getSize() {
+    return file.length();
+  }
+
+  @Override
+  public byte[] getBytes() throws IOException {
+    return Files.readAllBytes(file.toPath());
+  }
+
+  @Override
+  public InputStream getInputStream() throws IOException {
+    return new FileInputStream(file);
+  }
+
+  @Override
+  public void transferTo(File dest) throws IOException, IllegalStateException {
+    Files.copy(file.toPath(), dest.toPath());
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/OmsTestHelperController.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/OmsTestHelperController.java
index 773aca0b8cf988562896bdfbf14e12be59bf33c9..88ecbc7e3861e005f7056edc88db4f71ce0f9f5c 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/OmsTestHelperController.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/OmsTestHelperController.java
@@ -5,7 +5,7 @@
 
 package de.eshg.officialmedicalservice.testhelper;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.lib.auditlog.AuditLogTestHelperService;
 import de.eshg.officialmedicalservice.testhelper.api.PostPopulateAdministrativeResponse;
 import de.eshg.officialmedicalservice.testhelper.api.PostPopulateProcedureRequest;
@@ -16,7 +16,6 @@ import de.eshg.testhelper.TestHelperController;
 import de.eshg.testhelper.environment.EnvironmentConfig;
 import io.swagger.v3.oas.annotations.Operation;
 import jakarta.validation.Valid;
-import java.io.IOException;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.service.annotation.PostExchange;
@@ -24,7 +23,7 @@ import org.springframework.web.service.annotation.PostExchange;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class OmsTestHelperController extends TestHelperController
-    implements SharedAuditLogTestHelperApi {
+    implements AuditLogClientTestHelperApi {
   public static final String TEST_POPULATION_PATH = "/population";
   public static final String TEST_POPULATION_URL = TestHelperApi.BASE_URL + TEST_POPULATION_PATH;
 
@@ -58,12 +57,7 @@ public class OmsTestHelperController extends TestHelperController
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
-  }
-
-  @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 }
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/TestPopulateProcedureService.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/TestPopulateProcedureService.java
index 987edab21611731f497eb1c32d407ce2c60203c4..aae239a79e063a9856f630bf39c86a4584dd2a68 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/TestPopulateProcedureService.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/TestPopulateProcedureService.java
@@ -11,17 +11,34 @@ import static de.eshg.lib.procedure.model.ProcedureStatusDto.OPEN;
 import de.eshg.officialmedicalservice.appointment.OmsAppointmentService;
 import de.eshg.officialmedicalservice.concern.ConcernMapper;
 import de.eshg.officialmedicalservice.concern.ConcernService;
+import de.eshg.officialmedicalservice.document.OmsDocumentService;
+import de.eshg.officialmedicalservice.document.api.DocumentStatusDto;
+import de.eshg.officialmedicalservice.document.api.PatchDocumentReviewRequest;
+import de.eshg.officialmedicalservice.document.api.ReviewResultDto;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocumentRepository;
+import de.eshg.officialmedicalservice.document.persistence.entity.OmsDocumentStatus;
 import de.eshg.officialmedicalservice.procedure.EmployeeOmsProcedureService;
 import de.eshg.officialmedicalservice.procedure.api.ConcernDto;
 import de.eshg.officialmedicalservice.procedure.api.PatchConcernRequest;
+import de.eshg.officialmedicalservice.procedure.api.PatchEmployeeOmsProcedureEmailNotificationsRequest;
 import de.eshg.officialmedicalservice.procedure.api.PatchEmployeeOmsProcedurePhysicianRequest;
 import de.eshg.officialmedicalservice.testhelper.api.AppointmentPopulationDto;
+import de.eshg.officialmedicalservice.testhelper.api.DocumentPopulationDto;
 import de.eshg.officialmedicalservice.testhelper.api.PostPopulateProcedureRequest;
 import de.eshg.officialmedicalservice.testhelper.api.PostPopulateProcedureResponse;
+import de.eshg.officialmedicalservice.waitingroom.WaitingRoomService;
 import de.eshg.testhelper.ConditionalOnTestHelperEnabled;
 import de.eshg.testhelper.population.PopulateWithAccessTokenHelper;
 import jakarta.transaction.Transactional;
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -29,6 +46,7 @@ import java.util.Objects;
 import java.util.Optional;
 import java.util.UUID;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
 /*
 Entities still to handle:
@@ -96,19 +114,25 @@ public class TestPopulateProcedureService {
   private final ConcernService concernService;
   private final OmsAppointmentService appointmentService;
   private final PopulateWithAccessTokenHelper populateWithAccessTokenHelper;
-  private final OmsAppointmentService omsAppointmentService;
+  private final OmsDocumentService omsDocumentService;
+  private final OmsDocumentRepository omsDocumentRepository;
+  private final WaitingRoomService waitingRoomService;
 
   public TestPopulateProcedureService(
       EmployeeOmsProcedureService employeeOmsProcedureService,
       ConcernService concernService,
       OmsAppointmentService appointmentService,
       PopulateWithAccessTokenHelper populateWithAccessTokenHelper,
-      OmsAppointmentService omsAppointmentService) {
+      OmsDocumentService omsDocumentService,
+      OmsDocumentRepository omsDocumentRepository,
+      WaitingRoomService waitingRoomService) {
     this.employeeOmsProcedureService = employeeOmsProcedureService;
     this.concernService = concernService;
     this.appointmentService = appointmentService;
     this.populateWithAccessTokenHelper = populateWithAccessTokenHelper;
-    this.omsAppointmentService = omsAppointmentService;
+    this.omsDocumentService = omsDocumentService;
+    this.omsDocumentRepository = omsDocumentRepository;
+    this.waitingRoomService = waitingRoomService;
   }
 
   @Transactional
@@ -119,17 +143,26 @@ public class TestPopulateProcedureService {
           UUID procedureId;
           UUID facilityId = null;
           Map<String, UUID> appointmentMap;
+          Map<String, UUID> documentMap = new HashMap<>();
 
           // 1. create procedure
           procedureId =
               employeeOmsProcedureService.createEmployeeProcedure((request.procedureData()));
 
-          // 2. add facility
+          // 2. Deactivate email notifications
+          if (request.sendEmailNotifications() != null) {
+            employeeOmsProcedureService.patchEmailNotifications(
+                procedureId,
+                new PatchEmployeeOmsProcedureEmailNotificationsRequest(
+                    request.sendEmailNotifications()));
+          }
+
+          // 3. add facility
           if (request.facility() != null) {
             facilityId = employeeOmsProcedureService.addFacility(procedureId, request.facility());
           }
 
-          // 3. add concern
+          // 4. add concern
           if (request.concern() != null) {
             ConcernDto concern =
                 concernService.getConcerns().categories().stream()
@@ -152,32 +185,47 @@ public class TestPopulateProcedureService {
                 procedureId, new PatchConcernRequest(concern));
           }
 
-          // 4. add physicians
+          // 5. add physician
           if (request.physician() != null) {
             employeeOmsProcedureService.modifyPhysician(
                 procedureId, new PatchEmployeeOmsProcedurePhysicianRequest(request.physician()));
           }
 
-          // 5. start procedure
+          // 6. start procedure
           if (Arrays.asList(OPEN, CLOSED).contains(request.targetState())) {
             employeeOmsProcedureService.acceptDraftProcedure(procedureId);
           }
 
-          // 6. add appointments
+          // 7. add appointments
           appointmentMap = addAppointments(procedureId, request.appointments());
 
-          // 7. cancel appointments
+          // 8. cancel appointments
           cancelAppointments(request.cancelledAppointments(), appointmentMap);
 
-          // 8. close appointments
+          // 9. close appointments
           closeAppointments(request.closedAppointments(), appointmentMap);
 
-          // 9. close procedure
+          // 10. add documents
+          documentMap = addDocuments(procedureId, request.documents());
+
+          // 11. update medical opinion status
+          if (request.medicalOpinionStatus() != null) {
+            employeeOmsProcedureService.updateMedicalOpinionStatus(
+                procedureId, request.medicalOpinionStatus());
+          }
+
+          // 12. update waiting room
+          if (request.waitingRoom() != null) {
+            waitingRoomService.updateWaitingRoom(procedureId, request.waitingRoom());
+          }
+
+          // 13. close procedure
           if (Objects.equals(CLOSED, request.targetState())) {
             employeeOmsProcedureService.closeOpenProcedure(procedureId);
           }
 
-          return new PostPopulateProcedureResponse(procedureId, facilityId, appointmentMap);
+          return new PostPopulateProcedureResponse(
+              procedureId, facilityId, appointmentMap, documentMap);
         });
   }
 
@@ -188,7 +236,7 @@ public class TestPopulateProcedureService {
       appointmentPopulations.forEach(
           population -> {
             UUID appointmentId =
-                omsAppointmentService.addAppointmentEmployee(procedureId, population.request());
+                appointmentService.addAppointmentEmployee(procedureId, population.request());
             appointmentMap.put(population.key(), appointmentId);
           });
     }
@@ -221,4 +269,67 @@ public class TestPopulateProcedureService {
           appointmentService.closeAppointmentEmployee(appointmentId);
         });
   }
+
+  private Map<String, UUID> addDocuments(
+      UUID procedureId, List<DocumentPopulationDto> documentPopulation) {
+    Map<String, UUID> documentMap = new LinkedHashMap<>();
+    if (documentPopulation != null) {
+      documentPopulation.forEach(
+          document -> {
+            List<MultipartFile> filesToAdd = new ArrayList<>();
+            String note = null;
+            if (document.targetState() == DocumentStatusDto.ACCEPTED
+                || document.targetState() == DocumentStatusDto.SUBMITTED) {
+              document
+                  .files()
+                  .forEach(
+                      config -> {
+                        try {
+                          Path filePath =
+                              Paths.get(
+                                  getClass()
+                                      .getClassLoader()
+                                      .getResource("documents/" + config.getName())
+                                      .toURI());
+                          File file = filePath.toFile();
+
+                          filesToAdd.add(
+                              new OmsDocumentTestHelperFile(
+                                  file.getName(), Files.probeContentType(file.toPath()), file));
+                        } catch (IOException | URISyntaxException e) {
+                          throw new RuntimeException(
+                              "Fehler beim Laden der Testdatei: " + config.getName(), e);
+                        }
+                      });
+
+              if (!document.files().isEmpty()) {
+                note = document.note();
+              }
+            }
+
+            UUID documentId =
+                omsDocumentService.addDocumentEmployee(
+                    procedureId, document.request(), filesToAdd, note);
+
+            // TODO: use document service once citizen portal document service functions exist
+            if (DocumentStatusDto.SUBMITTED == document.targetState()
+                || DocumentStatusDto.REJECTED == document.targetState()) {
+              omsDocumentRepository
+                  .findById(documentId)
+                  .orElseThrow()
+                  .setDocumentStatus(OmsDocumentStatus.SUBMITTED);
+            }
+
+            if (document.targetState() == DocumentStatusDto.REJECTED) {
+              omsDocumentService.reviewDocumentEmployee(
+                  documentId,
+                  new PatchDocumentReviewRequest(
+                      ReviewResultDto.REJECTED, document.reasonForRejection()));
+            }
+
+            documentMap.put(document.key(), documentId);
+          });
+    }
+    return documentMap;
+  }
 }
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/DocumentPopulationDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/DocumentPopulationDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..c688185d9b6cc8b742d70d475e2d48f52844c95e
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/DocumentPopulationDto.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.testhelper.api;
+
+import de.eshg.officialmedicalservice.document.api.DocumentStatusDto;
+import de.eshg.officialmedicalservice.document.api.PostDocumentRequest;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.util.List;
+
+@Schema(name = "DocumentPopulation")
+public record DocumentPopulationDto(
+    @NotBlank String key,
+    @NotNull @Valid PostDocumentRequest request,
+    DocumentStatusDto targetState,
+    String reasonForRejection,
+    List<FileTestDataConfig> files,
+    String note) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/FileTestDataConfig.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/FileTestDataConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ed5eef2b31536c723b127fc1b2404ba499c38cb
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/FileTestDataConfig.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.testhelper.api;
+
+public enum FileTestDataConfig {
+  PDF("testHelperSampleDocument.pdf"),
+  JPG("testHelperSampleImage.jpg"),
+  PNG("testHelperSampleImage.png");
+
+  String name;
+
+  FileTestDataConfig(String name) {
+    this.name = name;
+  }
+
+  public String getName() {
+    return name;
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/PostPopulateProcedureRequest.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/PostPopulateProcedureRequest.java
index 6d041379557d6cd5edd9a9c94427faadec5a1780..fd6cad8c24b2ec45a851918417bb9ef8ba47a2d3 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/PostPopulateProcedureRequest.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/PostPopulateProcedureRequest.java
@@ -6,8 +6,10 @@
 package de.eshg.officialmedicalservice.testhelper.api;
 
 import de.eshg.lib.procedure.model.ProcedureStatusDto;
+import de.eshg.officialmedicalservice.procedure.api.MedicalOpinionStatusDto;
 import de.eshg.officialmedicalservice.procedure.api.PostEmployeeOmsProcedureFacilityRequest;
 import de.eshg.officialmedicalservice.procedure.api.PostEmployeeOmsProcedureRequest;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomDto;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
 import java.util.List;
@@ -21,4 +23,9 @@ public record PostPopulateProcedureRequest(
     @Valid List<@Valid AppointmentPopulationDto> appointments,
     List<String> cancelledAppointments,
     List<String> closedAppointments,
-    ProcedureStatusDto targetState) {}
+    @Valid List<DocumentPopulationDto> documents,
+    MedicalOpinionStatusDto medicalOpinionStatus,
+    ProcedureStatusDto targetState,
+    Boolean sendEmailNotifications,
+    @Valid WaitingRoomDto waitingRoom,
+    String citizenUserId) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/PostPopulateProcedureResponse.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/PostPopulateProcedureResponse.java
index c838f507d1ab34536a9679f0e9e0a16559983d9c..440a6cfa5d14b53aa072bab2382e0fb632cfd31f 100644
--- a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/PostPopulateProcedureResponse.java
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/testhelper/api/PostPopulateProcedureResponse.java
@@ -11,4 +11,7 @@ import java.util.Map;
 import java.util.UUID;
 
 public record PostPopulateProcedureResponse(
-    @NotNull UUID procedureId, UUID facilityId, @NotNull @Valid Map<String, UUID> appointments) {}
+    @NotNull UUID procedureId,
+    UUID facilityId,
+    @NotNull @Valid Map<String, UUID> appointments,
+    @Valid Map<String, UUID> documentMap) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/user/CitizenAccessCodeUserClient.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/user/CitizenAccessCodeUserClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..243900c2453f67322ff221a2c4da315a425d2938
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/user/CitizenAccessCodeUserClient.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.user;
+
+import de.eshg.base.citizenuser.CitizenAccessCodeUserApi;
+import de.eshg.base.citizenuser.api.AddCitizenAccessCodeUserWithDateOfBirthCredentialRequest;
+import de.eshg.base.citizenuser.api.CitizenAccessCodeUserDto;
+import java.util.UUID;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CitizenAccessCodeUserClient {
+  private final CitizenAccessCodeUserApi citizenAccessCodeUserApi;
+
+  public CitizenAccessCodeUserClient(CitizenAccessCodeUserApi citizenAccessCodeUserApi) {
+    this.citizenAccessCodeUserApi = citizenAccessCodeUserApi;
+  }
+
+  public CitizenAccessCodeUserDto addCitizenAccessCodeUser(UUID personFileStateId) {
+    AddCitizenAccessCodeUserWithDateOfBirthCredentialRequest request =
+        new AddCitizenAccessCodeUserWithDateOfBirthCredentialRequest(personFileStateId);
+    return citizenAccessCodeUserApi.addCitizenAccessCodeUserWithDateOfBirthCredential(request);
+  }
+
+  public CitizenAccessCodeUserDto getCitizenAccessCode(UUID citizenUserId) {
+    return citizenAccessCodeUserApi.getCitizenAccessCodeUser(citizenUserId);
+  }
+
+  public void deleteCitizenAccessCodeUser(UUID citizenUserId) {
+    citizenAccessCodeUserApi.deleteCitizenAccessCodeUser(citizenUserId);
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/PagedWaitingRoomProcedures.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/PagedWaitingRoomProcedures.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea3d2156b647a4466b91a8a3f93b5363754b68c4
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/PagedWaitingRoomProcedures.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom;
+
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomProcedureDto;
+import java.util.List;
+import java.util.stream.Stream;
+
+public record PagedWaitingRoomProcedures(
+    List<WaitingRoomProcedureDto> proceduresPage, long totalNumberOfProcedures) {
+  public Stream<WaitingRoomProcedureDto> stream() {
+    return proceduresPage.stream();
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomController.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomController.java
new file mode 100644
index 0000000000000000000000000000000000000000..a240e9a60d95fbf7ee2e3170a81412542a18d30f
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomController.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom;
+
+import de.eshg.api.commons.InlineParameterObject;
+import de.eshg.officialmedicalservice.waitingroom.api.GetWaitingRoomProceduresResponse;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomProcedurePaginationAndSortParameters;
+import de.eshg.rest.service.security.config.BaseUrls.OfficialMedicalService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import org.springdoc.core.annotations.ParameterObject;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(path = WaitingRoomController.BASE_URL, produces = MediaType.APPLICATION_JSON_VALUE)
+@Tag(name = "WaitingRoom")
+public class WaitingRoomController {
+  public static final String BASE_URL = OfficialMedicalService.EMPLOYEE_API;
+  public static final String WAITING_ROOM_URL = "/waiting-room";
+
+  private final WaitingRoomService waitingRoomService;
+
+  public WaitingRoomController(WaitingRoomService waitingRoomService) {
+    this.waitingRoomService = waitingRoomService;
+  }
+
+  @GetMapping(path = WAITING_ROOM_URL)
+  @Operation(summary = "Get all procedures in waiting room.")
+  public GetWaitingRoomProceduresResponse getWaitingRoomProcedures(
+      @InlineParameterObject @ParameterObject @Valid
+          WaitingRoomProcedurePaginationAndSortParameters paginationAndSortParameters) {
+
+    PagedWaitingRoomProcedures pagedProcedures =
+        waitingRoomService.getWaitingRoomProcedures(paginationAndSortParameters);
+
+    return new GetWaitingRoomProceduresResponse(
+        pagedProcedures.proceduresPage(), pagedProcedures.totalNumberOfProcedures());
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomMapper.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d47c0dd21a8aaf2604e9d6a8292011c4b64cd3d
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomMapper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom;
+
+import de.eshg.base.SortDirection;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomDto;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingStatusDto;
+import de.eshg.officialmedicalservice.waitingroom.persistence.entity.WaitingRoom;
+import de.eshg.officialmedicalservice.waitingroom.persistence.entity.WaitingStatus;
+import de.eshg.officialmedicalservice.waitingroom.util.WaitingRoomPageSpec;
+import org.springframework.data.domain.Sort;
+
+public class WaitingRoomMapper {
+
+  private WaitingRoomMapper() {}
+
+  public static WaitingRoomDto mapToDto(WaitingRoom waitingRoom) {
+    if (waitingRoom == null) {
+      return null;
+    }
+
+    return new WaitingRoomDto(waitingRoom.getInfo(), mapStatusToDto(waitingRoom.getStatus()));
+  }
+
+  private static WaitingStatusDto mapStatusToDto(WaitingStatus waitingStatus) {
+    return switch (waitingStatus) {
+      case null -> null;
+      case WAITING_FOR_CONSULTATION -> WaitingStatusDto.WAITING_FOR_CONSULTATION;
+      case IN_CONSULTATION -> WaitingStatusDto.IN_CONSULTATION;
+      case DONE -> WaitingStatusDto.DONE;
+    };
+  }
+
+  public static WaitingStatus mapStatusFromDto(WaitingStatusDto waitingStatus) {
+    return switch (waitingStatus) {
+      case null -> null;
+      case WAITING_FOR_CONSULTATION -> WaitingStatus.WAITING_FOR_CONSULTATION;
+      case IN_CONSULTATION -> WaitingStatus.IN_CONSULTATION;
+      case DONE -> WaitingStatus.DONE;
+    };
+  }
+
+  public static WaitingRoomPageSpec mapToPageSpec(
+      int page, int pageSize, WaitingRoomSortKey sortField, SortDirection direction) {
+    return new WaitingRoomPageSpec(page, pageSize, sortField, mapDirection(direction));
+  }
+
+  public static Sort.Direction mapDirection(SortDirection sortDirection) {
+    return switch (sortDirection) {
+      case null -> Sort.Direction.ASC;
+      case ASC -> Sort.Direction.ASC;
+      case DESC -> Sort.Direction.DESC;
+    };
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomService.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomService.java
new file mode 100644
index 0000000000000000000000000000000000000000..2c7bca811b0abbdbd56a05a7a62b05f9984ce51f
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomService.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom;
+
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.DATE_OF_BIRTH;
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.FACILITY;
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.FIRSTNAME;
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.LASTNAME;
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.PHYSICIAN;
+import static java.util.Comparator.comparing;
+import static java.util.Comparator.naturalOrder;
+import static java.util.Comparator.nullsLast;
+
+import de.eshg.base.SortDirection;
+import de.eshg.base.centralfile.api.facility.GetFacilityFileStateResponse;
+import de.eshg.base.centralfile.api.facility.GetFacilityFileStatesRequest;
+import de.eshg.base.centralfile.api.person.GetPersonFileStateResponse;
+import de.eshg.base.centralfile.api.person.GetPersonFileStatesRequest;
+import de.eshg.base.centralfile.api.person.GetPersonFileStatesResponse;
+import de.eshg.base.centralfile.api.person.GetPersonFileStatesSortParameters;
+import de.eshg.base.centralfile.api.person.GetPersonsSortKey;
+import de.eshg.lib.procedure.domain.model.FacilityType;
+import de.eshg.lib.procedure.domain.model.PersonType;
+import de.eshg.lib.procedure.domain.model.ProcedureStatus;
+import de.eshg.lib.procedure.procedures.ProcedureQuery;
+import de.eshg.officialmedicalservice.facility.FacilityClient;
+import de.eshg.officialmedicalservice.facility.FacilityMapper;
+import de.eshg.officialmedicalservice.person.PersonClient;
+import de.eshg.officialmedicalservice.person.PersonMapper;
+import de.eshg.officialmedicalservice.procedure.api.AffectedPersonDto;
+import de.eshg.officialmedicalservice.procedure.api.FacilityDto;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedureRepository;
+import de.eshg.officialmedicalservice.user.UserClient;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomDto;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomProcedureDto;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomProcedurePaginationAndSortParameters;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey;
+import de.eshg.officialmedicalservice.waitingroom.persistence.entity.WaitingRoom;
+import de.eshg.officialmedicalservice.waitingroom.util.WaitingRoomPageSpec;
+import de.eshg.rest.service.error.BadRequestException;
+import de.eshg.rest.service.error.NotFoundException;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.stream.Stream;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
+
+@Service
+public class WaitingRoomService {
+  private final OmsProcedureRepository procedureRepository;
+  private final PersonClient personClient;
+  private final FacilityClient facilityClient;
+  private final ProcedureQuery procedureQuery;
+  private final OmsProcedureRepository omsProcedureRepository;
+  private final UserClient userClient;
+
+  public WaitingRoomService(
+      OmsProcedureRepository procedureRepository,
+      PersonClient personClient,
+      FacilityClient facilityClient,
+      ProcedureQuery procedureQuery,
+      OmsProcedureRepository omsProcedureRepository,
+      UserClient userClient) {
+    this.procedureRepository = procedureRepository;
+    this.personClient = personClient;
+    this.facilityClient = facilityClient;
+    this.procedureQuery = procedureQuery;
+    this.omsProcedureRepository = omsProcedureRepository;
+    this.userClient = userClient;
+  }
+
+  @Transactional(readOnly = true)
+  public PagedWaitingRoomProcedures getWaitingRoomProcedures(
+      WaitingRoomProcedurePaginationAndSortParameters paginationAndSortParameters) {
+
+    WaitingRoomPageSpec pageSpec =
+        WaitingRoomMapper.mapToPageSpec(
+            paginationAndSortParameters.pageNumberOrFallback(0),
+            paginationAndSortParameters.pageSizeOrFallback(25),
+            paginationAndSortParameters.sortKeyOrFallback(
+                de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.ID),
+            paginationAndSortParameters.sortDirectionOrFallback(SortDirection.DESC));
+
+    WaitingRoomSpecification waitingRoomSpecification =
+        new WaitingRoomSpecification(pageSpec.sortKey(), pageSpec.direction());
+
+    if (List.of(FIRSTNAME, LASTNAME, DATE_OF_BIRTH).contains(pageSpec.sortKey())) {
+      return getSortingForPersonAttributes(pageSpec, waitingRoomSpecification);
+    }
+
+    if (Objects.equals(PHYSICIAN, pageSpec.sortKey())) {
+      return getSortingForPhysicianAttribute(pageSpec);
+    }
+
+    if (Objects.equals(FACILITY, pageSpec.sortKey())) {
+      return getSortingForFacilityAttribute(pageSpec, waitingRoomSpecification);
+    }
+
+    Page<OmsProcedure> omsProcedures =
+        procedureRepository.findAll(
+            waitingRoomSpecification, PageRequest.of(pageSpec.pageNumber(), pageSpec.pageSize()));
+    List<WaitingRoomProcedureDto> procedureData =
+        augmentWithWaitingRoomData(omsProcedures.getContent()).toList();
+
+    return new PagedWaitingRoomProcedures(procedureData, omsProcedures.getTotalElements());
+  }
+
+  @Transactional
+  public void updateWaitingRoom(UUID externalId, WaitingRoomDto request) {
+    OmsProcedure omsProcedure = loadOmsProcedure(externalId);
+
+    if (Objects.equals(ProcedureStatus.DRAFT, omsProcedure.getProcedureStatus())) {
+      throw new BadRequestException(
+          "Waiting room cannot be updated when the procedure is in DRAFT status.");
+    }
+
+    if (omsProcedure.isFinalized()) {
+      throw new BadRequestException(
+          "Waiting room cannot be updated when the procedure is finalized.");
+    }
+
+    WaitingRoom waitingRoom = omsProcedure.getWaitingRoom();
+    waitingRoom.setInfo(request.info());
+    waitingRoom.setStatus(WaitingRoomMapper.mapStatusFromDto(request.status()));
+  }
+
+  private PagedWaitingRoomProcedures getSortingForPersonAttributes(
+      WaitingRoomPageSpec pageSpec, WaitingRoomSpecification waitingRoomSpecification) {
+    List<UUID> personIds =
+        procedureQuery.findAllRelatedPersonFileStateIds(
+            waitingRoomSpecification, OmsProcedure.class, PersonType.PATIENT);
+
+    List<UUID> pagedAndSortedPersonIds =
+        fetchPersonsBulk(
+                personIds,
+                mapToGetPersonsSortKey(pageSpec.sortKey()),
+                pageSpec.direction(),
+                pageSpec.pageNumber(),
+                pageSpec.pageSize())
+            .stream()
+            .map(GetPersonFileStateResponse::id)
+            .toList();
+
+    List<OmsProcedure> result =
+        omsProcedureRepository
+            .findByRelatedPersons(pagedAndSortedPersonIds)
+            .sorted(
+                Comparator.comparingInt(
+                    procedure -> {
+                      int index =
+                          pagedAndSortedPersonIds.indexOf(
+                              procedure.findAffectedPerson().getCentralFileStateId());
+                      Assert.isTrue(index >= 0, "Unexpected index: " + index);
+                      return index;
+                    }))
+            .toList();
+
+    List<WaitingRoomProcedureDto> procedureData = augmentWithWaitingRoomData(result).toList();
+    return new PagedWaitingRoomProcedures(procedureData, personIds.size());
+  }
+
+  private PagedWaitingRoomProcedures getSortingForPhysicianAttribute(WaitingRoomPageSpec pageSpec) {
+    List<UUID> physicianIds = omsProcedureRepository.findDistinctPhysicianIds();
+
+    List<UUID> pagedAndSortedPhysicianIds =
+        fetchPhysiciansBulk(
+            physicianIds, pageSpec.direction(), pageSpec.pageNumber(), pageSpec.pageSize());
+
+    List<OmsProcedure> result =
+        omsProcedureRepository
+            .findAllByWaitingRoomStatusInWaitingOrInConsultation()
+            .sorted(
+                Comparator.comparing(
+                    procedure -> {
+                      if (procedure.getPhysicianId() == null) {
+                        return null;
+                      }
+                      int index = pagedAndSortedPhysicianIds.indexOf(procedure.getPhysicianId());
+                      Assert.isTrue(index >= 0, "Unexpected index: " + index);
+                      return index;
+                    },
+                    nullsLast(naturalOrder())))
+            .toList();
+
+    List<WaitingRoomProcedureDto> procedureData = augmentWithWaitingRoomData(result).toList();
+    return new PagedWaitingRoomProcedures(procedureData, result.size());
+  }
+
+  private PagedWaitingRoomProcedures getSortingForFacilityAttribute(
+      WaitingRoomPageSpec pageSpec, WaitingRoomSpecification waitingRoomSpecification) {
+    List<UUID> facilityIds =
+        procedureQuery.findAllRelatedFacilityFileStateIds(
+            waitingRoomSpecification, OmsProcedure.class, FacilityType.OTHER);
+
+    List<UUID> pagedAndSortedFacilityIds =
+        fetchFacilitiesBulk(
+                facilityIds, pageSpec.direction(), pageSpec.pageNumber(), pageSpec.pageSize())
+            .stream()
+            .map(GetFacilityFileStateResponse::id)
+            .toList();
+
+    List<OmsProcedure> result =
+        omsProcedureRepository
+            .findByRelatedFacility(pagedAndSortedFacilityIds)
+            .sorted(
+                Comparator.comparingInt(
+                    procedure -> {
+                      int index =
+                          pagedAndSortedFacilityIds.indexOf(
+                              procedure.getFacility().orElseThrow().getCentralFileStateId());
+                      Assert.isTrue(index >= 0, "Unexpected index: " + index);
+                      return index;
+                    }))
+            .toList();
+
+    List<WaitingRoomProcedureDto> procedureData = augmentWithWaitingRoomData(result).toList();
+    return new PagedWaitingRoomProcedures(procedureData, facilityIds.size());
+  }
+
+  private Stream<WaitingRoomProcedureDto> augmentWithWaitingRoomData(
+      List<OmsProcedure> procedures) {
+    Map<UUID, String> physicianNamesMap = userClient.getPhysicianNamesMap();
+    return procedures.stream()
+        .map(
+            data -> {
+              AffectedPersonDto affectedPerson =
+                  PersonMapper.mapToAffectedPersonDto(
+                      personClient.getPersonFileState(
+                          data.findAffectedPerson().getCentralFileStateId()),
+                      data.findAffectedPerson().getVersion());
+              FacilityDto facility =
+                  FacilityMapper.mapToFacilityDto(
+                      facilityClient.getFacilityFileState(
+                          data.getFacility().orElseThrow().getCentralFileStateId()),
+                      data.findAffectedPerson().getVersion());
+
+              return new WaitingRoomProcedureDto(
+                  data.getExternalId(),
+                  affectedPerson.firstName(),
+                  affectedPerson.lastName(),
+                  affectedPerson.dateOfBirth(),
+                  facility.name(),
+                  physicianNamesMap.get(data.getPhysicianId()),
+                  WaitingRoomMapper.mapToDto(data.getWaitingRoom()),
+                  data.getWaitingRoom().getModifiedAt());
+            });
+  }
+
+  private OmsProcedure loadOmsProcedure(UUID externalId) {
+    return procedureRepository
+        .findByExternalId(externalId)
+        .orElseThrow(() -> new NotFoundException("Procedure not found"));
+  }
+
+  private List<GetPersonFileStateResponse> fetchPersonsBulk(
+      List<UUID> personIdsToFetch,
+      GetPersonsSortKey sortKey,
+      Sort.Direction direction,
+      Integer pageNumber,
+      Integer pageSize) {
+    if (personIdsToFetch.isEmpty()) {
+      return List.of();
+    }
+    GetPersonFileStatesSortParameters sortParameters =
+        mapToSortParameters(sortKey, direction, pageNumber, pageSize);
+
+    GetPersonFileStatesResponse response =
+        personClient.getPersonFileStates(
+            new GetPersonFileStatesRequest(personIdsToFetch, sortParameters));
+
+    int expectedResponseSize =
+        sortParameters == null
+            ? personIdsToFetch.size()
+            : Math.min(pageSize, personIdsToFetch.size() - (pageNumber * pageSize));
+    if (response.personFileStates().size() < expectedResponseSize) {
+      throw new IllegalStateException("Some persons were not found in the central file.");
+    }
+
+    return response.personFileStates();
+  }
+
+  private List<GetFacilityFileStateResponse> fetchFacilitiesBulk(
+      List<UUID> facilityIdsToFetch,
+      Sort.Direction direction,
+      Integer pageNumber,
+      Integer pageSize) {
+    if (facilityIdsToFetch.isEmpty()) {
+      return List.of();
+    }
+
+    List<GetFacilityFileStateResponse> facilities =
+        facilityClient
+            .getFacilityFileStates(new GetFacilityFileStatesRequest(facilityIdsToFetch))
+            .facilityFileStates();
+
+    Comparator<GetFacilityFileStateResponse> comparator =
+        comparing(GetFacilityFileStateResponse::name);
+
+    if (direction == Sort.Direction.DESC) {
+      comparator = comparator.reversed();
+    }
+
+    facilities = facilities.stream().sorted(comparator).toList();
+
+    int start = pageNumber * pageSize;
+    int end = Math.min(start + pageSize, facilities.size());
+
+    if (start > facilities.size()) {
+      return List.of();
+    }
+
+    return facilities.subList(start, end);
+  }
+
+  private List<UUID> fetchPhysiciansBulk(
+      List<UUID> physicianIdsToFetch,
+      Sort.Direction direction,
+      Integer pageNumber,
+      Integer pageSize) {
+
+    if (physicianIdsToFetch.isEmpty()) {
+      return List.of();
+    }
+
+    Map<UUID, String> physicianNamesMap = userClient.getPhysicianNamesMap();
+
+    List<Map.Entry<UUID, String>> physicians =
+        physicianNamesMap.entrySet().stream()
+            .filter(entry -> physicianIdsToFetch.contains(entry.getKey()))
+            .toList();
+
+    Comparator<Map.Entry<UUID, String>> comparator = comparing(Map.Entry::getValue);
+
+    if (direction == Sort.Direction.DESC) {
+      comparator = comparator.reversed();
+    }
+
+    physicians = physicians.stream().sorted(comparator).toList();
+
+    int start = pageNumber * pageSize;
+    int end = Math.min(start + pageSize, physicians.size());
+
+    if (start > physicians.size()) {
+      return List.of();
+    }
+
+    return physicians.subList(start, end).stream().map(Map.Entry::getKey).toList();
+  }
+
+  private GetPersonFileStatesSortParameters mapToSortParameters(
+      GetPersonsSortKey sortKey, Sort.Direction direction, Integer pageNumber, Integer pageSize) {
+    if (sortKey == null) {
+      return null;
+    }
+    return new GetPersonFileStatesSortParameters(
+        sortKey,
+        switch (direction) {
+          case ASC -> SortDirection.ASC;
+          case DESC -> SortDirection.DESC;
+        },
+        pageNumber,
+        pageSize);
+  }
+
+  private static GetPersonsSortKey mapToGetPersonsSortKey(WaitingRoomSortKey sortKey) {
+    return switch (sortKey) {
+      case DATE_OF_BIRTH -> GetPersonsSortKey.DATE_OF_BIRTH;
+      case FIRSTNAME -> GetPersonsSortKey.FIRST_NAME;
+      case LASTNAME -> GetPersonsSortKey.LAST_NAME;
+      case ID, INFO, STATUS, MODIFIED_AT, PHYSICIAN, FACILITY ->
+          throw new IllegalArgumentException("Unexpected sort key: " + sortKey);
+    };
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomSpecification.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomSpecification.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef25585a33f535a3e4c1b937c5a77eff48031ac9
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/WaitingRoomSpecification.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom;
+
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.DATE_OF_BIRTH;
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.FACILITY;
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.FIRSTNAME;
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.LASTNAME;
+import static de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey.PHYSICIAN;
+
+import de.eshg.lib.procedure.domain.model.ProcedureStatus;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure_;
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey;
+import de.eshg.officialmedicalservice.waitingroom.persistence.entity.WaitingRoom_;
+import de.eshg.officialmedicalservice.waitingroom.persistence.entity.WaitingStatus;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Expression;
+import jakarta.persistence.criteria.Order;
+import jakarta.persistence.criteria.Path;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
+import java.io.Serial;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+
+public class WaitingRoomSpecification implements Specification<OmsProcedure> {
+  @Serial private static final long serialVersionUID = 1L;
+
+  private final WaitingRoomSortKey sortKey;
+  private final Sort.Direction sortDirection;
+
+  public WaitingRoomSpecification(WaitingRoomSortKey sortKey, Sort.Direction sortDirection) {
+    this.sortKey = sortKey;
+    this.sortDirection = sortDirection;
+  }
+
+  @Override
+  public Predicate toPredicate(
+      Root<OmsProcedure> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
+    List<Predicate> conjunctions = new ArrayList<>();
+    conjunctions.add(
+        criteriaBuilder.equal(root.get(OmsProcedure_.procedureStatus), ProcedureStatus.OPEN));
+    conjunctions.add(
+        criteriaBuilder.isNotNull(root.get(OmsProcedure_.waitingRoom).get(WaitingRoom_.status)));
+    conjunctions.add(
+        criteriaBuilder.not(
+            root.get(OmsProcedure_.waitingRoom).get(WaitingRoom_.status).in(WaitingStatus.DONE)));
+
+    Set<Order> orders = new LinkedHashSet<>();
+    if (!List.of(FIRSTNAME, LASTNAME, DATE_OF_BIRTH, FACILITY, PHYSICIAN).contains(sortKey)) {
+      orders.add(getOrder(root, criteriaBuilder));
+    }
+    orders.add(getFallbackOrder(root, criteriaBuilder));
+
+    query.orderBy(orders.stream().toList());
+    return criteriaBuilder.and(conjunctions.toArray(Predicate[]::new));
+  }
+
+  private Order getFallbackOrder(Root<OmsProcedure> root, CriteriaBuilder criteriaBuilder) {
+    Expression<?> fallbackOrderExpression = root.get(OmsProcedure_.id);
+    return switch (sortDirection) {
+      case ASC -> criteriaBuilder.asc(fallbackOrderExpression);
+      case DESC -> criteriaBuilder.desc(fallbackOrderExpression);
+    };
+  }
+
+  private Order getOrder(Root<OmsProcedure> root, CriteriaBuilder criteriaBuilder) {
+    Expression<?> sortOrder =
+        switch (sortKey) {
+          case ID -> root.get(OmsProcedure_.id);
+          case FIRSTNAME, LASTNAME, DATE_OF_BIRTH, FACILITY, PHYSICIAN ->
+              throw new IllegalArgumentException("Unexpected sort key: " + sortKey);
+          case STATUS -> root.get(OmsProcedure_.waitingRoom).get(WaitingRoom_.status);
+          case INFO ->
+              nullsLastString(
+                  root.get(OmsProcedure_.waitingRoom).get(WaitingRoom_.info), criteriaBuilder);
+          case MODIFIED_AT -> root.get(OmsProcedure_.waitingRoom).get(WaitingRoom_.modifiedAt);
+        };
+    return switch (sortDirection) {
+      case ASC -> criteriaBuilder.asc(sortOrder);
+      case DESC -> criteriaBuilder.desc(sortOrder);
+    };
+  }
+
+  private Expression<String> nullsLastString(Path<String> instantPath, CriteriaBuilder cb) {
+    String valueWhenNull =
+        switch (sortDirection) {
+          case ASC -> null;
+          case DESC -> "";
+        };
+    return nullsLast(instantPath, cb, valueWhenNull);
+  }
+
+  // This is a workaround because the CriteriaBuilder currently does not support
+  // generating SQL’s "NULLS LAST"
+  // It’s supposed to be added in Java Persistence 3.2 / Hibernate 7.0
+  private static <T> Expression<T> nullsLast(
+      Path<T> instantPath, CriteriaBuilder cb, T valueWhenNull) {
+    return cb.coalesce(instantPath, cb.literal(valueWhenNull));
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/GetWaitingRoomProceduresResponse.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/GetWaitingRoomProceduresResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..85f015e5888960a80fc891fd90809f4f75a2b245
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/GetWaitingRoomProceduresResponse.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.api;
+
+import de.eshg.base.PagedResponse;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import java.util.List;
+
+@Schema(name = "GetWaitingRoomProceduresResponse")
+public record GetWaitingRoomProceduresResponse(
+    @Valid @NotNull List<WaitingRoomProcedureDto> elements, @NotNull long totalNumberOfElements)
+    implements PagedResponse<WaitingRoomProcedureDto> {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..16727f7bc3a5e0ea54cac776e3d2450ab1b09605
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomDto.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.api;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(name = "WaitingRoom")
+public record WaitingRoomDto(String info, WaitingStatusDto status) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomProcedureDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomProcedureDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f0084fb9abd526a4283eec6d614be5dc9e45a68
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomProcedureDto.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.api;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.util.UUID;
+
+@Schema(name = "WaitingRoomProcedure")
+public record WaitingRoomProcedureDto(
+    @NotNull UUID id,
+    @NotNull String firstName,
+    @NotNull String lastName,
+    @NotNull LocalDate dateOfBirth,
+    @NotNull String facilityName,
+    String physicianName,
+    @NotNull @Valid WaitingRoomDto waitingRoom,
+    @NotNull Instant modifiedAt) {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomProcedurePaginationAndSortParameters.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomProcedurePaginationAndSortParameters.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc7608b5c3acdb0e321547601d109d1c59e6b6f4
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomProcedurePaginationAndSortParameters.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.api;
+
+import de.eshg.base.PaginationParameters;
+import de.eshg.base.SortDirection;
+import de.eshg.base.SortParameters;
+import jakarta.validation.constraints.Min;
+
+public record WaitingRoomProcedurePaginationAndSortParameters(
+    WaitingRoomSortKey sortKey,
+    SortDirection sortDirection,
+    @Min(0) Integer pageNumber,
+    @Min(1) Integer pageSize)
+    implements PaginationParameters, SortParameters<WaitingRoomSortKey> {}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomSortKey.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomSortKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..915154244b3a5010383e72ee70efac90c56e8458
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingRoomSortKey.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.api;
+
+public enum WaitingRoomSortKey {
+  ID,
+  FIRSTNAME,
+  LASTNAME,
+  DATE_OF_BIRTH,
+  FACILITY,
+  PHYSICIAN,
+  STATUS,
+  INFO,
+  MODIFIED_AT,
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingStatusDto.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingStatusDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..df5090b63da2743afea9952509bdd8a9aaf28583
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/api/WaitingStatusDto.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.api;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(name = "WaitingStatus")
+public enum WaitingStatusDto {
+  WAITING_FOR_CONSULTATION,
+  IN_CONSULTATION,
+  DONE,
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/persistence/entity/WaitingRoom.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/persistence/entity/WaitingRoom.java
new file mode 100644
index 0000000000000000000000000000000000000000..b17247b974be2be0f971c62cbb6ad968f5a41e0b
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/persistence/entity/WaitingRoom.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.persistence.entity;
+
+import de.eshg.domain.model.BaseEntity;
+import de.eshg.lib.common.DataSensitivity;
+import de.eshg.lib.common.SensitivityLevel;
+import de.eshg.officialmedicalservice.procedure.persistence.entity.OmsProcedure;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.MapsId;
+import jakarta.persistence.OneToOne;
+import jakarta.validation.constraints.NotNull;
+import java.time.Instant;
+import org.hibernate.annotations.JdbcType;
+import org.hibernate.dialect.PostgreSQLEnumJdbcType;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+@Entity
+@EntityListeners(AuditingEntityListener.class)
+@DataSensitivity(SensitivityLevel.PSEUDONYMIZED)
+public class WaitingRoom extends BaseEntity {
+
+  @MapsId
+  @OneToOne(optional = false)
+  private OmsProcedure procedure;
+
+  private String info;
+
+  @JdbcType(PostgreSQLEnumJdbcType.class)
+  private WaitingStatus status;
+
+  @NotNull @LastModifiedDate private Instant modifiedAt;
+
+  public OmsProcedure getProcedure() {
+    return procedure;
+  }
+
+  public void setProcedure(OmsProcedure procedure) {
+    this.procedure = procedure;
+  }
+
+  public String getInfo() {
+    return info;
+  }
+
+  public void setInfo(String info) {
+    this.info = info;
+  }
+
+  public WaitingStatus getStatus() {
+    return status;
+  }
+
+  public void setStatus(WaitingStatus status) {
+    this.status = status;
+  }
+
+  public Instant getModifiedAt() {
+    return modifiedAt;
+  }
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/persistence/entity/WaitingStatus.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/persistence/entity/WaitingStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ecbe3d2e175b65a62840c30594a5f8e670aeefd
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/persistence/entity/WaitingStatus.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.persistence.entity;
+
+public enum WaitingStatus {
+  WAITING_FOR_CONSULTATION,
+  IN_CONSULTATION,
+  DONE,
+}
diff --git a/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/util/WaitingRoomPageSpec.java b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/util/WaitingRoomPageSpec.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d92253fa8c9606b5c9f4ce3531e20cb491996cf
--- /dev/null
+++ b/backend/official-medical-service/src/main/java/de/eshg/officialmedicalservice/waitingroom/util/WaitingRoomPageSpec.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package de.eshg.officialmedicalservice.waitingroom.util;
+
+import de.eshg.officialmedicalservice.waitingroom.api.WaitingRoomSortKey;
+import org.springframework.data.domain.Sort;
+
+public record WaitingRoomPageSpec(
+    int pageNumber, int pageSize, WaitingRoomSortKey sortKey, Sort.Direction direction) {}
diff --git a/backend/official-medical-service/src/main/resources/application-health-department-frankfurt.properties b/backend/official-medical-service/src/main/resources/application-health-department-frankfurt.properties
index b36ec31b1b80ef03721d361127a88216ac73d9c3..9243a0c6b9be61c9496c9650fe47c828e8515b14 100644
--- a/backend/official-medical-service/src/main/resources/application-health-department-frankfurt.properties
+++ b/backend/official-medical-service/src/main/resources/application-health-department-frankfurt.properties
@@ -25,3 +25,8 @@ de.eshg.official-medical-service.department-info.phoneNumber=069 212 33622
 de.eshg.official-medical-service.department-info.email=info.amtsaerztlicherdienst@stadt-frankfurt.de
 # de.eshg.official-medical-service.department-info.latitude=
 # de.eshg.official-medical-service.department-info.longitude=
+
+# notifications (by mail)
+de.eshg.official-medical-service.notification.fromAddress=tba@stadt-frankfurt.de
+de.eshg.official-medical-service.notification.greeting=Ihr TBA-Team der Stadt Frankfurt
+de.eshg.official-medical-service.notification.templates.path=notifications/ga_frankfurt/de
diff --git a/backend/official-medical-service/src/main/resources/application.properties b/backend/official-medical-service/src/main/resources/application.properties
index f4aa01a173ffc3657728ddaf8d1a4104c1646c76..10340045fab7549e144fb4915188a6502b764286 100644
--- a/backend/official-medical-service/src/main/resources/application.properties
+++ b/backend/official-medical-service/src/main/resources/application.properties
@@ -14,7 +14,7 @@ spring.liquibase.enabled=false
 
 logging.level.org.zalando.logbook=TRACE
 
-spring.security.oauth2.client.registration.module-client.client-id=system-official-medicine-service
+spring.security.oauth2.client.registration.module-client.client-id=system-official-medical-service
 spring.security.oauth2.client.registration.module-client.client-secret=password
 spring.security.oauth2.client.provider.eshg-keycloak.token-uri=${eshg.keycloak.internal.url}/realms/eshg/protocol/openid-connect/token
 
@@ -37,6 +37,16 @@ de.eshg.lib.appointmentblock.createAppointmentBlockForCurrentUser=false
 
 eshg.population.default-number-of-entities-to-populate.appointment-block-group=0
 
+eshg.citizen-portal.reverse-proxy.url=http://localhost:4001
+
 de.eshg.official-medical-service.concerns.templates.path=concerns
 
 de.eshg.official-medical-service.concerns.config=classpath:${de.eshg.official-medical-service.concerns.templates.path}/concerns.yaml
+
+# standard notifications (by mail)
+de.eshg.official-medical-service.notification.fromAddress=tba@stadt-frankfurt.de
+de.eshg.official-medical-service.notification.greeting=Ihr TBA-Team der Stadt Frankfurt
+
+de.eshg.official-medical-service.notification.templates.path=notifications/default/de
+de.eshg.official-medical-service.notification.template.new_citizen_user.subject=Bestätigung
+de.eshg.official-medical-service.notification.template.new_citizen_user.body=classpath:${de.eshg.official-medical-service.notification.templates.path}/new_citizen_user.txt
diff --git a/backend/official-medical-service/src/main/resources/documents/testHelperSampleDocument.pdf b/backend/official-medical-service/src/main/resources/documents/testHelperSampleDocument.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..89551d242906e200b6dc2212962337c2bded29fb
Binary files /dev/null and b/backend/official-medical-service/src/main/resources/documents/testHelperSampleDocument.pdf differ
diff --git a/backend/official-medical-service/src/main/resources/documents/testHelperSampleImage.jpg b/backend/official-medical-service/src/main/resources/documents/testHelperSampleImage.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..83f9478af1700702804d85cfac05d33cd9b9e0f4
Binary files /dev/null and b/backend/official-medical-service/src/main/resources/documents/testHelperSampleImage.jpg differ
diff --git a/backend/official-medical-service/src/main/resources/documents/testHelperSampleImage.png b/backend/official-medical-service/src/main/resources/documents/testHelperSampleImage.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b2f9e4521862951c878578010b0e0fcb4f4303b
Binary files /dev/null and b/backend/official-medical-service/src/main/resources/documents/testHelperSampleImage.png differ
diff --git a/backend/official-medical-service/src/main/resources/notifications/default/de/new_citizen_user.txt b/backend/official-medical-service/src/main/resources/notifications/default/de/new_citizen_user.txt
new file mode 100644
index 0000000000000000000000000000000000000000..22e24f6a6badde00dbdfac469b4ea226c32926a5
--- /dev/null
+++ b/backend/official-medical-service/src/main/resources/notifications/default/de/new_citizen_user.txt
@@ -0,0 +1,17 @@
+Sehr geehrte(r) %s %s,
+
+wir möchten Ihnen mitteilen, dass ...
+  ... bitten wir Sie, dies über unseren Online-Service vorzunehmen. Nutzen Sie hierfür bitte den folgenden Link:
+%s
+
+Ihr Anmeldecode: %s
+
+Zur Verifikation wird Ihr Geburtsdatum benötigt.
+
+Beachten Sie bitte, dass es nicht möglich ist auf diese Email zu antworten. Für Änderungen und Absagen verwenden Sie bitte den angegebenen Link.
+
+Vielen Dank, dass Sie unseren Service nutzen. Wir freuen uns darauf, Sie bald bei uns begrüßen zu dürfen.
+
+Mit freundlichen Grüßen,
+
+%s
diff --git a/backend/official-medical-service/src/main/resources/notifications/ga_frankfurt/de/new_citizen_user.txt b/backend/official-medical-service/src/main/resources/notifications/ga_frankfurt/de/new_citizen_user.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4718bbf4d00fdcf9e1d53d114a82d1c4ca27e026
--- /dev/null
+++ b/backend/official-medical-service/src/main/resources/notifications/ga_frankfurt/de/new_citizen_user.txt
@@ -0,0 +1,16 @@
+Sehr geehrte(r) %s %s,
+
+wir möchten Ihnen mitteilen, dass ...
+  ... bitten wir Sie, dies über unseren Online-Service vorzunehmen. Nutzen Sie hierfür bitte den folgenden Link:
+%s
+
+Anmeldecode: %s
+Zur Verifikation wird Ihr Geburtsdatum benötigt.
+
+Beachten Sie bitte, dass es nicht möglich ist auf diese Email zu antworten. Für Änderungen und Absagen verwenden Sie bitte den angegebenen Link.
+
+Vielen Dank, dass Sie unseren Service nutzen. Wir freuen uns darauf, Sie bald bei uns begrüßen zu dürfen.
+
+Mit freundlichen Grüßen,
+
+%s
diff --git a/backend/opendata/gradle.lockfile b/backend/opendata/gradle.lockfile
index bd266a768827a8768042e1160251451867942174..b37e5539aa75d5e4d5543ae0a0b35bad692c6d3c 100644
--- a/backend/opendata/gradle.lockfile
+++ b/backend/opendata/gradle.lockfile
@@ -60,10 +60,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -86,7 +86,7 @@ org.antlr:antlr4-runtime:4.13.0=annotationProcessor,compileClasspath,productionR
 org.apache.commons:commons-collections4:4.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.apache.commons:commons-compress:1.24.0=testCompileClasspath,testRuntimeClasspath
 org.apache.commons:commons-lang3:3.17.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.apache.commons:commons-text:1.12.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.apache.commons:commons-text:1.13.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.apache.httpcomponents.client5:httpclient5:5.4.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.apache.httpcomponents.core5:httpcore5-h2:5.3.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.apache.httpcomponents.core5:httpcore5:5.3.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -117,10 +117,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -139,16 +139,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/relay-server/gradle.lockfile b/backend/relay-server/gradle.lockfile
index e1315dd52d960b34e94da6d6ded47215030ed25f..7b4890c1b29178fed592cbfac1b992a1acef2e7d 100644
--- a/backend/relay-server/gradle.lockfile
+++ b/backend/relay-server/gradle.lockfile
@@ -58,8 +58,8 @@ io.netty:netty-transport:4.1.116.Final=testCompileClasspath,testRuntimeClasspath
 io.projectreactor.netty:reactor-netty-core:1.2.1=testCompileClasspath,testRuntimeClasspath
 io.projectreactor.netty:reactor-netty-http:1.2.1=testCompileClasspath,testRuntimeClasspath
 io.projectreactor:reactor-core:3.7.1=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -90,10 +90,10 @@ org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClass
 org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
@@ -108,9 +108,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.reactivestreams:reactive-streams:1.0.4=testCompileClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/rest-client-commons/gradle.lockfile b/backend/rest-client-commons/gradle.lockfile
index 75c1e6344cfbfb75dfa38e031d58fd9acde58f9f..520cb944ab20df90c2040a0b38a3aded02b4a148 100644
--- a/backend/rest-client-commons/gradle.lockfile
+++ b/backend/rest-client-commons/gradle.lockfile
@@ -21,8 +21,8 @@ com.squareup.okio:okio:3.6.0=testCompileClasspath,testRuntimeClasspath
 com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.quarkus:quarkus-junit4-mock:3.17.7=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.quarkus:quarkus-junit4-mock:3.18.0=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -43,10 +43,10 @@ org.apiguardian:apiguardian-api:1.1.2=compileClasspath,productionRuntimeClasspat
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jetbrains.kotlin:kotlin-stdlib-common:1.9.25=testCompileClasspath,testRuntimeClasspath
 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.25=testCompileClasspath,testRuntimeClasspath
 org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.25=testCompileClasspath,testRuntimeClasspath
@@ -64,9 +64,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/rest-oauth-client-commons/gradle.lockfile b/backend/rest-oauth-client-commons/gradle.lockfile
index a67c67be8b1c0dd1b540f15cb6157f25ccc666c0..a77310932d8f6ab75154402d163e6d96264cbbc8 100644
--- a/backend/rest-oauth-client-commons/gradle.lockfile
+++ b/backend/rest-oauth-client-commons/gradle.lockfile
@@ -79,7 +79,7 @@ io.netty:netty-transport-rxtx:4.1.116.Final=testRuntimeClasspath
 io.netty:netty-transport-sctp:4.1.116.Final=testRuntimeClasspath
 io.netty:netty-transport-udt:4.1.116.Final=testRuntimeClasspath
 io.netty:netty-transport:4.1.116.Final=testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -115,10 +115,10 @@ org.checkerframework:checker-qual:3.43.0=testRuntimeClasspath
 org.freemarker:freemarker:2.3.33=testRuntimeClasspath
 org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jetbrains.kotlin:kotlin-reflect:1.9.25=testRuntimeClasspath
 org.jetbrains.kotlin:kotlin-stdlib-common:1.9.25=testCompileClasspath,testRuntimeClasspath
 org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.25=testCompileClasspath,testRuntimeClasspath
@@ -137,9 +137,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=compileClasspath,jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/rest-service-commons/gradle.lockfile b/backend/rest-service-commons/gradle.lockfile
index daefac1db7f7d73c5934034293db60d76337f41e..022e137af667c0f8f7cf0c7bda6f23130a7478ec 100644
--- a/backend/rest-service-commons/gradle.lockfile
+++ b/backend/rest-service-commons/gradle.lockfile
@@ -28,11 +28,11 @@ org.apiguardian:apiguardian-api:1.1.2=productionRuntimeClasspath,runtimeClasspat
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
-org.jetbrains:annotations:26.0.1=compileClasspath
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
+org.jetbrains:annotations:26.0.2=compileClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -45,9 +45,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/rest-service-errors/gradle.lockfile b/backend/rest-service-errors/gradle.lockfile
index b7c33814007655a6316d65fbc4d2cfad8c514e33..d331f44c03e862641913eaf5193920b7e6687088 100644
--- a/backend/rest-service-errors/gradle.lockfile
+++ b/backend/rest-service-errors/gradle.lockfile
@@ -8,7 +8,7 @@ com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspat
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -23,10 +23,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -39,9 +39,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/school-entry/build.gradle b/backend/school-entry/build.gradle
index eae704f2eadc8129693b23f7c3d2509ec3143e92..36d42bbae9aa41ed083d9ff630a6e79174f66b41 100644
--- a/backend/school-entry/build.gradle
+++ b/backend/school-entry/build.gradle
@@ -36,6 +36,7 @@ dependencies {
     testImplementation testFixtures(project(':lib-document-generator'))
     testImplementation testFixtures(project(':lib-xlsx-import'))
     testImplementation testFixtures(project(':lib-statistics'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 }
 
 dockerCompose {
diff --git a/backend/school-entry/gradle.lockfile b/backend/school-entry/gradle.lockfile
index 5f8d79fdd896b3f582e6d5565738bb9ec59e6924..8a0a7f775b95e7a6537c508ad5452731706a5475 100644
--- a/backend/school-entry/gradle.lockfile
+++ b/backend/school-entry/gradle.lockfile
@@ -79,10 +79,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -177,13 +177,13 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
-org.jetbrains:annotations:26.0.1=compileClasspath
+org.jetbrains:annotations:26.0.2=compileClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -200,16 +200,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/school-entry/openApi.json b/backend/school-entry/openApi.json
index cb19d208d19d9fef1bbf80e1f359679bab534e2f..73a5ea0741d0626a0e614a7368c6b93b670900f5 100644
--- a/backend/school-entry/openApi.json
+++ b/backend/school-entry/openApi.json
@@ -4056,18 +4056,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
-        "responses" : {
-          "200" : {
-            "description" : "OK"
-          }
-        },
-        "tags" : [ "TestHelper" ]
-      }
-    },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -4757,9 +4746,9 @@
             "format" : "uuid"
           },
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
@@ -9160,9 +9149,9 @@
         "type" : "object",
         "properties" : {
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
diff --git a/backend/school-entry/src/main/java/de/eshg/schoolentry/SchoolEntryController.java b/backend/school-entry/src/main/java/de/eshg/schoolentry/SchoolEntryController.java
index 4b16ef795850c3426345526b16237f8f5370ff59..cbb8e4fece4cd256ed62351d8820bc045e086f23 100644
--- a/backend/school-entry/src/main/java/de/eshg/schoolentry/SchoolEntryController.java
+++ b/backend/school-entry/src/main/java/de/eshg/schoolentry/SchoolEntryController.java
@@ -143,7 +143,7 @@ public class SchoolEntryController {
   }
 
   @GetMapping("/{procedureId}")
-  @Transactional(readOnly = true)
+  @Transactional
   @Operation(summary = "Get school entry procedure by id.")
   public ProcedureDetailsDto getProcedure(@PathVariable("procedureId") UUID procedureId) {
     ProcedureDetailsData procedureDetailsData =
diff --git a/backend/school-entry/src/main/java/de/eshg/schoolentry/api/CreatePersonDto.java b/backend/school-entry/src/main/java/de/eshg/schoolentry/api/CreatePersonDto.java
index a22a0b86eb80bfcb0f41becc69be2c03d1a39a57..7f2106ea238b3d87745394e1671d70759820f3ba 100644
--- a/backend/school-entry/src/main/java/de/eshg/schoolentry/api/CreatePersonDto.java
+++ b/backend/school-entry/src/main/java/de/eshg/schoolentry/api/CreatePersonDto.java
@@ -9,6 +9,7 @@ import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.DateOfBirth;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
@@ -25,7 +26,7 @@ public record CreatePersonDto(
     GenderDto gender,
     @NotNull @Size(min = 1, max = 80) String firstName,
     @NotNull @Size(min = 1, max = 120) String lastName,
-    @NotNull LocalDate dateOfBirth,
+    @NotNull @DateOfBirth LocalDate dateOfBirth,
     @Size(min = 1, max = 40) String nameAtBirth,
     @Size(min = 1, max = 50) String placeOfBirth,
     CountryCode countryOfBirth,
diff --git a/backend/school-entry/src/main/java/de/eshg/schoolentry/api/UpdatePersonRequest.java b/backend/school-entry/src/main/java/de/eshg/schoolentry/api/UpdatePersonRequest.java
index 119891b97012230a0b52d9c302b19af09fb12d04..c6e522c0d6be7be64fd8f718e4c4c471c697bdda 100644
--- a/backend/school-entry/src/main/java/de/eshg/schoolentry/api/UpdatePersonRequest.java
+++ b/backend/school-entry/src/main/java/de/eshg/schoolentry/api/UpdatePersonRequest.java
@@ -9,6 +9,7 @@ import de.eshg.base.GenderDto;
 import de.eshg.base.SalutationDto;
 import de.eshg.base.address.AddressDto;
 import de.eshg.lib.common.CountryCode;
+import de.eshg.validation.constraints.DateOfBirth;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Size;
@@ -22,7 +23,7 @@ public record UpdatePersonRequest(
     GenderDto gender,
     @NotNull @Size(min = 1, max = 80) String firstName,
     @NotNull @Size(min = 1, max = 120) String lastName,
-    @NotNull LocalDate dateOfBirth,
+    @NotNull @DateOfBirth LocalDate dateOfBirth,
     @Size(min = 1, max = 40) String nameAtBirth,
     @Size(min = 1, max = 50) String placeOfBirth,
     CountryCode countryOfBirth,
diff --git a/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/CitizenListRowReader.java b/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/CitizenListRowReader.java
index a4a7cab289a119b3bb0f23258a448a7e9e93b245..ed40755a03ad88a7aa050b437aa419cddd39f332 100644
--- a/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/CitizenListRowReader.java
+++ b/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/CitizenListRowReader.java
@@ -16,6 +16,7 @@ import de.eshg.lib.xlsximport.RowReader;
 import de.eshg.lib.xlsximport.model.AddressData;
 import de.eshg.schoolentry.business.model.ImportChildData;
 import de.eshg.schoolentry.business.model.ImportCustodianData;
+import java.time.Clock;
 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.List;
@@ -55,8 +56,8 @@ class CitizenListRowReader extends RowReader<CitizenListRow, CitizenListColumn>
               SALUTATION_CUSTODIAN_2,
               GENDER_CUSTODIAN_2));
 
-  CitizenListRowReader(Sheet sheet, List<CitizenListColumn> actualColumns) {
-    super(sheet, actualColumns, CitizenListRow::new);
+  CitizenListRowReader(Sheet sheet, Clock clock, List<CitizenListColumn> actualColumns) {
+    super(sheet, actualColumns, CitizenListRow::new, clock);
   }
 
   @Override
@@ -76,7 +77,7 @@ class CitizenListRowReader extends RowReader<CitizenListRow, CitizenListColumn>
     String lastName = cellAsString(col, LAST_NAME, errorHandler);
     String firstName = cellAsString(col, FIRST_NAME, errorHandler);
     AddressData addressData = readAddressData(col, CHILD_ADDRESS_COLUMNS, errorHandler, true);
-    LocalDate birthDate = cellAsDate(col, DATE_OF_BIRTH, errorHandler);
+    LocalDate birthDate = cellAsDateOfBirth(col, DATE_OF_BIRTH, errorHandler);
     String placeOfBirth = cellAsString(col, PLACE_OF_BIRTH, true, false, errorHandler);
     CountryCode countryCode = cellAsCountryCode(col, COUNTRY_OF_BIRTH, errorHandler);
     GenderDto genderDto = cellAsGender(col, GENDER, errorHandler);
@@ -93,7 +94,7 @@ class CitizenListRowReader extends RowReader<CitizenListRow, CitizenListColumn>
         String firstName = cellAsString(col, custodian.firstName(), errorHandler);
         String lastName = cellAsString(col, custodian.lastName(), errorHandler);
         AddressData address = readAddressData(col, custodian.address(), errorHandler, false);
-        LocalDate dateOfBirth = cellAsDate(col, custodian.dateOfBirth(), errorHandler);
+        LocalDate dateOfBirth = cellAsDateOfBirth(col, custodian.dateOfBirth(), errorHandler);
         String title = cellAsString(col, custodian.title(), true, false, errorHandler);
         SalutationDto salutation = cellAsSalutation(col, custodian.salutation(), errorHandler);
         GenderDto gender = cellAsGender(col, custodian.gender(), errorHandler);
diff --git a/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/ImportService.java b/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/ImportService.java
index fbf504551903ff91b83e663157a8d50be0318cf4..2846e0fb0a68dc59f6ea483d342340a25db7cfc3 100644
--- a/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/ImportService.java
+++ b/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/ImportService.java
@@ -40,6 +40,7 @@ import de.eshg.schoolentry.util.ProgressEntryUtil;
 import de.eshg.schoolentry.util.SchoolEntrySystemProgressEntryType;
 import jakarta.persistence.criteria.Path;
 import java.io.IOException;
+import java.time.Clock;
 import java.time.Year;
 import java.util.*;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
@@ -55,6 +56,7 @@ public class ImportService {
 
   private static final Logger log = LoggerFactory.getLogger(ImportService.class);
 
+  private final Clock clock;
   private final Validator validator;
   private final SchoolEntryService schoolEntryService;
   private final LabelService labelService;
@@ -67,6 +69,7 @@ public class ImportService {
   private final SchoolEntryProcedureRepository schoolEntryProcedureRepository;
 
   public ImportService(
+      Clock clock,
       Validator validator,
       SchoolEntryService schoolEntryService,
       LabelService labelService,
@@ -77,6 +80,7 @@ public class ImportService {
       SchoolEntryProperties schoolEntryProperties,
       ProcedureTypeAssignmentHelper procedureTypeAssignmentHelper,
       SchoolEntryProcedureRepository schoolEntryProcedureRepository) {
+    this.clock = clock;
     this.validator = validator;
     this.schoolEntryService = schoolEntryService;
     this.labelService = labelService;
@@ -148,7 +152,7 @@ public class ImportService {
       List<CitizenListColumn> actualColumns) {
     return new CitizenOrSchoolListImporter<>(
         sheet,
-        new CitizenListRowReader(sheet, actualColumns),
+        new CitizenListRowReader(sheet, clock, actualColumns),
         new FeedbackColumnAccessor(actualColumns),
         importType,
         new CitizenListRowValueMapper(),
@@ -168,7 +172,7 @@ public class ImportService {
       List<SchoolListColumn> actualColumns) {
     return new CitizenOrSchoolListImporter<>(
         sheet,
-        new SchoolListRowReader(sheet, actualColumns),
+        new SchoolListRowReader(sheet, clock, actualColumns),
         new FeedbackColumnAccessor(actualColumns),
         importType,
         new SchoolListRowValueMapper(schoolYear, procedureTypeAssignmentHelper),
@@ -186,7 +190,7 @@ public class ImportService {
       List<PastProcedureListColumn> actualColumns) {
     return new PastProcedureListImporter(
         sheet,
-        new PastProcedureListRowReader(sheet, actualColumns),
+        new PastProcedureListRowReader(sheet, clock, actualColumns),
         new FeedbackColumnAccessor(actualColumns),
         schoolId,
         schoolYear,
diff --git a/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/PastProcedureListRowReader.java b/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/PastProcedureListRowReader.java
index 35cfe705ae3ca15b0201e672e4e4c64662bfc6f1..dcae946346d18365268397f86da08f022ad756f4 100644
--- a/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/PastProcedureListRowReader.java
+++ b/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/PastProcedureListRowReader.java
@@ -15,6 +15,7 @@ import de.eshg.schoolentry.api.CountryCodeDto;
 import de.eshg.schoolentry.business.model.*;
 import de.eshg.schoolentry.domain.model.*;
 import de.eshg.schoolentry.mapper.AnamnesisMapper;
+import java.time.Clock;
 import java.time.LocalDate;
 import java.time.Period;
 import java.time.YearMonth;
@@ -35,8 +36,9 @@ class PastProcedureListRowReader extends RowReader<PastProcedureListRow, PastPro
   static final List<PastProcedureListColumn> CHRONIC_DISEASE_ICD10_COLUMNS =
       List.of(CHRONIC_DISEASE_ICD10_1, CHRONIC_DISEASE_ICD10_2, CHRONIC_DISEASE_ICD10_3);
 
-  PastProcedureListRowReader(Sheet sheet, List<PastProcedureListColumn> actualColumns) {
-    super(sheet, actualColumns, PastProcedureListRow::new);
+  PastProcedureListRowReader(
+      Sheet sheet, Clock clock, List<PastProcedureListColumn> actualColumns) {
+    super(sheet, actualColumns, PastProcedureListRow::new, clock);
   }
 
   @Override
@@ -356,7 +358,7 @@ class PastProcedureListRowReader extends RowReader<PastProcedureListRow, PastPro
     return new ImportChildData(
         cellAsString(col, FIRST_NAME, errorHandler),
         cellAsString(col, LAST_NAME, errorHandler),
-        cellAsDate(col, DATE_OF_BIRTH, errorHandler),
+        cellAsDateOfBirth(col, DATE_OF_BIRTH, errorHandler),
         cellAsGender(col, GENDER, errorHandler),
         readAddressData(
             col,
diff --git a/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/SchoolListRowReader.java b/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/SchoolListRowReader.java
index 38ba1d5335c692d6189e01e5bdb08ac2f205c615..a68784b903269f9b838063c1106e1c58c13ed603 100644
--- a/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/SchoolListRowReader.java
+++ b/backend/school-entry/src/main/java/de/eshg/schoolentry/importer/SchoolListRowReader.java
@@ -11,13 +11,14 @@ import de.eshg.lib.xlsximport.ColumnAccessor;
 import de.eshg.lib.xlsximport.ErrorHandler;
 import de.eshg.lib.xlsximport.RowReader;
 import de.eshg.schoolentry.business.model.ImportChildData;
+import java.time.Clock;
 import java.util.List;
 import org.apache.poi.ss.usermodel.Sheet;
 
 class SchoolListRowReader extends RowReader<SchoolListRow, SchoolListColumn> {
 
-  SchoolListRowReader(Sheet sheet, List<SchoolListColumn> actualColumns) {
-    super(sheet, actualColumns, SchoolListRow::new);
+  SchoolListRowReader(Sheet sheet, Clock clock, List<SchoolListColumn> actualColumns) {
+    super(sheet, actualColumns, SchoolListRow::new, clock);
   }
 
   @Override
@@ -35,7 +36,7 @@ class SchoolListRowReader extends RowReader<SchoolListRow, SchoolListColumn> {
     return new ImportChildData(
         cellAsString(col, FIRST_NAME, errorHandler),
         cellAsString(col, LAST_NAME, errorHandler),
-        cellAsDate(col, DATE_OF_BIRTH, errorHandler),
+        cellAsDateOfBirth(col, DATE_OF_BIRTH, errorHandler),
         cellAsGender(col, GENDER, errorHandler),
         readAddressData(
             col,
diff --git a/backend/school-entry/src/main/java/de/eshg/schoolentry/testhelper/SchoolEntryTestHelperController.java b/backend/school-entry/src/main/java/de/eshg/schoolentry/testhelper/SchoolEntryTestHelperController.java
index 3e4cc69b589f2b578f4592cb476a672793b823e8..ccc538a2b46c71f879c33c5d9290589783d13e03 100644
--- a/backend/school-entry/src/main/java/de/eshg/schoolentry/testhelper/SchoolEntryTestHelperController.java
+++ b/backend/school-entry/src/main/java/de/eshg/schoolentry/testhelper/SchoolEntryTestHelperController.java
@@ -5,7 +5,7 @@
 
 package de.eshg.schoolentry.testhelper;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.lib.appointmentblock.LocationSelectionMode;
 import de.eshg.lib.appointmentblock.api.CreateAppointmentBlockGroupResponse;
 import de.eshg.lib.appointmentblock.spring.AppointmentBlockProperties;
@@ -24,7 +24,6 @@ import de.eshg.testhelper.api.PopulationRequest;
 import de.eshg.testhelper.environment.EnvironmentConfig;
 import de.eshg.testhelper.population.ListWithTotalNumber;
 import jakarta.validation.Valid;
-import java.io.IOException;
 import java.util.UUID;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -37,7 +36,7 @@ import org.springframework.web.service.annotation.PostExchange;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class SchoolEntryTestHelperController extends TestHelperController
-    implements SharedAuditLogTestHelperApi {
+    implements AuditLogClientTestHelperApi {
 
   private final SchoolEntryTestHelperService schoolEntryTestHelperService;
   private final SchoolEntryFeatureToggle schoolEntryFeatureToggle;
@@ -126,12 +125,7 @@ public class SchoolEntryTestHelperController extends TestHelperController
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
-  }
-
-  @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 }
diff --git a/backend/school-entry/src/main/resources/migrations/0077_add_auditlog_entry.xml b/backend/school-entry/src/main/resources/migrations/0077_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..28652f29b57ec0315a42976d18deee225ec7f99e
--- /dev/null
+++ b/backend/school-entry/src/main/resources/migrations/0077_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/school-entry/src/main/resources/migrations/0078_convert_duration_columns_to_interval.xml b/backend/school-entry/src/main/resources/migrations/0078_convert_duration_columns_to_interval.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b823d445751a347a9bd4f46b15ce1307647cc
--- /dev/null
+++ b/backend/school-entry/src/main/resources/migrations/0078_convert_duration_columns_to_interval.xml
@@ -0,0 +1,30 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="use_interval_for_durations">
+    <sql>
+      ALTER TABLE appointment_type_config
+      ALTER COLUMN standard_duration_in_minutes TYPE interval second(6)
+      USING (standard_duration_in_minutes * INTERVAL '1 minute');
+    </sql>
+    <renameColumn tableName="appointment_type_config"
+                  oldColumnName="standard_duration_in_minutes"
+                  newColumnName="standard_duration"/>
+
+    <sql>
+      ALTER TABLE appointment_block_group
+      ALTER COLUMN slot_duration_in_minutes TYPE interval second(6)
+      USING (slot_duration_in_minutes * INTERVAL '1 minute');
+    </sql>
+    <renameColumn tableName="appointment_block_group"
+                  oldColumnName="slot_duration_in_minutes"
+                  newColumnName="slot_duration"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/school-entry/src/main/resources/migrations/changelog.xml b/backend/school-entry/src/main/resources/migrations/changelog.xml
index e440340e179f4387a08c8ab9746e0f838388f0a4..1fbfda436c3fecb4e1848011cd2a5736d7946d8f 100644
--- a/backend/school-entry/src/main/resources/migrations/changelog.xml
+++ b/backend/school-entry/src/main/resources/migrations/changelog.xml
@@ -84,5 +84,7 @@
   <include file="migrations/0074_add_cemetery_delete_at.xml"/>
   <include file="migrations/0075_add_previous_file_state_id_to_system_progress_entry.xml"/>
   <include file="migrations/0076_add_waiting_status.xml"/>
+  <include file="migrations/0077_add_auditlog_entry.xml"/>
+  <include file="migrations/0078_convert_duration_columns_to_interval.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/service-commons/gradle.lockfile b/backend/service-commons/gradle.lockfile
index 4b85b0791360fcc5ed4cec672127605a43463fef..641c789b08285695998734de7f9d2e1c823c41d8 100644
--- a/backend/service-commons/gradle.lockfile
+++ b/backend/service-commons/gradle.lockfile
@@ -25,10 +25,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -41,9 +41,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/service-directory/gradle.lockfile b/backend/service-directory/gradle.lockfile
index 1a69c45e088dabc9bc0575ea929dddc6e4e5baa3..36b9881a3973e8aa8404fb01f77775ad9f7ea75c 100644
--- a/backend/service-directory/gradle.lockfile
+++ b/backend/service-directory/gradle.lockfile
@@ -60,10 +60,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -114,10 +114,10 @@ org.hibernate.common:hibernate-commons-annotations:7.0.3.Final=productionRuntime
 org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -135,16 +135,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/spatz-dns/gradle.lockfile b/backend/spatz-dns/gradle.lockfile
index e1de784a1f2d3bbc73fbb37623b8688c015ee47e..205a9bf9ba3e7ed6cf8eda70609b6b6220bdab63 100644
--- a/backend/spatz-dns/gradle.lockfile
+++ b/backend/spatz-dns/gradle.lockfile
@@ -20,10 +20,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -36,9 +36,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/spatz/build.gradle b/backend/spatz/build.gradle
index 8e36fefa9224c8ab962e6f7c4d3367216d24e182..90c5a3f24c079b6d6cdb1be010efd9c04da9c505 100644
--- a/backend/spatz/build.gradle
+++ b/backend/spatz/build.gradle
@@ -57,7 +57,7 @@ tasks.named('test').configure {
 }
 
 ext.listenPort=80
-ext.additionalAptPackages = "netcat node-ws nmap dnsutils"
+ext.additionalAptPackages = "netcat-openbsd node-ws nmap dnsutils"
 createDockerfile {
     healthcheck(new Dockerfile.Healthcheck("nc -z 127.0.0.1 ${listenPort}").withStartPeriod(Duration.ofSeconds(60)).withInterval(Duration.ofSeconds(5)))
 }
diff --git a/backend/spatz/gradle.lockfile b/backend/spatz/gradle.lockfile
index 65b35f5bd3809b2638a44f2c87b4473bd672dfa9..8bb76ef2aa0853a957842bb847dd3288ef6bea81 100644
--- a/backend/spatz/gradle.lockfile
+++ b/backend/spatz/gradle.lockfile
@@ -50,7 +50,7 @@ de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeCla
 de.cronn:postgres-snapshot-util:1.4=testRuntimeClasspath
 de.cronn:test-utils:1.1.1=testCompileClasspath,testRuntimeClasspath
 de.cronn:validation-file-assertions:0.8.0=testCompileClasspath,testRuntimeClasspath
-dnsjava:dnsjava:3.6.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+dnsjava:dnsjava:3.6.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.fabric8:kubernetes-client-api:6.10.0=testCompileClasspath,testRuntimeClasspath
 io.fabric8:kubernetes-client:6.10.0=testCompileClasspath,testRuntimeClasspath
 io.fabric8:kubernetes-httpclient-okhttp:6.10.0=testRuntimeClasspath
@@ -103,8 +103,8 @@ io.netty:netty-transport:4.1.116.Final=compileClasspath,productionRuntimeClasspa
 io.projectreactor.netty:reactor-netty-core:1.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.projectreactor.netty:reactor-netty-http:1.2.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.projectreactor:reactor-core:3.7.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.mail:jakarta.mail-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -151,10 +151,10 @@ org.glassfish.jaxb:xsom:4.0.5=productionRuntimeClasspath,runtimeClasspath,testCo
 org.hamcrest:hamcrest-core:2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.java-websocket:Java-WebSocket:1.6.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jboss.logging:commons-logging-jboss-logging:1.0.0.Final=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.jboss.logging:jboss-logging:3.6.1.Final=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -186,9 +186,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.reactivestreams:reactive-streams:1.0.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/statistics/build.gradle b/backend/statistics/build.gradle
index 637ff8c4bcf2f27b411f9c4310a601cec2e5673d..d541c057d93f656d190abd8e6cf01e356d3fd09b 100644
--- a/backend/statistics/build.gradle
+++ b/backend/statistics/build.gradle
@@ -19,10 +19,18 @@ dependencies {
     implementation 'org.apache.poi:poi:latest.release'
     implementation 'org.apache.poi:poi-ooxml:latest.release'
 
+    // arx + dependencies
+    implementation files('lib/org/deidentifier/arx/libarx-3.9.1-min.jar')
+    implementation files('lib/de/linearbits/jhpl/jhpl-0.0.1.jar')
+    implementation 'com.carrotsearch:hppc:0.6.0'
+    implementation 'colt:colt:1.2.0'
+    implementation 'org.apache.commons:commons-math3:latest.release'
+
     annotationProcessor 'org.hibernate.orm:hibernate-jpamodelgen'
     runtimeOnly 'org.postgresql:postgresql'
 
     testImplementation testFixtures(project(':business-module-persistence-commons'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 }
 
 dockerCompose {
diff --git a/backend/statistics/gradle.lockfile b/backend/statistics/gradle.lockfile
index 18feab52904f27446d8a74843b1242dfbca7be1b..34fb44c6f5b0b0e93e527ef7f37652faaf26141f 100644
--- a/backend/statistics/gradle.lockfile
+++ b/backend/statistics/gradle.lockfile
@@ -3,6 +3,8 @@
 # This file is expected to be part of source control.
 ch.qos.logback:logback-classic:1.5.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 ch.qos.logback:logback-core:1.5.12=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+colt:colt:1.2.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+com.carrotsearch:hppc:0.6.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 com.fasterxml.jackson.core:jackson-annotations:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 com.fasterxml.jackson.core:jackson-core:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 com.fasterxml.jackson.core:jackson-databind:2.18.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -46,6 +48,7 @@ com.zaxxer:HikariCP:5.1.0=compileClasspath,productionRuntimeClasspath,runtimeCla
 com.zaxxer:SparseBitSet:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 commons-codec:commons-codec:1.17.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 commons-io:commons-io:2.18.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+concurrent:concurrent:1.3.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 de.cronn:commons-lang:1.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 de.cronn:liquibase-changelog-generator-postgresql:1.0=testCompileClasspath,testRuntimeClasspath
 de.cronn:liquibase-changelog-generator:1.0=testCompileClasspath,testRuntimeClasspath
@@ -66,10 +69,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -97,7 +100,7 @@ org.apache.commons:commons-collections4:4.4=compileClasspath,productionRuntimeCl
 org.apache.commons:commons-compress:1.27.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.apache.commons:commons-lang3:3.17.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.apache.commons:commons-math3:3.6.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.apache.commons:commons-text:1.12.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.apache.commons:commons-text:1.13.0=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.apache.httpcomponents.client5:httpclient5:5.4.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.apache.httpcomponents.core5:httpcore5-h2:5.3.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.apache.httpcomponents.core5:httpcore5:5.3.1=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -132,10 +135,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -154,16 +157,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/statistics/lib/de/linearbits/jhpl/jhpl-0.0.1.jar b/backend/statistics/lib/de/linearbits/jhpl/jhpl-0.0.1.jar
new file mode 100644
index 0000000000000000000000000000000000000000..94f8d9470d00f9f2331b24e7fc408f81997caff0
Binary files /dev/null and b/backend/statistics/lib/de/linearbits/jhpl/jhpl-0.0.1.jar differ
diff --git a/backend/statistics/lib/org/deidentifier/arx/libarx-3.9.1-min.jar b/backend/statistics/lib/org/deidentifier/arx/libarx-3.9.1-min.jar
new file mode 100644
index 0000000000000000000000000000000000000000..e52b715f1d4cb47ec1f2b6845152030d9d67cd54
Binary files /dev/null and b/backend/statistics/lib/org/deidentifier/arx/libarx-3.9.1-min.jar differ
diff --git a/backend/statistics/openApi.json b/backend/statistics/openApi.json
index 43a99098d01e0e26660b47ec91814e981119b4b8..b5621b430ff800b8204ac6c5d4bdf5a52a831534 100644
--- a/backend/statistics/openApi.json
+++ b/backend/statistics/openApi.json
@@ -1421,18 +1421,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
-        "responses" : {
-          "200" : {
-            "description" : "OK"
-          }
-        },
-        "tags" : [ "TestHelper" ]
-      }
-    },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -2342,12 +2331,15 @@
         }
       },
       "BaseDataSourceAttribute" : {
-        "required" : [ "code", "displayName", "name" ],
+        "required" : [ "code", "dataPrivacyCategory", "displayName", "name" ],
         "type" : "object",
         "properties" : {
           "code" : {
             "type" : "string"
           },
+          "dataPrivacyCategory" : {
+            "$ref" : "#/components/schemas/DataPrivacyCategory"
+          },
           "displayName" : {
             "type" : "string"
           },
@@ -2485,6 +2477,9 @@
           "code" : {
             "type" : "string"
           },
+          "dataPrivacyCategory" : {
+            "$ref" : "#/components/schemas/DataPrivacyCategory"
+          },
           "name" : {
             "type" : "string"
           }
@@ -2676,6 +2671,10 @@
           }
         }
       },
+      "DataPrivacyCategory" : {
+        "type" : "string",
+        "enum" : [ "QUASI_IDENTIFYING", "SENSITIVE", "INSENSITIVE" ]
+      },
       "DataRow" : {
         "required" : [ "values" ],
         "type" : "object",
@@ -3409,7 +3408,7 @@
         }
       },
       "GetEvaluationResponse" : {
-        "required" : [ "dataRows", "evaluationInfo", "tableColumnHeaders", "totalNumberOfElements" ],
+        "required" : [ "dataRows", "evaluationInfo", "sortDirection", "tableColumnHeaders", "totalNumberOfElements" ],
         "type" : "object",
         "properties" : {
           "dataRows" : {
@@ -3421,6 +3420,12 @@
           "evaluationInfo" : {
             "$ref" : "#/components/schemas/EvaluationInfo"
           },
+          "sortAttribute" : {
+            "$ref" : "#/components/schemas/AttributeSelection"
+          },
+          "sortDirection" : {
+            "$ref" : "#/components/schemas/SortDirection"
+          },
           "tableColumnHeaders" : {
             "type" : "array",
             "items" : {
@@ -3852,6 +3857,12 @@
             "grouping" : {
               "$ref" : "#/components/schemas/Grouping"
             },
+            "maxBin" : {
+              "type" : "number"
+            },
+            "minBin" : {
+              "type" : "number"
+            },
             "numberOfBins" : {
               "maximum" : 50,
               "minimum" : 2,
@@ -4448,7 +4459,7 @@
       },
       "SortDirection" : {
         "type" : "string",
-        "default" : "DESC",
+        "default" : "ASC",
         "enum" : [ "ASC", "DESC" ]
       },
       "StatisticsFeature" : {
@@ -4493,6 +4504,9 @@
           "businessModule" : {
             "type" : "string"
           },
+          "dataPrivacyCategory" : {
+            "$ref" : "#/components/schemas/DataPrivacyCategory"
+          },
           "dataSourceId" : {
             "type" : "string",
             "format" : "uuid"
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/AnalysisService.java b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/AnalysisService.java
index 2abbb097cef15552168da243053f39272b0f71a4..7dbbe6807b0c29c7d6d95f0055a6d5ae8824ebb4 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/AnalysisService.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/AnalysisService.java
@@ -360,19 +360,37 @@ public class AnalysisService {
       }
     }
 
+    validateBinning(histogramChartConfiguration, name);
+  }
+
+  private static void validateBinning(
+      HistogramChartConfigurationDto histogramChartConfiguration, String name) {
     if (histogramChartConfiguration.binningMode().equals(BinningModeDto.MANUAL)
-        && histogramChartConfiguration.numberOfBins() == null) {
+        && (histogramChartConfiguration.numberOfBins() == null
+            || histogramChartConfiguration.minBin() == null
+            || histogramChartConfiguration.maxBin() == null)) {
       throw new BadRequestException(
-          "'%s': numberOfBins is required for binning mode '%s'"
+          "'%s': numberOfBins, minBin & maxBin is required for binning mode '%s'"
               .formatted(name, BinningModeDto.MANUAL.name()));
     }
 
     if (histogramChartConfiguration.binningMode().equals(BinningModeDto.AUTO)
-        && histogramChartConfiguration.numberOfBins() != null) {
+        && (histogramChartConfiguration.numberOfBins() != null
+            || histogramChartConfiguration.minBin() != null
+            || histogramChartConfiguration.maxBin() != null)) {
       throw new BadRequestException(
-          "'%s': numberOfBins must not be set for binning mode '%s'"
+          "'%s': numberOfBins, minBin & maxBin must not be set for binning mode '%s'"
               .formatted(name, BinningModeDto.AUTO.name()));
     }
+
+    if (histogramChartConfiguration.binningMode().equals(BinningModeDto.MANUAL)) {
+      boolean maxIsNotGreaterThanMin =
+          histogramChartConfiguration.maxBin().compareTo(histogramChartConfiguration.minBin()) <= 0;
+      if (maxIsNotGreaterThanMin) {
+        throw new BadRequestException(
+            "'%s': value of maxBin must be greater than minBin".formatted(name));
+      }
+    }
   }
 
   public List<HistogramBin> calculateHistogramBins(
@@ -393,20 +411,22 @@ public class AnalysisService {
     }
 
     int numberOfBins;
+    BigDecimal minimum;
+    BigDecimal maximum;
     if (histogramChartConfiguration.binningMode().equals(BinningModeDto.MANUAL)) {
       numberOfBins = histogramChartConfiguration.numberOfBins();
+      maximum = histogramChartConfiguration.maxBin();
+      minimum = histogramChartConfiguration.minBin();
     } else {
       numberOfBins = Math.clamp((int) Math.ceil(Math.sqrt(numberOfDataPoints)), 2, 50);
-    }
 
-    BigDecimal minimum;
-    BigDecimal maximum;
-    if (tableColumnPrimary.getValueType().equals(TableColumnValueType.DECIMAL)) {
-      minimum = tableColumnPrimary.getMinMaxNullUnknownValues().getMinDecimal();
-      maximum = tableColumnPrimary.getMinMaxNullUnknownValues().getMaxDecimal();
-    } else {
-      minimum = new BigDecimal(tableColumnPrimary.getMinMaxNullUnknownValues().getMinInteger());
-      maximum = new BigDecimal(tableColumnPrimary.getMinMaxNullUnknownValues().getMaxInteger());
+      if (tableColumnPrimary.getValueType().equals(TableColumnValueType.DECIMAL)) {
+        minimum = tableColumnPrimary.getMinMaxNullUnknownValues().getMinDecimal();
+        maximum = tableColumnPrimary.getMinMaxNullUnknownValues().getMaxDecimal();
+      } else {
+        minimum = new BigDecimal(tableColumnPrimary.getMinMaxNullUnknownValues().getMinInteger());
+        maximum = new BigDecimal(tableColumnPrimary.getMinMaxNullUnknownValues().getMaxInteger());
+      }
     }
 
     BigDecimal binWidth = calculateBinWidth(maximum, minimum, numberOfBins);
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/DataAggregationService.java b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/DataAggregationService.java
index 2c978d21915c16044e5d54c5cc724ebebce27a0e..82bd31f360aac43e2d019a6f64030a5f3693eff7 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/DataAggregationService.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/DataAggregationService.java
@@ -17,6 +17,7 @@ import de.eshg.lib.aggregation.BusinessModuleAggregationHelper;
 import de.eshg.lib.aggregation.ClientResponse;
 import de.eshg.lib.auditlog.AuditLogger;
 import de.eshg.lib.statistics.api.Attribute;
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import de.eshg.lib.statistics.api.DataRow;
 import de.eshg.lib.statistics.api.DataSourceSensitivity;
 import de.eshg.lib.statistics.api.DataTableHeader;
@@ -39,6 +40,7 @@ import de.eshg.statistics.persistence.entity.Evaluation;
 import de.eshg.statistics.persistence.entity.MinMaxNullUnknownValues;
 import de.eshg.statistics.persistence.entity.StatisticsDataSensitivity;
 import de.eshg.statistics.persistence.entity.TableColumn;
+import de.eshg.statistics.persistence.entity.TableColumnDataPrivacyCategory;
 import de.eshg.statistics.persistence.entity.TableColumnValueType;
 import de.eshg.statistics.persistence.entity.TableRow;
 import de.eshg.statistics.persistence.entity.ValueToMeaning;
@@ -312,6 +314,8 @@ public class DataAggregationService {
 
     if (baseModuleAttribute == null) {
       tableColumn.setValueType(mapToTableColumnValueType(businessModuleAttribute.valueType()));
+      tableColumn.setDataPrivacyCategory(
+          mapToTableColumnDataPrivacyCategory(businessModuleAttribute.dataPrivacyCategory()));
       tableColumn.setUnit(businessModuleAttribute.unit());
       tableColumn.addValueToMeanings(
           EvaluationMapper.mapToValueToMeanings(businessModuleAttribute.valueOptions()));
@@ -320,6 +324,8 @@ public class DataAggregationService {
       tableColumn.setBaseModuleAttributeCode(baseModuleAttribute.code());
       tableColumn.setBaseModuleAttributeName(baseModuleAttribute.name());
       tableColumn.setValueType(mapToTableColumnValueType(baseModuleAttribute.valueType()));
+      tableColumn.setDataPrivacyCategory(
+          mapToTableColumnDataPrivacyCategory(baseModuleAttribute.dataPrivacyCategory()));
       tableColumn.setUnit(baseModuleAttribute.unit());
       tableColumn.addValueToMeanings(
           EvaluationMapper.mapToValueToMeanings(baseModuleAttribute.valueOptions()));
@@ -340,6 +346,13 @@ public class DataAggregationService {
     return TableColumnValueType.valueOf(valueType.name());
   }
 
+  private static TableColumnDataPrivacyCategory mapToTableColumnDataPrivacyCategory(
+      DataPrivacyCategory dataPrivacyCategory) {
+    return dataPrivacyCategory == null
+        ? null
+        : TableColumnDataPrivacyCategory.valueOf(dataPrivacyCategory.name());
+  }
+
   private static List<TableColumn> createTableColumnsForBaseAttributes(
       String dataSourceName,
       String businessModuleName,
@@ -555,7 +568,10 @@ public class DataAggregationService {
             firstTableColumn.getBaseModuleAttributeCode(),
             secondTableColumn.getBaseModuleAttributeCode())
         || !Objects.equals(firstTableColumn.getUnit(), secondTableColumn.getUnit())
-        || firstTableColumn.isMandatory() != secondTableColumn.isMandatory()) {
+        || firstTableColumn.isMandatory() != secondTableColumn.isMandatory()
+        || !Objects.equals(
+            firstTableColumn.getDataPrivacyCategory(),
+            secondTableColumn.getDataPrivacyCategory())) {
       return true;
     }
     if (firstTableColumn.getValueToMeanings().size()
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/DataSourceAggregationService.java b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/DataSourceAggregationService.java
index 99e3242774ae242580a68555341ccc905fb3bf0f..12a8452e88bd1e1749e18ca8850e4e84c273a914 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/DataSourceAggregationService.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/DataSourceAggregationService.java
@@ -139,18 +139,19 @@ public class DataSourceAggregationService {
     return businessAttributes.stream()
         .map(
             attribute -> {
-              Optional<BaseAvailableDataSource> baseAvailableDataSource =
-                  findBaseAvailableDataSource(baseAvailableDataSources, attribute);
-              return new BusinessDataSourceAttribute(
-                  attribute.name(),
-                  attribute.code(),
-                  attribute.category(),
-                  baseAvailableDataSource
+              List<BaseDataSourceAttribute> baseDataSourceAttributes =
+                  findBaseAvailableDataSource(baseAvailableDataSources, attribute)
                       .map(
                           availableDataSource ->
                               mapToBaseDataSourceAttributes(
                                   attribute.name(), availableDataSource.attributes()))
-                      .orElse(null));
+                      .orElse(null);
+              return new BusinessDataSourceAttribute(
+                  attribute.name(),
+                  attribute.code(),
+                  attribute.category(),
+                  baseDataSourceAttributes == null ? attribute.dataPrivacyCategory() : null,
+                  baseDataSourceAttributes);
             })
         .toList();
   }
@@ -192,7 +193,8 @@ public class DataSourceAggregationService {
                     EvaluationMapper.getAttributeDisplayName(
                         businessAttributeName, attribute.name()),
                     attribute.name(),
-                    attribute.code()))
+                    attribute.code(),
+                    attribute.dataPrivacyCategory()))
         .toList();
   }
 }
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/EvaluationCopyService.java b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/EvaluationCopyService.java
index 585b8adb768744d9d4e1cb05063e9f9cea194b46..1a3f05c2407505fa68c22e42fd4e3b613c9baecf 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/EvaluationCopyService.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/EvaluationCopyService.java
@@ -116,6 +116,7 @@ public class EvaluationCopyService {
     copy.setBaseModuleAttributeCode(original.getBaseModuleAttributeCode());
     copy.setBaseModuleAttributeName(original.getBaseModuleAttributeName());
     copy.setValueType(original.getValueType());
+    copy.setDataPrivacyCategory(original.getDataPrivacyCategory());
     copy.setUnit(original.getUnit());
     copy.setDataSourceName(original.getDataSourceName());
     copy.setDataSourceId(original.getDataSourceId());
@@ -484,6 +485,8 @@ public class EvaluationCopyService {
     copy.setGrouping(original.getGrouping());
     copy.setBinningMode(original.getBinningMode());
     copy.setNumberOfBins(original.getNumberOfBins());
+    copy.setMinBin(original.getMinBin());
+    copy.setMaxBin(original.getMaxBin());
     if (copyHistogramBins) {
       copy.addBins(copyHistogramBins(original.getBins()));
     }
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/EvaluationService.java b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/EvaluationService.java
index 25f8ee96db89453b457a381591a19a530d747ae6..814f3ad46a73e8e3b7e7532e20bff6c459696ffe 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/aggregation/EvaluationService.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/aggregation/EvaluationService.java
@@ -464,6 +464,10 @@ public class EvaluationService extends AbstractAggregationResultService {
 
     return EvaluationMapper.mapToApi(
         evaluation,
+        sortTableColumn.getValueType().equals(TableColumnValueType.PROCEDURE_REFERENCE)
+            ? null
+            : sortTableColumn,
+        getEvaluationRequest.sortDirection(),
         tableRowPage.get().toList(),
         tableRowPage.getTotalElements(),
         isTooMuchDataForExportFunction().apply(evaluation));
@@ -480,7 +484,13 @@ public class EvaluationService extends AbstractAggregationResultService {
       AttributeSelectionDto sortAttribute, Evaluation evaluation) {
     TableColumn sortTableColumn = AggregationResultUtil.getTableColumn(sortAttribute, evaluation);
     if (sortTableColumn == null) {
-      sortTableColumn = evaluation.getTableColumns().getFirst();
+      sortTableColumn =
+          evaluation.getTableColumns().stream()
+              .filter(
+                  tableColumn ->
+                      !tableColumn.getValueType().equals(TableColumnValueType.PROCEDURE_REFERENCE))
+              .findFirst()
+              .orElse(evaluation.getTableColumns().getFirst());
     }
     return sortTableColumn;
   }
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/api/TableColumnHeader.java b/backend/statistics/src/main/java/de/eshg/statistics/api/TableColumnHeader.java
index 3b9d07c82ebd9714c75fd6cb90b8df473fdc55fd..b6d58e5d2f0bfaa238fa1551731f18c620862a98 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/api/TableColumnHeader.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/api/TableColumnHeader.java
@@ -5,6 +5,7 @@
 
 package de.eshg.statistics.api;
 
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import de.eshg.statistics.api.attributes.AbstractTableColumnHeaderAttribute;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
@@ -16,4 +17,5 @@ public record TableColumnHeader(
     @NotBlank String businessModule,
     @NotNull UUID dataSourceId,
     @NotBlank String dataSourceName,
-    @NotNull @Valid AbstractTableColumnHeaderAttribute attribute) {}
+    @NotNull @Valid AbstractTableColumnHeaderAttribute attribute,
+    DataPrivacyCategory dataPrivacyCategory) {}
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/api/chart/HistogramChartConfigurationDto.java b/backend/statistics/src/main/java/de/eshg/statistics/api/chart/HistogramChartConfigurationDto.java
index e5e0cad2d3c91718d25a8b05adb2b7698c958676..327c56bc87003e42782bd3211269980c5a38dc33 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/api/chart/HistogramChartConfigurationDto.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/api/chart/HistogramChartConfigurationDto.java
@@ -13,6 +13,7 @@ import jakarta.validation.Valid;
 import jakarta.validation.constraints.Max;
 import jakarta.validation.constraints.Min;
 import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
 
 @Schema(name = SCHEMA_NAME)
 public record HistogramChartConfigurationDto(
@@ -21,7 +22,9 @@ public record HistogramChartConfigurationDto(
     ScalingDto scaling,
     GroupingDto grouping,
     @NotNull BinningModeDto binningMode,
-    @Min(2) @Max(50) Integer numberOfBins)
+    @Min(2) @Max(50) Integer numberOfBins,
+    BigDecimal minBin,
+    BigDecimal maxBin)
     implements AddChartConfigurationDto, ChartConfigurationDto {
   public static final String SCHEMA_NAME = "HistogramChartConfiguration";
 
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/api/datasource/BaseDataSourceAttribute.java b/backend/statistics/src/main/java/de/eshg/statistics/api/datasource/BaseDataSourceAttribute.java
index d3b450677b71292e6382cc4df86411628167adc8..63ad5267496c1f219b9c8a3ed969b103c22d607a 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/api/datasource/BaseDataSourceAttribute.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/api/datasource/BaseDataSourceAttribute.java
@@ -5,7 +5,12 @@
 
 package de.eshg.statistics.api.datasource;
 
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
 
 public record BaseDataSourceAttribute(
-    @NotBlank String displayName, @NotBlank String name, @NotBlank String code) {}
+    @NotBlank String displayName,
+    @NotBlank String name,
+    @NotBlank String code,
+    @NotNull DataPrivacyCategory dataPrivacyCategory) {}
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/api/datasource/BusinessDataSourceAttribute.java b/backend/statistics/src/main/java/de/eshg/statistics/api/datasource/BusinessDataSourceAttribute.java
index 82d062773812173c230b31a2a257d4cb39f3098d..512aee6b08c2fc29ea3b01b6fcaac412481eeb47 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/api/datasource/BusinessDataSourceAttribute.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/api/datasource/BusinessDataSourceAttribute.java
@@ -5,6 +5,7 @@
 
 package de.eshg.statistics.api.datasource;
 
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
 import java.util.List;
@@ -13,4 +14,5 @@ public record BusinessDataSourceAttribute(
     @NotBlank String name,
     @NotBlank String code,
     @NotBlank String category,
+    DataPrivacyCategory dataPrivacyCategory,
     @Valid List<BaseDataSourceAttribute> baseAttributes) {}
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/api/evaluation/GetEvaluationRequest.java b/backend/statistics/src/main/java/de/eshg/statistics/api/evaluation/GetEvaluationRequest.java
index be3eb1f5c8c3ad3fe65248be2fc563790edc67fe..c95f73fdf9edf75941ea4d8493332491ad0d060b 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/api/evaluation/GetEvaluationRequest.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/api/evaluation/GetEvaluationRequest.java
@@ -16,7 +16,7 @@ import java.util.Optional;
 
 public record GetEvaluationRequest(
     @Valid AttributeSelectionDto sortAttribute,
-    @Schema(defaultValue = "DESC") SortDirection sortDirection,
+    @Schema(defaultValue = "ASC") SortDirection sortDirection,
     @Min(0) @Schema(defaultValue = "0") Integer page,
     @Min(1) @Schema(defaultValue = "25") Integer pageSize,
     @Valid List<TableColumnFilterParameter> filters) {
@@ -28,7 +28,7 @@ public record GetEvaluationRequest(
       Integer pageSize,
       List<TableColumnFilterParameter> filters) {
     this.sortAttribute = sortAttribute;
-    this.sortDirection = Optional.ofNullable(sortDirection).orElse(SortDirection.DESC);
+    this.sortDirection = Optional.ofNullable(sortDirection).orElse(SortDirection.ASC);
     this.page = Optional.ofNullable(page).orElse(0);
     this.pageSize = Optional.ofNullable(pageSize).orElse(25);
     this.filters = filters;
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/api/evaluation/GetEvaluationResponse.java b/backend/statistics/src/main/java/de/eshg/statistics/api/evaluation/GetEvaluationResponse.java
index 9d7f9f0480770b81f49151876f86833b94bbd71d..3fe45f82380df4b1745dafd2c3470b213cacd299 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/api/evaluation/GetEvaluationResponse.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/api/evaluation/GetEvaluationResponse.java
@@ -5,7 +5,9 @@
 
 package de.eshg.statistics.api.evaluation;
 
+import de.eshg.base.SortDirection;
 import de.eshg.lib.statistics.api.DataRow;
+import de.eshg.statistics.api.AttributeSelectionDto;
 import de.eshg.statistics.api.TableColumnHeader;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.Min;
@@ -14,6 +16,8 @@ import java.util.List;
 
 public record GetEvaluationResponse(
     @NotNull @Valid EvaluationInfo evaluationInfo,
+    @Valid AttributeSelectionDto sortAttribute,
+    @NotNull SortDirection sortDirection,
     @NotNull @Valid List<TableColumnHeader> tableColumnHeaders,
     @NotNull @Valid List<DataRow> dataRows,
     @NotNull @Min(0) long totalNumberOfElements) {}
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/centralrepository/RepoMapper.java b/backend/statistics/src/main/java/de/eshg/statistics/centralrepository/RepoMapper.java
index 8a86461c104c166d264218f6a7efddf2b327fc7d..90d8f2635225e7f831c849cd946ff3d209b4c9a6 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/centralrepository/RepoMapper.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/centralrepository/RepoMapper.java
@@ -219,7 +219,9 @@ public class RepoMapper {
         getEnumString(histogramChartConfiguration.getScaling()),
         getEnumString(histogramChartConfiguration.getGrouping()),
         getEnumString(histogramChartConfiguration.getBinningMode()),
-        histogramChartConfiguration.getNumberOfBins());
+        histogramChartConfiguration.getNumberOfBins(),
+        histogramChartConfiguration.getMinBin(),
+        histogramChartConfiguration.getMaxBin());
   }
 
   private static RepoLineChart mapToRepoLineChart(LineChartConfiguration lineChartConfiguration) {
@@ -450,7 +452,9 @@ public class RepoMapper {
         mapToScaling(repoHistogramChart.scaling()),
         mapToGrouping(repoHistogramChart.grouping()),
         mapToBinning(repoHistogramChart.binningMode()),
-        repoHistogramChart.numberOfBins());
+        repoHistogramChart.numberOfBins(),
+        repoHistogramChart.minBin(),
+        repoHistogramChart.maxBin());
   }
 
   private static LineChartConfigurationDto mapToLineChartConfiguration(
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/centralrepository/dto/chartconfiguration/RepoHistogramChart.java b/backend/statistics/src/main/java/de/eshg/statistics/centralrepository/dto/chartconfiguration/RepoHistogramChart.java
index 512706414e4cd5f8efee886999b32447f554327c..476490fb4438285075bd304b47ff6aa838ea0d82 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/centralrepository/dto/chartconfiguration/RepoHistogramChart.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/centralrepository/dto/chartconfiguration/RepoHistogramChart.java
@@ -11,6 +11,7 @@ import jakarta.validation.constraints.Max;
 import jakarta.validation.constraints.Min;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
 
 public record RepoHistogramChart(
     @NotNull @Valid RepoAttributeSelection primaryAttribute,
@@ -18,7 +19,9 @@ public record RepoHistogramChart(
     String scaling,
     String grouping,
     @NotBlank String binningMode,
-    @Min(2) @Max(50) Integer numberOfBins)
+    @Min(2) @Max(50) Integer numberOfBins,
+    BigDecimal minBin,
+    BigDecimal maxBin)
     implements RepoChartConfiguration {
   public static final String SCHEMA_NAME = "RepoHistogramChart";
 
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/export/AggregationResultExportService.java b/backend/statistics/src/main/java/de/eshg/statistics/export/AggregationResultExportService.java
index 0b334af03ab66217e7827518eeb3996a31acf526..8a24514d47a62985fab8acbb6fee57f1c5e41dfb 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/export/AggregationResultExportService.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/export/AggregationResultExportService.java
@@ -227,7 +227,7 @@ public class AggregationResultExportService {
     return tableRowPage.getSize();
   }
 
-  @Transactional(readOnly = true)
+  @Transactional
   public void auditLogAggregationResultDataExport(
       UUID id, AbstractAggregationResultService service, String function) {
     AbstractAggregationResult aggregationResult = service.getAbstractAggregationResultInternal(id);
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/export/DiagramExportService.java b/backend/statistics/src/main/java/de/eshg/statistics/export/DiagramExportService.java
index fed2d5c1904f2f26ea80b30abd4cc27d57bce7f3..21659f8c167ca402f49d46b36aeda0614c68c23f 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/export/DiagramExportService.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/export/DiagramExportService.java
@@ -71,7 +71,7 @@ public class DiagramExportService {
     analysisService.checkPermissionForDiagram(diagramId);
   }
 
-  @Transactional(readOnly = true)
+  @Transactional
   public Resource exportData(UUID diagramId) {
     Diagram diagram = analysisService.getDiagramInternal(diagramId);
     AbstractAggregationResult aggregationResult = diagram.getAnalysis().getAggregationResult();
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/mapper/AnalysisMapper.java b/backend/statistics/src/main/java/de/eshg/statistics/mapper/AnalysisMapper.java
index 1bb90fe3a6a84445402692ee60fe093782f7ce2f..376de85c524919507aa41dc8c64264bad52cfe63 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/mapper/AnalysisMapper.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/mapper/AnalysisMapper.java
@@ -197,6 +197,8 @@ public class AnalysisMapper {
         mapToBinningMode(histogramChartConfigurationDto.binningMode()));
     histogramChartConfiguration.setNumberOfBins(histogramChartConfigurationDto.numberOfBins());
     histogramChartConfiguration.addBins(histogramBins);
+    histogramChartConfiguration.setMinBin(histogramChartConfigurationDto.minBin());
+    histogramChartConfiguration.setMaxBin(histogramChartConfigurationDto.maxBin());
     return histogramChartConfiguration;
   }
 
@@ -395,7 +397,9 @@ public class AnalysisMapper {
         mapToScalingDto(histogramChartConfiguration.getScaling()),
         mapToGroupingDto(histogramChartConfiguration.getGrouping()),
         mapToBinningModeDto(histogramChartConfiguration.getBinningMode()),
-        histogramChartConfiguration.getNumberOfBins());
+        histogramChartConfiguration.getNumberOfBins(),
+        histogramChartConfiguration.getMinBin(),
+        histogramChartConfiguration.getMaxBin());
   }
 
   private static ChartConfigurationDto mapToChoroplethMapConfigurationDto(
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/mapper/AttributeSelectionMapper.java b/backend/statistics/src/main/java/de/eshg/statistics/mapper/AttributeSelectionMapper.java
index b62fa92fc6ec9f8e7056bef46341c318b241fe05..4831b1c3ded8a9a40f84fa3a9667a91c6fa733b7 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/mapper/AttributeSelectionMapper.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/mapper/AttributeSelectionMapper.java
@@ -7,6 +7,7 @@ package de.eshg.statistics.mapper;
 
 import de.eshg.statistics.api.AttributeSelectionDto;
 import de.eshg.statistics.persistence.entity.AttributeSelection;
+import de.eshg.statistics.persistence.entity.TableColumn;
 import java.util.Objects;
 import java.util.UUID;
 
@@ -70,4 +71,16 @@ public class AttributeSelectionMapper {
         attributeSelection.getBusinessModuleAttributeCode(),
         attributeSelection.getBaseModuleAttributeCode());
   }
+
+  public static AttributeSelectionDto mapToApi(TableColumn tableColumn) {
+    if (tableColumn == null) {
+      return null;
+    } else {
+      return new AttributeSelectionDto(
+          tableColumn.getBusinessModuleName(),
+          tableColumn.getDataSourceId(),
+          tableColumn.getBusinessModuleAttributeCode(),
+          tableColumn.getBaseModuleAttributeCode());
+    }
+  }
 }
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/mapper/EvaluationMapper.java b/backend/statistics/src/main/java/de/eshg/statistics/mapper/EvaluationMapper.java
index 856ac6552adf26b4c15193502d3d78e3202684e7..dd8e289762a7a99425831699d77a3628eaf5a424 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/mapper/EvaluationMapper.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/mapper/EvaluationMapper.java
@@ -7,6 +7,7 @@ package de.eshg.statistics.mapper;
 
 import de.eshg.base.SortDirection;
 import de.eshg.base.user.api.UserDto;
+import de.eshg.lib.statistics.api.DataPrivacyCategory;
 import de.eshg.lib.statistics.api.DataRow;
 import de.eshg.lib.statistics.api.ValueOptionInternal;
 import de.eshg.statistics.api.TableColumnHeader;
@@ -33,6 +34,7 @@ import de.eshg.statistics.persistence.entity.Evaluation;
 import de.eshg.statistics.persistence.entity.MinMaxNullUnknownValues;
 import de.eshg.statistics.persistence.entity.StatisticsDataSensitivity;
 import de.eshg.statistics.persistence.entity.TableColumn;
+import de.eshg.statistics.persistence.entity.TableColumnDataPrivacyCategory;
 import de.eshg.statistics.persistence.entity.TableColumnValueType;
 import de.eshg.statistics.persistence.entity.TableRow;
 import de.eshg.statistics.persistence.entity.ValueToMeaning;
@@ -50,11 +52,15 @@ public class EvaluationMapper {
 
   public static GetEvaluationResponse mapToApi(
       Evaluation evaluation,
+      TableColumn sortTableColumn,
+      SortDirection sortDirection,
       List<TableRow> tableRows,
       long totalNumberOfElements,
       boolean isTooMuchDataForExport) {
     return new GetEvaluationResponse(
         mapToEvaluationInfo(evaluation, isTooMuchDataForExport),
+        AttributeSelectionMapper.mapToApi(sortTableColumn),
+        sortDirection,
         mapToApi(evaluation.getTableColumns()),
         tableRows.stream().map(EvaluationMapper::mapToApi).toList(),
         totalNumberOfElements);
@@ -77,7 +83,8 @@ public class EvaluationMapper {
               tableColumn.getBusinessModuleAttributeCode(),
               tableColumn.getUnit(),
               tableColumn.getValueToMeanings(),
-              tableColumn.getMinMaxNullUnknownValues()));
+              tableColumn.getMinMaxNullUnknownValues()),
+          mapDataPrivacyCategory(tableColumn.getDataPrivacyCategory()));
     } else {
       return new TableColumnHeader(
           getAttributeDisplayName(tableColumn, false),
@@ -93,7 +100,8 @@ public class EvaluationMapper {
                   tableColumn.getBaseModuleAttributeCode(),
                   tableColumn.getUnit(),
                   tableColumn.getValueToMeanings(),
-                  tableColumn.getMinMaxNullUnknownValues())));
+                  tableColumn.getMinMaxNullUnknownValues())),
+          mapDataPrivacyCategory(tableColumn.getDataPrivacyCategory()));
     }
   }
 
@@ -171,6 +179,13 @@ public class EvaluationMapper {
     return new ValueOption(valueToMeaning.getValue(), valueToMeaning.getMeaning());
   }
 
+  private static DataPrivacyCategory mapDataPrivacyCategory(
+      TableColumnDataPrivacyCategory dataPrivacyCategory) {
+    return dataPrivacyCategory == null
+        ? null
+        : DataPrivacyCategory.valueOf(dataPrivacyCategory.name());
+  }
+
   private static DataRow mapToApi(TableRow tableRow) {
     return new DataRow(tableRow.getCellEntries().stream().map(CellEntry::getValue).toList());
   }
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/TableColumn.java b/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/TableColumn.java
index 5f6b0f9e1730fd56b497f22514ef734f5a77c876..f42f28c3277735541b8184d8ceb93cef10eefde9 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/TableColumn.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/TableColumn.java
@@ -52,6 +52,10 @@ public class TableColumn extends BaseEntity {
   @JdbcType(PostgreSQLEnumJdbcType.class)
   private TableColumnValueType valueType;
 
+  @Column
+  @JdbcType(PostgreSQLEnumJdbcType.class)
+  private TableColumnDataPrivacyCategory dataPrivacyCategory;
+
   @Column private String unit;
 
   @OneToMany(
@@ -141,6 +145,14 @@ public class TableColumn extends BaseEntity {
     this.valueType = valueType;
   }
 
+  public TableColumnDataPrivacyCategory getDataPrivacyCategory() {
+    return dataPrivacyCategory;
+  }
+
+  public void setDataPrivacyCategory(TableColumnDataPrivacyCategory dataPrivacyCategory) {
+    this.dataPrivacyCategory = dataPrivacyCategory;
+  }
+
   public String getUnit() {
     return unit;
   }
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/TableColumnDataPrivacyCategory.java b/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/TableColumnDataPrivacyCategory.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe1115a31ff61c1638190dbfa4e61e5b7caa8c34
--- /dev/null
+++ b/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/TableColumnDataPrivacyCategory.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.statistics.persistence.entity;
+
+public enum TableColumnDataPrivacyCategory {
+  QUASI_IDENTIFYING,
+  SENSITIVE,
+  INSENSITIVE
+}
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/chart/HistogramChartConfiguration.java b/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/chart/HistogramChartConfiguration.java
index afb249046c99c0216c127ca68f3e07750db30bd0..168ea620ec0a7eb29b2597ebb6513dd370364952 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/chart/HistogramChartConfiguration.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/persistence/entity/chart/HistogramChartConfiguration.java
@@ -19,6 +19,7 @@ import jakarta.persistence.OneToMany;
 import jakarta.persistence.OneToOne;
 import jakarta.persistence.OrderColumn;
 import jakarta.validation.constraints.Min;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 import org.hibernate.annotations.JdbcType;
@@ -55,6 +56,12 @@ public class HistogramChartConfiguration extends ChartConfiguration
   @Column
   private Integer numberOfBins;
 
+  @Column(precision = 10, scale = 4)
+  private BigDecimal minBin;
+
+  @Column(precision = 10, scale = 4)
+  private BigDecimal maxBin;
+
   @OneToMany(
       cascade = CascadeType.PERSIST,
       fetch = FetchType.LAZY,
@@ -124,4 +131,20 @@ public class HistogramChartConfiguration extends ChartConfiguration
     this.bins.forEach(bin -> bin.setHistogramChartConfiguration(null));
     this.bins.clear();
   }
+
+  public BigDecimal getMinBin() {
+    return minBin;
+  }
+
+  public void setMinBin(BigDecimal minBin) {
+    this.minBin = minBin;
+  }
+
+  public BigDecimal getMaxBin() {
+    return maxBin;
+  }
+
+  public void setMaxBin(BigDecimal maxBin) {
+    this.maxBin = maxBin;
+  }
 }
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/testhelper/StatisticsPopulator.java b/backend/statistics/src/main/java/de/eshg/statistics/testhelper/StatisticsPopulator.java
index 2afda541974d2dfaa1a65f459b1023e083de33dc..99d3ea083d203c56573d775524e4bd126509f433 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/testhelper/StatisticsPopulator.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/testhelper/StatisticsPopulator.java
@@ -473,14 +473,18 @@ public class StatisticsPopulator {
     ScalingDto scaling = null;
     GroupingDto grouping = null;
     BinningModeDto binning = BinningModeDto.AUTO;
-    Integer numberBins = null;
+    Integer numberOfBins = null;
+    BigDecimal minBin = null;
+    BigDecimal maxBin = null;
     if (secondAttribute != null) {
       name = "histo with second";
       secondDto = getAttributeSelectionDto(secondAttribute, businessModule, dataSourceId);
       scaling = ScalingDto.RELATIVE;
       grouping = GroupingDto.STACKED;
       binning = BinningModeDto.MANUAL;
-      numberBins = 4;
+      numberOfBins = 4;
+      minBin = BigDecimal.ONE;
+      maxBin = BigDecimal.TEN;
     }
     AnalysisDto analysisDto =
         analysisController.addAnalysis(
@@ -493,7 +497,9 @@ public class StatisticsPopulator {
                     scaling,
                     grouping,
                     binning,
-                    numberBins)));
+                    numberOfBins,
+                    minBin,
+                    maxBin)));
     addDiagramWithoutFilters(analysisDto);
   }
 
diff --git a/backend/statistics/src/main/java/de/eshg/statistics/testhelper/StatisticsTestHelperController.java b/backend/statistics/src/main/java/de/eshg/statistics/testhelper/StatisticsTestHelperController.java
index 47f8deee61c1223ce9e39965d3a50bdc3722d11b..33551dbbf9a052369a34fedcd215ec615e412bb7 100644
--- a/backend/statistics/src/main/java/de/eshg/statistics/testhelper/StatisticsTestHelperController.java
+++ b/backend/statistics/src/main/java/de/eshg/statistics/testhelper/StatisticsTestHelperController.java
@@ -5,7 +5,7 @@
 
 package de.eshg.statistics.testhelper;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.lib.auditlog.AuditLogTestHelperService;
 import de.eshg.rest.service.error.BadRequestException;
 import de.eshg.statistics.aggregation.ReportExecution;
@@ -16,7 +16,6 @@ import de.eshg.testhelper.ConditionalOnTestHelperEnabled;
 import de.eshg.testhelper.DefaultTestHelperService;
 import de.eshg.testhelper.TestHelperController;
 import de.eshg.testhelper.environment.EnvironmentConfig;
-import java.io.IOException;
 import java.util.UUID;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RestController;
@@ -25,7 +24,7 @@ import org.springframework.web.service.annotation.PostExchange;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class StatisticsTestHelperController extends TestHelperController
-    implements SharedAuditLogTestHelperApi {
+    implements AuditLogClientTestHelperApi {
 
   private final StatisticsFeatureToggle statisticsFeatureToggle;
   private final AuditLogTestHelperService auditLogTestHelperService;
@@ -59,11 +58,6 @@ public class StatisticsTestHelperController extends TestHelperController
     statisticsExecutorService.submit(reportExecution::handlePlannedReportsInternal);
   }
 
-  @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
-  }
-
   @PostExchange("/populate-create-evaluation/{businessModuleName}/{anonymized}")
   public UUID createEvaluation(
       @PathVariable("businessModuleName") String businessModuleName,
@@ -81,7 +75,7 @@ public class StatisticsTestHelperController extends TestHelperController
   }
 
   @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 }
diff --git a/backend/statistics/src/main/resources/migrations/0044_add_auditlog_entry.xml b/backend/statistics/src/main/resources/migrations/0044_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..28652f29b57ec0315a42976d18deee225ec7f99e
--- /dev/null
+++ b/backend/statistics/src/main/resources/migrations/0044_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/statistics/src/main/resources/migrations/0045_data_privacy_category.xml b/backend/statistics/src/main/resources/migrations/0045_data_privacy_category.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a59aa1ebe464e57683324d98693cd01ea470dc2c
--- /dev/null
+++ b/backend/statistics/src/main/resources/migrations/0045_data_privacy_category.xml
@@ -0,0 +1,16 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737990141304-1">
+    <ext:createPostgresEnumType name="tablecolumndataprivacycategory" values="INSENSITIVE, QUASI_IDENTIFYING, SENSITIVE"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737990141304-2">
+    <addColumn tableName="table_column">
+      <column name="data_privacy_category" type="TABLECOLUMNDATAPRIVACYCATEGORY"/>
+    </addColumn>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/statistics/src/main/resources/migrations/0046_add_minBin_and_maxBin.xml b/backend/statistics/src/main/resources/migrations/0046_add_minBin_and_maxBin.xml
new file mode 100644
index 0000000000000000000000000000000000000000..73434af86fe5c8cbda2039ec29bff5694a46de66
--- /dev/null
+++ b/backend/statistics/src/main/resources/migrations/0046_add_minBin_and_maxBin.xml
@@ -0,0 +1,16 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737531968510-1">
+      <addColumn tableName="histogram_chart_configuration">
+          <column name="max_bin" type="numeric(10, 4)"/>
+      </addColumn>
+      <addColumn tableName="histogram_chart_configuration">
+          <column name="min_bin" type="numeric(10, 4)"/>
+      </addColumn>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/statistics/src/main/resources/migrations/0047_migrate_minBin_and_maxBin.xml b/backend/statistics/src/main/resources/migrations/0047_migrate_minBin_and_maxBin.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0bc469ad706871cc52e7d9caf62402c081e57397
--- /dev/null
+++ b/backend/statistics/src/main/resources/migrations/0047_migrate_minBin_and_maxBin.xml
@@ -0,0 +1,30 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="173753321568510-1">
+    <sql>
+      UPDATE histogram_chart_configuration hc
+      SET min_bin = (
+        SELECT (hb.lower_bound + hb.upper_bound) / 2
+        FROM histogram_bin hb
+      WHERE hb.histogram_chart_configuration_id = hc.id
+        ORDER BY hb.lower_bound ASC
+        LIMIT 1
+        )
+      WHERE hc.binning_mode = 'MANUAL';
+      UPDATE histogram_chart_configuration hc
+      SET max_bin = (
+        SELECT (hb.lower_bound + hb.upper_bound) / 2
+        FROM histogram_bin hb
+        WHERE hb.histogram_chart_configuration_id = hc.id
+        ORDER BY hb.upper_bound DESC
+        LIMIT 1
+        )
+      WHERE hc.binning_mode = 'MANUAL';
+    </sql>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/statistics/src/main/resources/migrations/changelog.xml b/backend/statistics/src/main/resources/migrations/changelog.xml
index 648cc146f64e5794364f6858672f120ed10ff066..f2e873a689d583487335fd889b5c9bb5e129f841 100644
--- a/backend/statistics/src/main/resources/migrations/changelog.xml
+++ b/backend/statistics/src/main/resources/migrations/changelog.xml
@@ -51,4 +51,8 @@
     <include file="migrations/0041_introduce_table_column_value_type.xml"/>
     <include file="migrations/0042_store_procedure_references_instead_of_ids.xml"/>
     <include file="migrations/0043_remove_linechart_column.xml"/>
+    <include file="migrations/0044_add_auditlog_entry.xml"/>
+    <include file="migrations/0045_data_privacy_category.xml"/>
+    <include file="migrations/0046_add_minBin_and_maxBin.xml"/>
+    <include file="migrations/0047_migrate_minBin_and_maxBin.xml"/>
 </databaseChangeLog>
diff --git a/backend/sti-protection/build.gradle b/backend/sti-protection/build.gradle
index 99c14d3048f91bcd7c3d733afddc2888c2856a32..e167fba5fd4fd716f32fdb0fd78557ac17ce70ce 100644
--- a/backend/sti-protection/build.gradle
+++ b/backend/sti-protection/build.gradle
@@ -22,6 +22,7 @@ dependencies {
     testImplementation testFixtures(project(':business-module-persistence-commons'))
     testImplementation testFixtures(project(':lib-document-generator'))
     testImplementation testFixtures(project(':lib-procedures'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 }
 
 dockerCompose {
diff --git a/backend/sti-protection/gradle.lockfile b/backend/sti-protection/gradle.lockfile
index 3dba2bc986ef823ecfc2b041522b20c2a428a41b..024a5d5b0cd25c98b0905c13b73aaaa864416d3b 100644
--- a/backend/sti-protection/gradle.lockfile
+++ b/backend/sti-protection/gradle.lockfile
@@ -72,10 +72,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -164,10 +164,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -186,16 +186,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/sti-protection/openApi.json b/backend/sti-protection/openApi.json
index 7709d6c8d4220122bbf336a20ee834adea319c83..969c0858e16d4acec206b75b14d1f8c9dd3c3153 100644
--- a/backend/sti-protection/openApi.json
+++ b/backend/sti-protection/openApi.json
@@ -549,6 +549,95 @@
         "tags" : [ "Archiving" ]
       }
     },
+    "/citizen/public/department-info" : {
+      "get" : {
+        "operationId" : "getDepartmentInfo",
+        "parameters" : [ {
+          "in" : "query",
+          "name" : "request",
+          "required" : true,
+          "schema" : {
+            "$ref" : "#/components/schemas/GetDepartmentInfoRequest"
+          }
+        } ],
+        "responses" : {
+          "200" : {
+            "content" : {
+              "*/*" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/GetDepartmentInfoResponse"
+                }
+              }
+            },
+            "description" : "OK"
+          }
+        },
+        "summary" : "Get department info",
+        "tags" : [ "StiProtectionCitizen" ]
+      }
+    },
+    "/citizen/public/free-appointments" : {
+      "get" : {
+        "operationId" : "getFreeAppointmentsForCitizen",
+        "parameters" : [ {
+          "in" : "query",
+          "name" : "appointmentType",
+          "required" : true,
+          "schema" : {
+            "$ref" : "#/components/schemas/StiAppointmentType"
+          }
+        }, {
+          "in" : "query",
+          "name" : "earliestDate",
+          "required" : false,
+          "schema" : {
+            "type" : "string",
+            "format" : "date-time"
+          }
+        } ],
+        "responses" : {
+          "200" : {
+            "content" : {
+              "*/*" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/GetFreeAppointmentsResponse"
+                }
+              }
+            },
+            "description" : "OK"
+          }
+        },
+        "summary" : "Get free appointments for an appointment type.",
+        "tags" : [ "StiProtectionCitizen" ]
+      }
+    },
+    "/citizen/public/opening-hours" : {
+      "get" : {
+        "operationId" : "getOpeningHours",
+        "parameters" : [ {
+          "in" : "query",
+          "name" : "request",
+          "required" : true,
+          "schema" : {
+            "$ref" : "#/components/schemas/GetOpeningHoursRequest"
+          }
+        } ],
+        "responses" : {
+          "200" : {
+            "content" : {
+              "*/*" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/GetOpeningHoursResponse"
+                }
+              }
+            },
+            "description" : "OK"
+          }
+        },
+        "summary" : "Get opening hours",
+        "tags" : [ "StiProtectionCitizen" ]
+      }
+    },
     "/files/{fileId}" : {
       "delete" : {
         "operationId" : "deleteFile",
@@ -2089,6 +2178,7 @@
             "description" : "OK"
           }
         },
+        "summary" : "Create a new STI procedure.",
         "tags" : [ "StiProtectionProcedure" ]
       }
     },
@@ -2570,6 +2660,7 @@
             "description" : "OK"
           }
         },
+        "summary" : "Create an STI follow-up procedure.",
         "tags" : [ "StiProtectionProcedure" ]
       }
     },
@@ -3234,18 +3325,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
-        "responses" : {
-          "200" : {
-            "description" : "OK"
-          }
-        },
-        "tags" : [ "TestHelper" ]
-      }
-    },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -3311,6 +3391,34 @@
         "tags" : [ "TestHelper" ]
       }
     },
+    "/test-helper/population/text-templates" : {
+      "post" : {
+        "operationId" : "populateTextTemplates",
+        "requestBody" : {
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/TextTemplatePopulationRequest"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "content" : {
+              "*/*" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/TextTemplatePopulationResponse"
+                }
+              }
+            },
+            "description" : "OK"
+          }
+        },
+        "tags" : [ "TestHelper" ]
+      }
+    },
     "/test-helper/request-interceptor" : {
       "post" : {
         "operationId" : "interceptNextRequest",
@@ -3655,9 +3763,9 @@
             "format" : "uuid"
           },
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
@@ -4313,13 +4421,17 @@
         "type" : "object",
         "properties" : {
           "content" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Predefined text that will be inserted.",
+            "example" : "Complete hepatitis A serology (acute vs. immunity)"
           },
           "context" : {
             "$ref" : "#/components/schemas/TextTemplateContext"
           },
           "name" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Display name of the text template.",
+            "example" : "Hepatitis Panel"
           }
         }
       },
@@ -4414,31 +4526,41 @@
         "properties" : {
           "findings" : {
             "type" : "array",
+            "description" : "Records diagnostic findings using ICD-10 codes.",
             "items" : {
               "$ref" : "#/components/schemas/Icd10Code"
             }
           },
           "generalRemarks" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Additional remarks or observations documented during the diagnosis phase.",
+            "example" : "Positive for HIV antibodies and presence of P24 antigen detected."
           },
           "medications" : {
             "type" : "array",
+            "description" : "Lists prescribed medications.",
             "items" : {
               "$ref" : "#/components/schemas/Medication"
             }
           },
           "otherTestTypeName" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Provides the name of a test type not included in the predefined list.",
+            "example" : "ELISA."
           },
           "results" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Details the results of the diagnosis.",
+            "example" : "Colicky pain, acute abdomen; medication prescribed for pain management."
           },
           "resultsCommunicated" : {
-            "type" : "boolean"
+            "type" : "boolean",
+            "description" : "Indicates whether the patient has been informed of their diagnostic results and updates the laboratory status to 'CLOSE'."
           },
           "testTypes" : {
             "uniqueItems" : true,
             "type" : "array",
+            "description" : "Specifies the type of laboratory tests conducted during examination.",
             "items" : {
               "$ref" : "#/components/schemas/TestType"
             }
@@ -5013,6 +5135,71 @@
           }
         }
       },
+      "GetDepartmentInfoRequest" : {
+        "type" : "object",
+        "properties" : {
+          "concern" : {
+            "$ref" : "#/components/schemas/Concern"
+          }
+        }
+      },
+      "GetDepartmentInfoResponse" : {
+        "required" : [ "city", "country", "email", "homepage", "houseNumber", "location", "name", "phoneNumber", "postalCode", "street" ],
+        "type" : "object",
+        "properties" : {
+          "abbreviation" : {
+            "type" : "string",
+            "description" : "The abbreviation of the name of the department",
+            "example" : "LTG"
+          },
+          "city" : {
+            "type" : "string",
+            "description" : "The name of the city where the department is located",
+            "example" : "Berlin"
+          },
+          "country" : {
+            "$ref" : "#/components/schemas/CountryCode"
+          },
+          "email" : {
+            "type" : "string",
+            "description" : "The email address of the department",
+            "example" : "mail@address.de"
+          },
+          "homepage" : {
+            "type" : "string",
+            "description" : "The domain of the department's official homepage, excluding protocols",
+            "example" : "department-homepage.de"
+          },
+          "houseNumber" : {
+            "type" : "string",
+            "description" : "The house number at the department's address, including any extensions or suffixes",
+            "example" : "1b"
+          },
+          "location" : {
+            "$ref" : "#/components/schemas/Location"
+          },
+          "name" : {
+            "type" : "string",
+            "description" : "The name of the department",
+            "example" : "Gesundheitsamt Landkreis Testgebiet"
+          },
+          "phoneNumber" : {
+            "type" : "string",
+            "description" : "The primary contact telephone number for the department",
+            "example" : "+491234567890"
+          },
+          "postalCode" : {
+            "type" : "string",
+            "description" : "The postal code for the department’s address",
+            "example" : "12345"
+          },
+          "street" : {
+            "type" : "string",
+            "description" : "The street name for the department’s address, not including the house number",
+            "example" : "Beispielweg"
+          }
+        }
+      },
       "GetDetailedProcedureResponse" : {
         "required" : [ "facilities", "persons", "procedure", "tasks" ],
         "type" : "object",
@@ -5252,6 +5439,33 @@
           }
         }
       },
+      "GetOpeningHoursRequest" : {
+        "required" : [ "concern" ],
+        "type" : "object",
+        "properties" : {
+          "concern" : {
+            "$ref" : "#/components/schemas/Concern"
+          }
+        }
+      },
+      "GetOpeningHoursResponse" : {
+        "required" : [ "de", "en" ],
+        "type" : "object",
+        "properties" : {
+          "de" : {
+            "type" : "array",
+            "items" : {
+              "type" : "string"
+            }
+          },
+          "en" : {
+            "type" : "array",
+            "items" : {
+              "type" : "string"
+            }
+          }
+        }
+      },
       "GetPersonFileStateResponse" : {
         "required" : [ "dataOrigin", "dateOfBirth", "emailAddresses", "firstName", "gender", "id", "lastName", "phoneNumbers", "referenceVersion", "salutation" ],
         "type" : "object",
@@ -5582,7 +5796,7 @@
       "GetStiProtectionProceduresSortBy" : {
         "type" : "string",
         "default" : "CREATED_AT",
-        "enum" : [ "CREATED_AT", "STATUS", "CONCERN", "YEAR_OF_BIRTH", "GENDER", "LAB_STATUS" ]
+        "enum" : [ "CREATED_AT", "SAMPLE_BARCODE", "APPOINTMENT" ]
       },
       "GetStiProtectionProceduresSortOrder" : {
         "type" : "string",
@@ -5731,7 +5945,8 @@
             "description" : "ICD-10 code title",
             "example" : "Cholera"
           }
-        }
+        },
+        "description" : "Records diagnostic findings using ICD-10 codes."
       },
       "Image" : {
         "required" : [ "@type", "createdAt", "deletable", "deleted", "fileId", "fileName", "fileSizeBytes", "fileType", "locked", "modifiedAt" ],
@@ -6082,6 +6297,25 @@
           }
         }
       },
+      "Location" : {
+        "required" : [ "latitude", "longitude" ],
+        "type" : "object",
+        "properties" : {
+          "latitude" : {
+            "type" : "number",
+            "description" : "Geographic coordinate that specifies the north–south angular location of a point on the surface of the Earth.",
+            "format" : "double",
+            "example" : 52.51627
+          },
+          "longitude" : {
+            "type" : "number",
+            "description" : "Geographic coordinate that specifies the east–west angular position of a point on the surface of the Earth.",
+            "format" : "double",
+            "example" : 13.377703
+          }
+        },
+        "description" : "Location defined by latitude and longitude."
+      },
       "Mail" : {
         "required" : [ "@type", "createdAt", "deletable", "deleted", "fileId", "fileName", "fileSizeBytes", "fileType", "locked", "modifiedAt", "removedInvalidAttachments" ],
         "type" : "object",
@@ -6216,16 +6450,23 @@
         "type" : "object",
         "properties" : {
           "dose" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Prescribed dosage of the medication.",
+            "example" : "300 mg once daily."
           },
           "name" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Name of the prescribed medication.",
+            "example" : "Tenofovir."
           },
           "prescriptionDate" : {
             "type" : "string",
-            "format" : "date"
+            "description" : "Date the medication was prescribed.",
+            "format" : "date",
+            "example" : "2025-01-16"
           }
-        }
+        },
+        "description" : "Lists prescribed medications."
       },
       "MetaData" : {
         "required" : [ "@type" ],
@@ -7021,6 +7262,10 @@
         "type" : "string",
         "enum" : [ "ASC", "DESC" ]
       },
+      "StiAppointmentType" : {
+        "type" : "string",
+        "enum" : [ "HIV_STI_CONSULTATION", "SEX_WORK" ]
+      },
       "StiConsultationMedicalHistory" : {
         "type" : "object",
         "allOf" : [ {
@@ -7101,6 +7346,9 @@
           "person" : {
             "$ref" : "#/components/schemas/Person"
           },
+          "sampleBarCode" : {
+            "type" : "string"
+          },
           "status" : {
             "$ref" : "#/components/schemas/ProcedureStatus"
           },
@@ -7110,7 +7358,7 @@
         }
       },
       "StiProtectionProcedureOverview" : {
-        "required" : [ "accessCode", "concern", "createdAt", "gender", "id", "labStatus", "status", "yearOfBirth" ],
+        "required" : [ "concern", "createdAt", "gender", "id", "labStatus", "status", "yearOfBirth" ],
         "type" : "object",
         "properties" : {
           "accessCode" : {
@@ -7119,6 +7367,10 @@
           "appointment" : {
             "$ref" : "#/components/schemas/Appointment"
           },
+          "appointmentStart" : {
+            "type" : "string",
+            "format" : "date-time"
+          },
           "concern" : {
             "$ref" : "#/components/schemas/Concern"
           },
@@ -7139,6 +7391,9 @@
           "labStatus" : {
             "$ref" : "#/components/schemas/LabStatus"
           },
+          "sampleBarCode" : {
+            "type" : "string"
+          },
           "status" : {
             "$ref" : "#/components/schemas/ProcedureStatus"
           },
@@ -7394,6 +7649,7 @@
       },
       "TestType" : {
         "type" : "string",
+        "description" : "Specifies the type of laboratory tests conducted during examination.",
         "enum" : [ "WESTERN_BLOT", "P24", "PCR", "OTHER" ]
       },
       "TextTemplate" : {
@@ -7401,24 +7657,58 @@
         "type" : "object",
         "properties" : {
           "content" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Predefined text that will be inserted.",
+            "example" : "Complete hepatitis A serology (acute vs. immunity)"
           },
           "context" : {
             "$ref" : "#/components/schemas/TextTemplateContext"
           },
           "externalId" : {
             "type" : "string",
-            "format" : "uuid"
+            "description" : "Unique identifier for referencing the text template.",
+            "format" : "uuid",
+            "example" : "UUID_4"
           },
           "name" : {
-            "type" : "string"
+            "type" : "string",
+            "description" : "Display name of the text template.",
+            "example" : "Hepatitis Panel"
           }
         }
       },
       "TextTemplateContext" : {
         "type" : "string",
+        "description" : "Category where the template is applicable.",
+        "example" : "DIAGNOSIS_RESULT",
         "enum" : [ "CONSULTATION_REASON", "CONSULTATION_REMARK", "RAPID_TESTS_REMARK", "LABORATORY_TESTS_REMARK", "DIAGNOSIS_RESULT", "DIAGNOSIS_REMARK" ]
       },
+      "TextTemplatePopulationRequest" : {
+        "required" : [ "numberOfEntitiesToPopulate" ],
+        "type" : "object",
+        "properties" : {
+          "numberOfEntitiesToPopulate" : {
+            "type" : "integer",
+            "format" : "int32"
+          }
+        }
+      },
+      "TextTemplatePopulationResponse" : {
+        "required" : [ "count" ],
+        "type" : "object",
+        "properties" : {
+          "count" : {
+            "type" : "integer",
+            "format" : "int64"
+          },
+          "textTemplates" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/components/schemas/TextTemplate"
+            }
+          }
+        }
+      },
       "Title" : {
         "type" : "string",
         "enum" : [ "DR", "PROF", "PROF_DR" ]
@@ -7449,9 +7739,9 @@
         "type" : "object",
         "properties" : {
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
@@ -7513,7 +7803,7 @@
             "type" : "string",
             "description" : "The Id of the user.",
             "format" : "uuid",
-            "example" : "UUID_4"
+            "example" : "UUID_5"
           },
           "username" : {
             "type" : "string",
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/DepartmentInfoService.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/DepartmentInfoService.java
new file mode 100644
index 0000000000000000000000000000000000000000..b539384670a72801e3a135f4adfaa80242fcf499
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/DepartmentInfoService.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection;
+
+import de.eshg.base.department.GetDepartmentInfoResponse;
+import de.eshg.base.department.LocationDto;
+import de.eshg.lib.document.generator.department.DepartmentClient;
+import de.eshg.stiprotection.api.citizen.GetOpeningHoursResponse;
+import de.eshg.stiprotection.persistence.config.DepartmentInfoConfig;
+import de.eshg.stiprotection.persistence.config.DepartmentInfoProperties;
+import de.eshg.stiprotection.persistence.config.OpeningHoursProperties;
+import de.eshg.stiprotection.persistence.db.Concern;
+import java.util.Map;
+import java.util.Optional;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+@Service
+public class DepartmentInfoService {
+
+  private final DepartmentClient departmentClient;
+  private final DepartmentInfoConfig departmentInfoConfig;
+
+  public DepartmentInfoService(
+      DepartmentClient departmentClient, DepartmentInfoConfig departmentInfoConfig) {
+    this.departmentClient = departmentClient;
+    this.departmentInfoConfig = departmentInfoConfig;
+  }
+
+  public GetDepartmentInfoResponse getDepartmentInfo(Concern concern) {
+    GetDepartmentInfoResponse baseDepartmentInfo = departmentClient.getDepartmentInfo();
+    if (concern == null) {
+      return baseDepartmentInfo;
+    }
+    String key =
+        mapConcernToKey(concern, departmentInfoConfig.getDepartmentInfo(), "DepartmentInfo");
+    Map<String, DepartmentInfoProperties> departments = departmentInfoConfig.getDepartmentInfo();
+    DepartmentInfoProperties departmentInfo = departments.get(key);
+    return mergeWithDepartmentFallback(departmentInfo, baseDepartmentInfo);
+  }
+
+  private String mapConcernToKey(Concern concern, Map<String, ?> map, String mapName) {
+    if (CollectionUtils.isEmpty(map)) {
+      throw new IllegalStateException("%s map is empty.".formatted(mapName));
+    }
+    String key = concern.name().toLowerCase();
+    if (!map.containsKey(key)) {
+      throw new IllegalStateException("%s map does not contain key %s.".formatted(mapName, key));
+    }
+    return key;
+  }
+
+  private GetDepartmentInfoResponse mergeWithDepartmentFallback(
+      DepartmentInfoProperties departmentInfo, GetDepartmentInfoResponse fallback) {
+
+    Double latitude =
+        Optional.ofNullable(departmentInfo.latitude())
+            .orElseGet(() -> fallback.location().latitude());
+    Double longitude =
+        Optional.ofNullable(departmentInfo.longitude())
+            .orElseGet(() -> fallback.location().longitude());
+
+    return new GetDepartmentInfoResponse(
+        Optional.ofNullable(departmentInfo.name()).orElseGet(fallback::name),
+        Optional.ofNullable(departmentInfo.abbreviation()).orElseGet(fallback::abbreviation),
+        Optional.ofNullable(departmentInfo.street()).orElseGet(fallback::street),
+        Optional.ofNullable(departmentInfo.houseNumber()).orElseGet(fallback::houseNumber),
+        Optional.ofNullable(departmentInfo.postalCode()).orElseGet(fallback::postalCode),
+        Optional.ofNullable(departmentInfo.city()).orElseGet(fallback::city),
+        Optional.ofNullable(departmentInfo.country()).orElseGet(fallback::country),
+        Optional.ofNullable(departmentInfo.phoneNumber()).orElseGet(fallback::phoneNumber),
+        Optional.ofNullable(departmentInfo.homepage()).orElseGet(fallback::homepage),
+        Optional.ofNullable(departmentInfo.email()).orElseGet(fallback::email),
+        new LocationDto(latitude, longitude));
+  }
+
+  public GetOpeningHoursResponse getOpeningHours(Concern concern) {
+    String key = mapConcernToKey(concern, departmentInfoConfig.getOpeningHours(), "OpeningHours");
+    Map<String, OpeningHoursProperties> departments = departmentInfoConfig.getOpeningHours();
+    OpeningHoursProperties openingHours = departments.get(key);
+    return new GetOpeningHoursResponse(openingHours.de(), openingHours.en());
+  }
+}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/FollowUpProcedureService.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/FollowUpProcedureService.java
index ad0dabcf960543e0ad150525ad6cc746f89a06be..8c2d7964100542a8342bdc910aa41bc55e4db548 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/FollowUpProcedureService.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/FollowUpProcedureService.java
@@ -16,6 +16,7 @@ import de.eshg.stiprotection.persistence.db.examination.LaboratoryTestSamplesDat
 import de.eshg.stiprotection.persistence.db.medicalhistory.Examination;
 import de.eshg.stiprotection.persistence.db.medicalhistory.MedicalHistory;
 import de.eshg.stiprotection.persistence.db.medicalhistory.SexWorkMedicalHistory;
+import java.util.List;
 import org.springframework.stereotype.Service;
 
 @Service
@@ -44,12 +45,23 @@ public class FollowUpProcedureService {
 
   private void transferDiagnosisData(
       StiProtectionProcedure procedure, StiProtectionProcedure followUpProcedure) {
+    Diagnosis previousDiagnosis = procedure.getDiagnosis();
+
     Diagnosis followUpDiagnosis =
-        DiagnosisMapper.toDatabaseType(DiagnosisMapper.toInterfaceType(procedure.getDiagnosis()));
+        DiagnosisMapper.toDatabaseType(
+            DiagnosisMapper.toInterfaceType(previousDiagnosis, List.of()));
+    followUpDiagnosis.setIcd10Codes(copyICD10Codes(previousDiagnosis));
     followUpDiagnosis.setResultsCommunicated(false);
     followUpProcedure.setDiagnosis(followUpDiagnosis);
   }
 
+  private static List<String> copyICD10Codes(Diagnosis previousDiagnosis) {
+    if (previousDiagnosis == null) {
+      return List.of();
+    }
+    return List.copyOf(previousDiagnosis.getIcd10Codes());
+  }
+
   private void transferMedicalHistoryData(
       StiProtectionProcedure procedure, StiProtectionProcedure followUpProcedure) {
     MedicalHistory medicalHistory = procedure.getMedicalHistory();
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionApplication.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionApplication.java
index 8abb000d46a212311b05c3d55dc42e277648f10e..341cedaebcb8542c1ce9618a78250aa8ff90e14a 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionApplication.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionApplication.java
@@ -7,15 +7,18 @@ package de.eshg.stiprotection;
 
 import de.eshg.lib.common.BusinessModule;
 import de.eshg.rest.service.security.config.StiProtectionPublicSecurityConfig;
+import de.eshg.stiprotection.persistence.config.DepartmentInfoConfig;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Import;
 
 @SpringBootApplication
 @Import(StiProtectionPublicSecurityConfig.class)
 @EntityScan("de.eshg")
+@EnableConfigurationProperties(DepartmentInfoConfig.class)
 public class StiProtectionApplication {
 
   @Bean
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionCitizenController.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionCitizenController.java
new file mode 100644
index 0000000000000000000000000000000000000000..884548a77f827df639b334fc54e810a479b804df
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionCitizenController.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection;
+
+import de.eshg.base.department.GetDepartmentInfoResponse;
+import de.eshg.lib.appointmentblock.AppointmentBlockService;
+import de.eshg.lib.appointmentblock.MappingUtil;
+import de.eshg.lib.appointmentblock.api.AppointmentDto;
+import de.eshg.lib.appointmentblock.api.GetFreeAppointmentsResponse;
+import de.eshg.lib.appointmentblock.persistence.AppointmentType;
+import de.eshg.rest.service.security.config.BaseUrls;
+import de.eshg.stiprotection.api.citizen.GetDepartmentInfoRequest;
+import de.eshg.stiprotection.api.citizen.GetOpeningHoursRequest;
+import de.eshg.stiprotection.api.citizen.GetOpeningHoursResponse;
+import de.eshg.stiprotection.api.citizen.StiAppointmentTypeDto;
+import de.eshg.stiprotection.mapper.ConcernMapper;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import java.time.Clock;
+import java.time.Instant;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(path = StiProtectionCitizenController.BASE_URL)
+@Tag(name = "StiProtectionCitizen")
+public class StiProtectionCitizenController {
+
+  private static final Logger log = LoggerFactory.getLogger(StiProtectionCitizenController.class);
+
+  public static final String BASE_URL = BaseUrls.StiProtection.CITIZEN_PUBLIC_CONTROLLER;
+
+  private final DepartmentInfoService departmentInfoService;
+  private final AppointmentBlockService appointmentBlockService;
+  private final Clock clock;
+
+  public StiProtectionCitizenController(
+      DepartmentInfoService departmentInfoService,
+      AppointmentBlockService appointmentBlockService,
+      Clock clock) {
+    this.departmentInfoService = departmentInfoService;
+    this.appointmentBlockService = appointmentBlockService;
+    this.clock = clock;
+  }
+
+  @GetMapping("/department-info")
+  @Operation(summary = "Get department info")
+  @Transactional(readOnly = true)
+  public GetDepartmentInfoResponse getDepartmentInfo(
+      @Valid @RequestBody GetDepartmentInfoRequest request) {
+    return departmentInfoService.getDepartmentInfo(ConcernMapper.toDatabaseType(request.concern()));
+  }
+
+  @GetMapping("/opening-hours")
+  @Operation(summary = "Get opening hours")
+  @Transactional(readOnly = true)
+  public GetOpeningHoursResponse getOpeningHours(
+      @Valid @RequestBody GetOpeningHoursRequest request) {
+    return departmentInfoService.getOpeningHours(ConcernMapper.toDatabaseType(request.concern()));
+  }
+
+  @Operation(summary = "Get free appointments for an appointment type.")
+  @GetMapping("/free-appointments")
+  @Transactional(readOnly = true)
+  public GetFreeAppointmentsResponse getFreeAppointmentsForCitizen(
+      @RequestParam(name = "appointmentType") @NotNull StiAppointmentTypeDto appointmentType,
+      @RequestParam(name = "earliestDate", required = false) Instant earliestDate) {
+
+    if (earliestDate != null && earliestDate.isBefore(Instant.now(clock))) {
+      log.warn("Received earliestDate {} is in the past. Adjusting to current time.", earliestDate);
+      earliestDate = Instant.now(clock);
+    }
+
+    List<AppointmentDto> appointments =
+        appointmentBlockService.getFreeAppointments(
+            earliestDate,
+            null,
+            MappingUtil.mapEnum(AppointmentType.class, appointmentType),
+            null,
+            null);
+
+    return new GetFreeAppointmentsResponse(appointments);
+  }
+}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureController.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureController.java
index 72d1016e617921c89255739eb493af2671f1baf1..dacd0740614a443aff49db4bcd43448a4b79779e 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureController.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureController.java
@@ -94,6 +94,7 @@ public class StiProtectionProcedureController {
   }
 
   @PostMapping
+  @Operation(summary = "Create a new STI procedure.")
   @Transactional
   public CreateProcedureResponse createProcedure(
       @Valid @RequestBody CreateProcedureRequest request) {
@@ -108,7 +109,7 @@ public class StiProtectionProcedureController {
 
   @GetMapping("/{id}")
   @Operation(summary = "Get STI protection procedure by id.")
-  @Transactional(readOnly = true)
+  @Transactional
   public GetProcedureResponse getStiProcedure(@PathVariable("id") UUID procedureId) {
     auditLogger.log(
         "Vorgangsbearbeitung",
@@ -250,13 +251,13 @@ public class StiProtectionProcedureController {
   }
 
   @PostMapping("/{id}/follow-up")
+  @Operation(summary = "Create an STI follow-up procedure.")
   @Transactional
   @ProcedureStatusTransition
   public CreateFollowUpProcedureResponse createFollowUpProcedure(
       @PathVariable("id") UUID procedureId,
       @Valid @RequestBody CreateFollowUpProcedureRequest request) {
     StiProtectionProcedure procedure = procedureFinder.findByExternalId(procedureId);
-    // Todo remove old access code user
     if (procedure.getProcedureStatus().isOpen()) {
       appointmentService.cancelAppointment(procedure);
       stiProtectionService.closeProcedure(procedure);
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureDeletionService.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureDeletionService.java
index a8743bcf1d39d26059d615c1064472dfceb0f491..838c23f895316eafac4349a8b30f162054445fe7 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureDeletionService.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureDeletionService.java
@@ -9,10 +9,8 @@ import de.eshg.base.centralfile.FacilityApi;
 import de.eshg.base.centralfile.PersonApi;
 import de.eshg.lib.procedure.cemetery.CemeteryService;
 import de.eshg.lib.procedure.procedures.ProcedureDeletionService;
-import de.eshg.rest.service.error.NotFoundException;
 import de.eshg.stiprotection.persistence.db.StiProtectionProcedure;
 import de.eshg.stiprotection.persistence.db.StiProtectionProcedureRepository;
-import java.util.UUID;
 import org.springframework.stereotype.Service;
 
 @Service
@@ -27,12 +25,6 @@ public class StiProtectionProcedureDeletionService
     super(stiProtectionProcedureRepository, cemeteryService, personApi, facilityApi);
   }
 
-  public StiProtectionProcedure find(UUID externalId) {
-    return procedureRepository
-        .findByExternalId(externalId)
-        .orElseThrow(() -> new NotFoundException("Procedure " + externalId + " not found."));
-  }
-
   @Override
   protected void markRelatedFileStatesForDeletion(StiProtectionProcedure procedure) {
     // do nothing
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureService.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureService.java
index 67db545418ddc48787a84233ff67ef55667901de..85c5b6ee1163649fe258b91549f6312f3f0cf4a8 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureService.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/StiProtectionProcedureService.java
@@ -46,7 +46,6 @@ import de.eshg.stiprotection.persistence.data.ResultPage;
 import de.eshg.stiprotection.persistence.data.StiProtectionProcedureData;
 import de.eshg.stiprotection.persistence.db.Concern;
 import de.eshg.stiprotection.persistence.db.Person;
-import de.eshg.stiprotection.persistence.db.Person_;
 import de.eshg.stiprotection.persistence.db.StiProtectionProcedure;
 import de.eshg.stiprotection.persistence.db.StiProtectionProcedureRepository;
 import de.eshg.stiprotection.persistence.db.StiProtectionProcedure_;
@@ -170,7 +169,7 @@ public class StiProtectionProcedureService {
       Join<StiProtectionProcedure, Person> psJoin =
           root.join(Procedure_.RELATED_PERSONS, JoinType.INNER);
 
-      Path<?> sortProperty = getSortProperty(sortBy, root, psJoin);
+      Path<?> sortProperty = getSortProperty(sortBy, root);
 
       if (sortOrder == ASC) {
         query.orderBy(criteriaBuilder.asc(sortProperty));
@@ -182,16 +181,11 @@ public class StiProtectionProcedureService {
   }
 
   private static Path<?> getSortProperty(
-      GetStiProtectionProceduresSortByDto sortBy,
-      Root<StiProtectionProcedure> root,
-      Join<StiProtectionProcedure, Person> psJoin) {
+      GetStiProtectionProceduresSortByDto sortBy, Root<StiProtectionProcedure> root) {
     return switch (sortBy) {
       case CREATED_AT -> root.get(Procedure_.createdAt);
-      case STATUS -> root.get(Procedure_.procedureStatus);
-      case CONCERN -> root.get(StiProtectionProcedure_.concern);
-      case YEAR_OF_BIRTH -> psJoin.get(Person_.yearOfBirth);
-      case GENDER -> psJoin.get(Person_.gender);
-      case LAB_STATUS -> root.get(StiProtectionProcedure_.labStatus);
+      case SAMPLE_BARCODE -> root.get(StiProtectionProcedure_.sampleBarCode);
+      case APPOINTMENT -> root.get(StiProtectionProcedure_.appointmentStart);
     };
   }
 
@@ -286,12 +280,12 @@ public class StiProtectionProcedureService {
   }
 
   public void deleteAnonymousUser(StiProtectionProcedure procedure) {
-    UUID anonymousUserId = procedure.getPerson().getAnonymousUserId();
-    if (anonymousUserId == null) {
-      throw new BadRequestException("User already deleted.");
+    Person person = procedure.getPerson();
+    UUID anonymousUserId = person.getAnonymousUserId();
+    if (anonymousUserId != null) {
+      citizenAccessCodeUserApi.deleteCitizenAccessCodeUser(anonymousUserId);
+      person.setAnonymousUserId(null);
     }
-    citizenAccessCodeUserApi.deleteCitizenAccessCodeUser(anonymousUserId);
-    procedure.getPerson().setAnonymousUserId(null);
   }
 
   public void verifyAnonymousUserPin(UUID procedureId, String pin) {
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/GetProcedureResponse.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/GetProcedureResponse.java
index 71ba4c9617c838a40db2d50ff2b68a51125a8dc9..d22cdb35283d294b830af0bb0c1ab216b1d2bb30 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/GetProcedureResponse.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/GetProcedureResponse.java
@@ -26,4 +26,5 @@ public record GetProcedureResponse(
     @Valid AppointmentDto appointment,
     @NotNull @Valid List<AppointmentHistoryEntryDto> appointmentHistory,
     @Valid WaitingRoomDto waitingRoom,
-    @NotNull LabStatusDto labStatus) {}
+    @NotNull LabStatusDto labStatus,
+    String sampleBarCode) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/GetStiProtectionProceduresSortByDto.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/GetStiProtectionProceduresSortByDto.java
index 0f259de5fc08678512c2e087d74e082a3ad69597..c7d39cbf1f113d557b6b11ef7495e44aa3d966a0 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/GetStiProtectionProceduresSortByDto.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/GetStiProtectionProceduresSortByDto.java
@@ -10,9 +10,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
 @Schema(name = "GetStiProtectionProceduresSortBy")
 public enum GetStiProtectionProceduresSortByDto {
   CREATED_AT,
-  STATUS,
-  CONCERN,
-  YEAR_OF_BIRTH,
-  GENDER,
-  LAB_STATUS
+  SAMPLE_BARCODE,
+  APPOINTMENT
 }
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/StiProtectionProcedureOverviewDto.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/StiProtectionProcedureOverviewDto.java
index 4387e67cd80c0fb5d8130d95701390ad2f6e87c4..b4aad29930f1fa84979db40395d8c650b6097b44 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/StiProtectionProcedureOverviewDto.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/StiProtectionProcedureOverviewDto.java
@@ -26,5 +26,7 @@ public record StiProtectionProcedureOverviewDto(
     CountryCode countryOfBirth,
     @NotNull GenderDto gender,
     @Valid AppointmentDto appointment,
-    @NotNull String accessCode,
-    @NotNull LabStatusDto labStatus) {}
+    String accessCode,
+    @NotNull LabStatusDto labStatus,
+    String sampleBarCode,
+    Instant appointmentStart) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/TextTemplatePopulationRequest.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/TextTemplatePopulationRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9ed8210386e08373531b2128bdda06602f33df71
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/TextTemplatePopulationRequest.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.api;
+
+import jakarta.validation.constraints.NotNull;
+
+public record TextTemplatePopulationRequest(@NotNull Integer numberOfEntitiesToPopulate) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/TextTemplatePopulationResponse.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/TextTemplatePopulationResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..62c3e70b9d1f11d3bba4c2223f0e4316e078fa05
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/TextTemplatePopulationResponse.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.api;
+
+import de.eshg.stiprotection.api.texttemplate.TextTemplateDto;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import java.util.List;
+
+public record TextTemplatePopulationResponse(
+    @Valid List<TextTemplateDto> textTemplates, @NotNull long count) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetDepartmentInfoRequest.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetDepartmentInfoRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..955279dc5f144d64fb38f313dbf32c2e7afeafdb
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetDepartmentInfoRequest.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.api.citizen;
+
+import de.eshg.stiprotection.api.ConcernDto;
+
+public record GetDepartmentInfoRequest(ConcernDto concern) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetOpeningHoursRequest.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetOpeningHoursRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3ad4a519756bd4a33d25976228eb94dd1bf08683
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetOpeningHoursRequest.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.api.citizen;
+
+import de.eshg.stiprotection.api.ConcernDto;
+import jakarta.validation.constraints.NotNull;
+
+public record GetOpeningHoursRequest(@NotNull ConcernDto concern) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetOpeningHoursResponse.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetOpeningHoursResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0b8d9ce01165b4f172f993adb5a3851fcf45177
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/GetOpeningHoursResponse.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.api.citizen;
+
+import jakarta.validation.constraints.NotNull;
+import java.util.List;
+
+public record GetOpeningHoursResponse(@NotNull List<String> de, @NotNull List<String> en) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/StiAppointmentTypeDto.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/StiAppointmentTypeDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7cd6c3da9257a4df68c653cbfa5af594e0e43c2
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/citizen/StiAppointmentTypeDto.java
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.api.citizen;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(name = "StiAppointmentType")
+public enum StiAppointmentTypeDto {
+  HIV_STI_CONSULTATION,
+  SEX_WORK
+}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/diagnosis/DiagnosisDto.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/diagnosis/DiagnosisDto.java
index 600223b73b51cf8dba3d05099ccdddf27b8eb912..cc73b85ee38472edd2964151f44ae05c68c3ec7b 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/diagnosis/DiagnosisDto.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/diagnosis/DiagnosisDto.java
@@ -17,13 +17,28 @@ import org.springframework.util.CollectionUtils;
 
 @Schema(name = "Diagnosis")
 public record DiagnosisDto(
-    String results,
-    @Valid List<MedicationDto> medications,
-    @Valid List<Icd10CodeDto> findings,
-    Set<TestTypeDto> testTypes,
-    String otherTestTypeName,
-    String generalRemarks,
-    Boolean resultsCommunicated) {
+    @Schema(
+            description = "Details the results of the diagnosis.",
+            example = "Colicky pain, acute abdomen; medication prescribed for pain management.")
+        String results,
+    @Schema(description = "Lists prescribed medications.") @Valid List<MedicationDto> medications,
+    @Schema(description = "Records diagnostic findings using ICD-10 codes.") @Valid
+        List<Icd10CodeDto> findings,
+    @Schema(description = "Specifies the type of laboratory tests conducted during examination.")
+        Set<TestTypeDto> testTypes,
+    @Schema(
+            description = "Provides the name of a test type not included in the predefined list.",
+            example = "ELISA.")
+        String otherTestTypeName,
+    @Schema(
+            description =
+                "Additional remarks or observations documented during the diagnosis phase.",
+            example = "Positive for HIV antibodies and presence of P24 antigen detected.")
+        String generalRemarks,
+    @Schema(
+            description =
+                "Indicates whether the patient has been informed of their diagnostic results and updates the laboratory status to 'CLOSE'.")
+        Boolean resultsCommunicated) {
 
   @AssertTrue(
       message =
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/diagnosis/MedicationDto.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/diagnosis/MedicationDto.java
index d30b01e9d6a3c33c6aabd71aeb8c89c0de9e2cb9..ed0b7b2b6995390c0edc78c426f06dee4dc3e1ff 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/diagnosis/MedicationDto.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/diagnosis/MedicationDto.java
@@ -12,4 +12,10 @@ import java.time.LocalDate;
 
 @Schema(name = "Medication")
 public record MedicationDto(
-    @NotBlank String name, @NotBlank String dose, @NotNull LocalDate prescriptionDate) {}
+    @Schema(description = "Name of the prescribed medication.", example = "Tenofovir.") @NotBlank
+        String name,
+    @Schema(description = "Prescribed dosage of the medication.", example = "300 mg once daily.")
+        @NotBlank
+        String dose,
+    @Schema(description = "Date the medication was prescribed.", example = "2025-01-16") @NotNull
+        LocalDate prescriptionDate) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/texttemplate/CreateTextTemplateRequest.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/texttemplate/CreateTextTemplateRequest.java
index f3fd681add208caa3cb27d63ec362965dc1c80da..6f172cdc42cbf951c7078decc7b68dfaf19bd899 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/texttemplate/CreateTextTemplateRequest.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/texttemplate/CreateTextTemplateRequest.java
@@ -5,8 +5,21 @@
 
 package de.eshg.stiprotection.api.texttemplate;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 
 public record CreateTextTemplateRequest(
-    @NotBlank String name, @NotNull TextTemplateContextDto context, @NotBlank String content) {}
+    @NotBlank
+        @Schema(description = "Display name of the text template.", example = "Hepatitis Panel")
+        String name,
+    @NotNull
+        @Schema(
+            description = "Category where the template is applicable.",
+            example = "DIAGNOSIS_RESULT")
+        TextTemplateContextDto context,
+    @NotBlank
+        @Schema(
+            description = "Predefined text that will be inserted.",
+            example = "Complete hepatitis A serology (acute vs. immunity)")
+        String content) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/texttemplate/TextTemplateDto.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/texttemplate/TextTemplateDto.java
index ce51225ca3326ddd8b9b485fcd0787a8576a0b35..b8a3dde4801c0617d50a93a6a946269a31e81a08 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/texttemplate/TextTemplateDto.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/api/texttemplate/TextTemplateDto.java
@@ -12,7 +12,21 @@ import java.util.UUID;
 
 @Schema(name = "TextTemplate")
 public record TextTemplateDto(
-    @NotNull UUID externalId,
-    @NotBlank String name,
-    @NotNull TextTemplateContextDto context,
-    @NotBlank String content) {}
+    @NotNull
+        @Schema(
+            description = "Unique identifier for referencing the text template.",
+            example = "696a337f-8cbe-47b7-ac13-2e13e574c2c5")
+        UUID externalId,
+    @NotBlank
+        @Schema(description = "Display name of the text template.", example = "Hepatitis Panel")
+        String name,
+    @NotNull
+        @Schema(
+            description = "Category where the template is applicable.",
+            example = "DIAGNOSIS_RESULT")
+        TextTemplateContextDto context,
+    @NotBlank
+        @Schema(
+            description = "Predefined text that will be inserted.",
+            example = "Complete hepatitis A serology (acute vs. immunity)")
+        String content) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/mapper/StiProtectionProcedureMapper.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/mapper/StiProtectionProcedureMapper.java
index 11196485b304bf89b37f7298ddf5bd1134599751..2759c4031cf0d3950803b33eafa501fd045c1731 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/mapper/StiProtectionProcedureMapper.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/mapper/StiProtectionProcedureMapper.java
@@ -34,7 +34,8 @@ public class StiProtectionProcedureMapper {
             procedureData.appointment(), procedureData.userDefinedAppointment()),
         AppointmentHistoryMapper.toInterfaceType(procedureData.appointmentHistory()),
         WaitingRoomMapper.toInterfaceType(procedureData.waitingRoom()),
-        LabStatusMapper.toInterfaceData(procedureData.procedure().getLabStatus()));
+        LabStatusMapper.toInterfaceData(procedureData.procedure().getLabStatus()),
+        procedureData.sampleBarCode());
   }
 
   public static StiProtectionProcedureOverviewDto toOverviewType(
@@ -50,6 +51,8 @@ public class StiProtectionProcedureMapper {
         AppointmentMapper.toInterfaceType(
             procedureData.appointment(), procedureData.userDefinedAppointment()),
         procedureData.accessCode(),
-        LabStatusMapper.toInterfaceData(procedureData.procedure().getLabStatus()));
+        LabStatusMapper.toInterfaceData(procedureData.procedure().getLabStatus()),
+        procedureData.sampleBarCode(),
+        procedureData.appointmentStart());
   }
 }
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/mapper/diagnosis/DiagnosisMapper.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/mapper/diagnosis/DiagnosisMapper.java
index ed760365d696673a78e6a0cc121111e1563bfd6d..d0a5f48bb187a84723f18ec763dc7330a15b9c15 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/mapper/diagnosis/DiagnosisMapper.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/mapper/diagnosis/DiagnosisMapper.java
@@ -30,21 +30,6 @@ public class DiagnosisMapper {
         entity.getResultsCommunicated());
   }
 
-  public static DiagnosisDto toInterfaceType(Diagnosis entity) {
-    if (entity == null) {
-      return new DiagnosisDto(null, null, null, null, null, null, false);
-    }
-
-    return new DiagnosisDto(
-        entity.getResults(),
-        MedicationMapper.toInterfaceType(entity.getMedications()),
-        null,
-        TestTypeMapper.toInterfaceType(entity.getTestTypes()),
-        entity.getOtherTestTypeName(),
-        entity.getGeneralRemarks(),
-        entity.getResultsCommunicated());
-  }
-
   public static Diagnosis toDatabaseType(DiagnosisDto dto) {
     if (dto == null) {
       return null;
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/DepartmentInfoConfig.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/DepartmentInfoConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0da16ff57fbc8f58a8140eb02af461fab776725
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/DepartmentInfoConfig.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.persistence.config;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties(prefix = "de.eshg.sti-protection")
+public class DepartmentInfoConfig {
+
+  private final Map<String, DepartmentInfoProperties> departmentInfo = new HashMap<>();
+  private final Map<String, OpeningHoursProperties> openingHours = new HashMap<>();
+
+  public Map<String, DepartmentInfoProperties> getDepartmentInfo() {
+    return departmentInfo;
+  }
+
+  public Map<String, OpeningHoursProperties> getOpeningHours() {
+    return openingHours;
+  }
+}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/DepartmentInfoProperties.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/DepartmentInfoProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..59c2ba9cc4d7aa32fabc083ebf4a077a3f4c3dc9
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/DepartmentInfoProperties.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.persistence.config;
+
+import de.eshg.lib.common.CountryCode;
+
+public record DepartmentInfoProperties(
+    String name,
+    String abbreviation,
+    String street,
+    String houseNumber,
+    String postalCode,
+    String city,
+    CountryCode country,
+    String phoneNumber,
+    String homepage,
+    String email,
+    Double latitude,
+    Double longitude) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/OpeningHoursProperties.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/OpeningHoursProperties.java
new file mode 100644
index 0000000000000000000000000000000000000000..5dd2bf1bb1d94b99cf8b6962fa4e8d67f629f093
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/config/OpeningHoursProperties.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.persistence.config;
+
+import java.util.List;
+
+public record OpeningHoursProperties(List<String> de, List<String> en) {}
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/data/StiProtectionProcedureData.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/data/StiProtectionProcedureData.java
index c0af713abb505af079f4c27cc833831ad9040c0d..241e07493d2cba4832e40f0f5479c0b08fa7449c 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/data/StiProtectionProcedureData.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/data/StiProtectionProcedureData.java
@@ -57,4 +57,12 @@ public record StiProtectionProcedureData(StiProtectionProcedure procedure, Strin
   public WaitingRoom waitingRoom() {
     return procedure.getWaitingRoom();
   }
+
+  public String sampleBarCode() {
+    return procedure.getSampleBarCode();
+  }
+
+  public Instant appointmentStart() {
+    return procedure.getAppointmentStart();
+  }
 }
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/db/StiProtectionProcedure.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/db/StiProtectionProcedure.java
index 7f15f64f2762cb87faa3a0e0b87b7b9f5002a2eb..df22cc43473cbd1ef8d9779068b82db33a8edcbd 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/db/StiProtectionProcedure.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/persistence/db/StiProtectionProcedure.java
@@ -29,12 +29,15 @@ import jakarta.persistence.Column;
 import jakarta.persistence.ElementCollection;
 import jakarta.persistence.Entity;
 import jakarta.persistence.FetchType;
+import jakarta.persistence.Index;
 import jakarta.persistence.JoinColumn;
 import jakarta.persistence.OneToOne;
 import jakarta.persistence.OrderColumn;
 import jakarta.persistence.PrePersist;
 import jakarta.persistence.PreUpdate;
+import jakarta.persistence.Table;
 import jakarta.persistence.Transient;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -44,6 +47,13 @@ import org.hibernate.dialect.PostgreSQLEnumJdbcType;
 import org.springframework.util.Assert;
 
 @Entity
+@Table(
+    indexes = {
+      @Index(name = "idx_sti_protection_procedure_sample_bar_code", columnList = "sample_bar_code"),
+      @Index(
+          name = "idx_sti_protection_procedure_appointment_start",
+          columnList = "appointment_start"),
+    })
 public class StiProtectionProcedure
     extends Procedure<StiProtectionProcedure, StiProtectionTask, Person, Facility>
     implements EntityWithAppointment {
@@ -134,6 +144,12 @@ public class StiProtectionProcedure
   @Column(nullable = false)
   private LabStatus labStatus;
 
+  @DataSensitivity(SensitivityLevel.SENSITIVE)
+  private String sampleBarCode;
+
+  @DataSensitivity(SensitivityLevel.SENSITIVE)
+  private Instant appointmentStart;
+
   @Transient
   public Person getPerson() {
     Assert.isTrue(getRelatedPersons().size() == 1, "There should be exactly one related person");
@@ -286,7 +302,13 @@ public class StiProtectionProcedure
 
   @PrePersist
   @PreUpdate
-  public void computeLabStatus() {
+  public void computeFieldValues() {
+    computeLabStatus();
+    computeSampleBarcode();
+    computeAppointmentStart();
+  }
+
+  private void computeLabStatus() {
     labStatus = LabStatus.OPEN;
     if (laboratoryTestExamination != null
         && Objects.nonNull(laboratoryTestExamination.getTestsConductedDate())) {
@@ -300,4 +322,28 @@ public class StiProtectionProcedure
   public LabStatus getLabStatus() {
     return labStatus;
   }
+
+  private void computeSampleBarcode() {
+    if (laboratoryTestExamination == null) {
+      sampleBarCode = null;
+    } else {
+      sampleBarCode = laboratoryTestExamination.getSampleBarCode();
+    }
+  }
+
+  public String getSampleBarCode() {
+    return sampleBarCode;
+  }
+
+  private void computeAppointmentStart() {
+    if (userDefinedAppointment != null) {
+      appointmentStart = userDefinedAppointment.getAppointmentStart();
+    } else if (appointment != null) {
+      appointmentStart = appointment.getAppointmentStart();
+    }
+  }
+
+  public Instant getAppointmentStart() {
+    return appointmentStart;
+  }
 }
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/testhelper/StiProtectionTestHelperController.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/testhelper/StiProtectionTestHelperController.java
index 204191f1d5aab7b5a0ea80c733ba8e63caca4773..324abfae0d9b964fa74e2b1d6dcd60677e3915e4 100644
--- a/backend/sti-protection/src/main/java/de/eshg/stiprotection/testhelper/StiProtectionTestHelperController.java
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/testhelper/StiProtectionTestHelperController.java
@@ -5,18 +5,20 @@
 
 package de.eshg.stiprotection.testhelper;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.lib.auditlog.AuditLogTestHelperService;
 import de.eshg.stiprotection.OverdueProceduresNotifier;
 import de.eshg.stiprotection.api.CreateProcedureResponse;
 import de.eshg.stiprotection.api.StiProtectionProcedurePopulationRequest;
 import de.eshg.stiprotection.api.StiProtectionProcedurePopulationResponse;
+import de.eshg.stiprotection.api.TextTemplatePopulationRequest;
+import de.eshg.stiprotection.api.TextTemplatePopulationResponse;
+import de.eshg.stiprotection.api.texttemplate.TextTemplateDto;
 import de.eshg.testhelper.ConditionalOnTestHelperEnabled;
 import de.eshg.testhelper.TestHelperController;
 import de.eshg.testhelper.environment.EnvironmentConfig;
 import de.eshg.testhelper.population.ListWithTotalNumber;
 import jakarta.validation.Valid;
-import java.io.IOException;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
@@ -25,21 +27,24 @@ import org.springframework.web.service.annotation.PostExchange;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class StiProtectionTestHelperController extends TestHelperController
-    implements SharedAuditLogTestHelperApi {
+    implements AuditLogClientTestHelperApi {
 
   private final AuditLogTestHelperService auditLogTestHelperService;
   private final StiProtectionPopulator populator;
+  private final TextTemplatePopulator textTemplatePopulator;
   private final OverdueProceduresNotifier overdueProceduresNotifier;
 
   public StiProtectionTestHelperController(
       StiProtectionTestHelperService testHelperService,
       AuditLogTestHelperService auditLogTestHelperService,
       StiProtectionPopulator populator,
+      TextTemplatePopulator textTemplatePopulator,
       EnvironmentConfig environmentConfig,
       OverdueProceduresNotifier overdueProceduresNotifier) {
     super(testHelperService, environmentConfig);
     this.auditLogTestHelperService = auditLogTestHelperService;
     this.populator = populator;
+    this.textTemplatePopulator = textTemplatePopulator;
     this.overdueProceduresNotifier = overdueProceduresNotifier;
   }
 
@@ -52,6 +57,14 @@ public class StiProtectionTestHelperController extends TestHelperController
         result.entities(), result.totalNumberOfElements());
   }
 
+  @PostExchange("/population/text-templates")
+  public TextTemplatePopulationResponse populateTextTemplates(
+      @Valid @RequestBody TextTemplatePopulationRequest request) {
+    ListWithTotalNumber<TextTemplateDto> result =
+        this.textTemplatePopulator.populate(request.numberOfEntitiesToPopulate());
+    return new TextTemplatePopulationResponse(result.entities(), result.totalNumberOfElements());
+  }
+
   @PostExchange("/notify/overdue-procedures")
   public ResponseEntity<Void> notifyOfOverdueProcedures() {
     overdueProceduresNotifier.runNow();
@@ -59,12 +72,7 @@ public class StiProtectionTestHelperController extends TestHelperController
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
-  }
-
-  @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 }
diff --git a/backend/sti-protection/src/main/java/de/eshg/stiprotection/testhelper/TextTemplatePopulator.java b/backend/sti-protection/src/main/java/de/eshg/stiprotection/testhelper/TextTemplatePopulator.java
new file mode 100644
index 0000000000000000000000000000000000000000..290c7a1aaaffd7e72057d67764f037a577a54c38
--- /dev/null
+++ b/backend/sti-protection/src/main/java/de/eshg/stiprotection/testhelper/TextTemplatePopulator.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package de.eshg.stiprotection.testhelper;
+
+import static de.eshg.base.util.ClassNameUtil.getClassNameAsPropertyKey;
+
+import de.eshg.stiprotection.TextTemplateController;
+import de.eshg.stiprotection.api.texttemplate.CreateTextTemplateRequest;
+import de.eshg.stiprotection.api.texttemplate.CreateTextTemplateResponse;
+import de.eshg.stiprotection.api.texttemplate.TextTemplateContextDto;
+import de.eshg.stiprotection.api.texttemplate.TextTemplateDto;
+import de.eshg.stiprotection.mapper.texttemplate.TextTemplateMapper;
+import de.eshg.stiprotection.persistence.db.texttemplate.TextTemplate;
+import de.eshg.stiprotection.persistence.db.texttemplate.TextTemplateRepository;
+import de.eshg.testhelper.environment.EnvironmentConfig;
+import de.eshg.testhelper.population.BasePopulator;
+import de.eshg.testhelper.population.ListWithTotalNumber;
+import de.eshg.testhelper.population.PopulateWithAccessTokenHelper;
+import de.eshg.testhelper.population.PopulationProperties;
+import de.eshg.testhelper.population.PopulatorComponent;
+import java.time.Clock;
+import java.util.Optional;
+import net.datafaker.Faker;
+
+@PopulatorComponent
+public class TextTemplatePopulator extends BasePopulator<TextTemplateDto> {
+
+  private final PopulateWithAccessTokenHelper populateWithAccessTokenHelper;
+  private final TextTemplateController textTemplateController;
+  private final TextTemplateRepository textTemplateRepository;
+
+  public TextTemplatePopulator(
+      PopulationProperties properties,
+      Clock clock,
+      EnvironmentConfig environmentConfig,
+      PopulateWithAccessTokenHelper populateWithAccessTokenHelper,
+      TextTemplateRepository textTemplateRepository,
+      TextTemplateController textTemplateController) {
+    super(properties, clock, getClassNameAsPropertyKey(TextTemplateDto.class), environmentConfig);
+    this.populateWithAccessTokenHelper = populateWithAccessTokenHelper;
+    this.textTemplateController = textTemplateController;
+    this.textTemplateRepository = textTemplateRepository;
+  }
+
+  @Override
+  public ListWithTotalNumber<TextTemplateDto> populate(int numberOfEntitiesToPopulate) {
+    return populateWithAccessTokenHelper.doWithAccessToken(
+        () -> populateWithAuthentication(numberOfEntitiesToPopulate));
+  }
+
+  @Override
+  protected TextTemplateDto populate(
+      int index,
+      Faker faker,
+      BasePopulator<TextTemplateDto>.UniqueValueProvider uniqueValueProvider) {
+
+    CreateTextTemplateResponse resp =
+        textTemplateController.createTextTemplate(textTemplate(faker));
+    Optional<TextTemplate> texTemplateDto =
+        this.textTemplateRepository.findByExternalId(resp.textTemplateId());
+
+    return TextTemplateMapper.toInterfaceType(texTemplateDto.get());
+  }
+
+  @Override
+  protected long countExistingEntities() {
+    return textTemplateRepository.count();
+  }
+
+  private static CreateTextTemplateRequest textTemplate(Faker faker) {
+    return new CreateTextTemplateRequest(
+        faker.theItCrowd().actors() + " - Vorlage " + faker.random().nextInt(1, 10),
+        BasePopulator.randomElement(faker, TextTemplateContextDto.values()),
+        BasePopulator.randomElement(faker, textTemplateContents()));
+  }
+
+  private static String[] textTemplateContents() {
+    return new String[] {
+      "Patient ist verunsichert und uneinsichtig.",
+      "Syphilis-Wert: $Wert",
+      "Der Grund für den Besuch des Patienten ist $Grund.",
+      "Der Patient ist allergisch gegen $Allergie und kann deshalb nicht mit $Arznei behandelt werden.",
+      "Was ist ihre Aufgabe im Betrieb/Welche Position haben Sie inne? Antwort: $Aufgabe",
+      "Scherzfrage: Wie hoch ist die durchschnittliche Fluggeschwindigkeit einer unbeladenen Schwalbe? Antwort: $Antwort",
+      "HIV-Testergebnis: $Ergebnis.",
+      "Anmerkung für MFA: $Notiz.",
+      "Anmerkung für Arzt:Ärztin: $Notiz.",
+      "Gruppe: $Wert\nFlora: $Wert\nEndocervix: $Wert\nProliferationsgrad: $Wert\n\nBemerkung: $Text.\n\nHPV\nhigh risk HPV-DNA: $Befund\nlow risk HPV-DNA: $Befund\n\nC-Nr.: $LabornummerFürBürger"
+    };
+  }
+}
diff --git a/backend/sti-protection/src/main/resources/application-health-department-frankfurt.properties b/backend/sti-protection/src/main/resources/application-health-department-frankfurt.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1561ea528fda2b8adc8c40336d9feaa683acc404
--- /dev/null
+++ b/backend/sti-protection/src/main/resources/application-health-department-frankfurt.properties
@@ -0,0 +1,39 @@
+de.eshg.sti-protection.department-info.hiv_sti_consultation.name=HIV/STI - Beratung
+de.eshg.sti-protection.department-info.hiv_sti_consultation.abbreviation=HIV-STI-Beratung
+de.eshg.sti-protection.department-info.hiv_sti_consultation.street=Breite Gasse
+de.eshg.sti-protection.department-info.hiv_sti_consultation.houseNumber=28
+de.eshg.sti-protection.department-info.hiv_sti_consultation.postalCode=60313
+de.eshg.sti-protection.department-info.hiv_sti_consultation.city=Frankfurt am Main
+de.eshg.sti-protection.department-info.hiv_sti_consultation.country=DE
+de.eshg.sti-protection.department-info.hiv_sti_consultation.phoneNumber=+49 69 212 43270
+de.eshg.sti-protection.department-info.hiv_sti_consultation.homepage=https://frankfurt.de/service-und-rathaus/verwaltung/aemter-und-institutionen/gesundheitsamt
+de.eshg.sti-protection.department-info.hiv_sti_consultation.email=sexuelle.gesundheit@stadt-frankfurt.de
+# de.eshg.sti-protection.department-info.hiv_sti_consultation.latitude=
+# de.eshg.sti-protection.department-info.hiv_sti_consultation.longitude=
+
+# can be set individually to overwrite base department infos
+de.eshg.sti-protection.department-info.sex_work.name=HIV/STI - Sexarbeit
+de.eshg.sti-protection.department-info.sex_work.abbreviation=Sexarbeit
+de.eshg.sti-protection.department-info.sex_work.street=Breite Gasse
+de.eshg.sti-protection.department-info.sex_work.houseNumber=28
+de.eshg.sti-protection.department-info.sex_work.postalCode=60313
+de.eshg.sti-protection.department-info.sex_work.city=Frankfurt am Main
+de.eshg.sti-protection.department-info.sex_work.country=DE
+de.eshg.sti-protection.department-info.sex_work.phoneNumber=+49 69 212 43270
+de.eshg.sti-protection.department-info.sex_work.homepage=https://frankfurt.de/service-und-rathaus/verwaltung/aemter-und-institutionen/gesundheitsamt
+de.eshg.sti-protection.department-info.sex_work.email=sexuelle.gesundheit@stadt-frankfurt.de
+# de.eshg.sti-protection.department-info.sex_work.latitude=
+# de.eshg.sti-protection.department-info.sex_work.longitude=
+
+
+de.eshg.sti-protection.opening-hours.sex_work.de[0]=Di, Mi
+de.eshg.sti-protection.opening-hours.sex_work.de[1]=09:00 - 11:00 Uhr\nOffene Sprechstunde nur für Sexarbeiterinnen und Sexarbeiter
+
+de.eshg.sti-protection.opening-hours.sex_work.en[0]=Tu, We
+de.eshg.sti-protection.opening-hours.sex_work.en[1]=09:00 - 11:00 am\nOpen consultation hours only for sex workers
+
+de.eshg.sti-protection.opening-hours.hiv_sti_consultation.de[0]=Di, Mi 09:00 - 11:00 Uhr
+de.eshg.sti-protection.opening-hours.hiv_sti_consultation.de[1]=Offene Sprechstunde für alle
+
+de.eshg.sti-protection.opening-hours.hiv_sti_consultation.en[0]=Tu, We 09:00 - 11:00 am
+de.eshg.sti-protection.opening-hours.hiv_sti_consultation.en[1]=Open consultation hours for everyone
diff --git a/backend/sti-protection/src/main/resources/application.properties b/backend/sti-protection/src/main/resources/application.properties
index c5cb3b8f9eea0d4c0bde127795cfe1fd2e572f16..a4046083b2bf9541f0ee411395a7bbda57fa2477 100644
--- a/backend/sti-protection/src/main/resources/application.properties
+++ b/backend/sti-protection/src/main/resources/application.properties
@@ -19,6 +19,7 @@ de.eshg.lib.appointmentblock.defaultAppointmentTypeConfiguration[SEX_WORK]=30m
 de.eshg.lib.appointmentblock.defaultAppointmentTypeConfiguration[RESULTS_REVIEW]=30m
 
 eshg.population.default-number-of-entities-to-populate.sti-protection-procedure=30
+eshg.population.default-number-of-entities-to-populate.text-template-dto=30
 eshg.population.default-number-of-entities-to-populate.appointment-block-group=0
 
 eshg.sti-protection.overdue-procedures.cron=0 0 1 * * *
diff --git a/backend/sti-protection/src/main/resources/migrations/0045_add_sample_bar_code.xml b/backend/sti-protection/src/main/resources/migrations/0045_add_sample_bar_code.xml
new file mode 100644
index 0000000000000000000000000000000000000000..50fca9405cbdf157bc54d30c3c06439b3edcd943
--- /dev/null
+++ b/backend/sti-protection/src/main/resources/migrations/0045_add_sample_bar_code.xml
@@ -0,0 +1,20 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737541616148-1">
+    <addColumn tableName="sti_protection_procedure">
+      <column name="sample_bar_code" type="TEXT"/>
+    </addColumn>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737541616148-2">
+    <createIndex indexName="idx_sti_protection_procedure_sample_bar_code" tableName="sti_protection_procedure">
+      <column name="sample_bar_code"/>
+    </createIndex>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/sti-protection/src/main/resources/migrations/0046_add_appointment_start.xml b/backend/sti-protection/src/main/resources/migrations/0046_add_appointment_start.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1b6c2dc9f75ad725bde4dea851ba4486f53d1676
--- /dev/null
+++ b/backend/sti-protection/src/main/resources/migrations/0046_add_appointment_start.xml
@@ -0,0 +1,21 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737557805956-1">
+    <addColumn tableName="sti_protection_procedure">
+      <column name="appointment_start" type="TIMESTAMP WITH TIME ZONE"/>
+    </addColumn>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737557805956-2">
+    <createIndex indexName="idx_sti_protection_procedure_appointment_start"
+      tableName="sti_protection_procedure">
+      <column name="appointment_start"/>
+    </createIndex>
+  </changeSet>
+</databaseChangeLog>
diff --git a/backend/sti-protection/src/main/resources/migrations/0047_add_auditlog_entry.xml b/backend/sti-protection/src/main/resources/migrations/0047_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..28652f29b57ec0315a42976d18deee225ec7f99e
--- /dev/null
+++ b/backend/sti-protection/src/main/resources/migrations/0047_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/sti-protection/src/main/resources/migrations/0048_convert_duration_columns_to_interval.xml b/backend/sti-protection/src/main/resources/migrations/0048_convert_duration_columns_to_interval.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b823d445751a347a9bd4f46b15ce1307647cc
--- /dev/null
+++ b/backend/sti-protection/src/main/resources/migrations/0048_convert_duration_columns_to_interval.xml
@@ -0,0 +1,30 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="use_interval_for_durations">
+    <sql>
+      ALTER TABLE appointment_type_config
+      ALTER COLUMN standard_duration_in_minutes TYPE interval second(6)
+      USING (standard_duration_in_minutes * INTERVAL '1 minute');
+    </sql>
+    <renameColumn tableName="appointment_type_config"
+                  oldColumnName="standard_duration_in_minutes"
+                  newColumnName="standard_duration"/>
+
+    <sql>
+      ALTER TABLE appointment_block_group
+      ALTER COLUMN slot_duration_in_minutes TYPE interval second(6)
+      USING (slot_duration_in_minutes * INTERVAL '1 minute');
+    </sql>
+    <renameColumn tableName="appointment_block_group"
+                  oldColumnName="slot_duration_in_minutes"
+                  newColumnName="slot_duration"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/sti-protection/src/main/resources/migrations/changelog.xml b/backend/sti-protection/src/main/resources/migrations/changelog.xml
index 442c59cbcae50a861b503392f4427a5cbc22067b..aee80fc88ea55246f916f22475ae0a0eec93c93e 100644
--- a/backend/sti-protection/src/main/resources/migrations/changelog.xml
+++ b/backend/sti-protection/src/main/resources/migrations/changelog.xml
@@ -52,5 +52,9 @@
   <include file="migrations/0042_add_previous_file_state_id_to_system_progress_entry.xml"/>
   <include file="migrations/0043_add_text_templates.xml"/>
   <include file="migrations/0044_add_follow_up_flag.xml"/>
+  <include file="migrations/0045_add_sample_bar_code.xml"/>
+  <include file="migrations/0046_add_appointment_start.xml"/>
+  <include file="migrations/0047_add_auditlog_entry.xml"/>
+  <include file="migrations/0048_convert_duration_columns_to_interval.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/synapse/gradle.lockfile b/backend/synapse/gradle.lockfile
index e1de784a1f2d3bbc73fbb37623b8688c015ee47e..205a9bf9ba3e7ed6cf8eda70609b6b6220bdab63 100644
--- a/backend/synapse/gradle.lockfile
+++ b/backend/synapse/gradle.lockfile
@@ -20,10 +20,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -36,9 +36,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/test-commons/gradle.lockfile b/backend/test-commons/gradle.lockfile
index 3cfa3ddc875d2d07e8ccc492dd387f743ec23f1a..20a9f435916e2de80e6aa47707f8556dd29089c3 100644
--- a/backend/test-commons/gradle.lockfile
+++ b/backend/test-commons/gradle.lockfile
@@ -33,7 +33,7 @@ de.cronn:test-utils:1.1.1=compileClasspath,productionRuntimeClasspath,runtimeCla
 de.cronn:validation-file-assertions:0.8.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.persistence:jakarta.persistence-api:3.1.0=compileClasspath
@@ -61,11 +61,11 @@ org.checkerframework:checker-qual:3.43.0=productionRuntimeClasspath,runtimeClass
 org.hamcrest:hamcrest-core:2.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
-org.jetbrains:annotations:26.0.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
+org.jetbrains:annotations:26.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -78,9 +78,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/test-commons/src/main/java/de/eshg/base/AuditLogTraits.java b/backend/test-commons/src/main/java/de/eshg/base/AuditLogTraits.java
deleted file mode 100644
index 64b0e2037a21d3b16631748b7275bc6e4896e334..0000000000000000000000000000000000000000
--- a/backend/test-commons/src/main/java/de/eshg/base/AuditLogTraits.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package de.eshg.base;
-
-import de.cronn.assertions.validationfile.junit5.JUnit5ValidationFileAssertions;
-import de.cronn.assertions.validationfile.normalization.ValidationNormalizer;
-import de.eshg.normalization.UuidNormalizer;
-
-public interface AuditLogTraits extends JUnit5ValidationFileAssertions {
-
-  String SUFFIX = "auditlog";
-
-  StaticLogDirExtension auditLogDirExtension();
-
-  default ValidationNormalizer defaultValidationNormalizer() {
-    return new UuidNormalizer();
-  }
-
-  default void assertAuditLogContentWithFile() {
-    StaticLogDirExtension staticLogDirExtension = auditLogDirExtension();
-    assertWithFileWithSuffix(
-        dumpContent(staticLogDirExtension), defaultValidationNormalizer(), SUFFIX);
-  }
-
-  default void assertAuditLogContentWithFileWithSuffix(String suffix) {
-    StaticLogDirExtension staticLogDirExtension = auditLogDirExtension();
-    assertWithFileWithSuffix(
-        dumpContent(staticLogDirExtension), defaultValidationNormalizer(), SUFFIX + "_" + suffix);
-  }
-
-  private String dumpContent(StaticLogDirExtension staticLogDirExtension) {
-    return PathUtil.listDirectoryAndFileContent(staticLogDirExtension.toPath());
-  }
-}
diff --git a/backend/test-commons/src/main/java/de/eshg/base/StaticLogDirExtension.java b/backend/test-commons/src/main/java/de/eshg/base/StaticLogDirExtension.java
deleted file mode 100644
index d74d6d79e9551c56e6f7666ff105e0bb3c41413e..0000000000000000000000000000000000000000
--- a/backend/test-commons/src/main/java/de/eshg/base/StaticLogDirExtension.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package de.eshg.base;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import org.apache.commons.io.FileUtils;
-import org.junit.jupiter.api.extension.BeforeEachCallback;
-import org.junit.jupiter.api.extension.ExtensionContext;
-
-public class StaticLogDirExtension implements BeforeEachCallback {
-
-  private final Path logOutputDir = TempDirUtil.getTempDirOrThrow();
-
-  @Override
-  public void beforeEach(ExtensionContext context) throws IOException {
-    FileUtils.cleanDirectory(logOutputDir.toFile());
-    assertThat(logOutputDir).isEmptyDirectory();
-  }
-
-  public Path toPath() {
-    return logOutputDir;
-  }
-
-  public Path toAbsolutePath() {
-    return logOutputDir.toAbsolutePath();
-  }
-}
diff --git a/backend/test-commons/src/main/java/de/eshg/base/ZipUtil.java b/backend/test-commons/src/main/java/de/eshg/base/ZipUtil.java
index 3233cb3801230bf3495350ee4557ba83bcb75a3f..24a92d8fdfda6ce6cdadf5f266767eb0707dcf5b 100644
--- a/backend/test-commons/src/main/java/de/eshg/base/ZipUtil.java
+++ b/backend/test-commons/src/main/java/de/eshg/base/ZipUtil.java
@@ -23,34 +23,44 @@ import org.apache.commons.lang3.exception.UncheckedException;
 
 public class ZipUtil {
 
+  private static final int MAX_ENTRIES = 1_000;
+  private static final int MAX_BYTES = 1_000_000;
+
+  public static final String TOO_MANY_ZIP_ENTRIES = "Too many ZIP entries";
+  public static final String EXPANDED_CONTENT_TOO_LARGE = "Expanded content too large";
+
   private ZipUtil() {}
 
   public static byte[] extractZipEntry(String internalPath, byte[] content) {
     try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
         ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) {
-      for (ZipEntry zipEntry = zipInputStream.getNextEntry();
-          zipEntry != null;
-          zipEntry = zipInputStream.getNextEntry()) {
+      for (int numberOfEntries = 0; numberOfEntries < MAX_ENTRIES; numberOfEntries++) {
+        ZipEntry zipEntry = zipInputStream.getNextEntry();
+        if (zipEntry == null) {
+          return new byte[0];
+        }
         if (internalPath.equals(zipEntry.getName())) {
-          return zipInputStream.readAllBytes();
+          return readBytes(zipInputStream);
         }
       }
+      throw new IllegalStateException(TOO_MANY_ZIP_ENTRIES);
     } catch (IOException e) {
       throw new UncheckedIOException(e);
     }
-    return new byte[0];
   }
 
   public static List<String> listZipEntries(byte[] content) {
     try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
         ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) {
       List<String> zipEntries = new ArrayList<>();
-      for (ZipEntry zipEntry = zipInputStream.getNextEntry();
-          zipEntry != null;
-          zipEntry = zipInputStream.getNextEntry()) {
+      for (int numberOfEntries = 0; numberOfEntries < MAX_ENTRIES; numberOfEntries++) {
+        ZipEntry zipEntry = zipInputStream.getNextEntry();
+        if (zipEntry == null) {
+          return zipEntries;
+        }
         zipEntries.add(zipEntry.getName());
       }
-      return zipEntries;
+      throw new IllegalStateException(TOO_MANY_ZIP_ENTRIES);
     } catch (IOException e) {
       throw new UncheckedIOException(e);
     }
@@ -65,20 +75,28 @@ public class ZipUtil {
   }
 
   public static String listZipContent(byte[] content, List<ValidationNormalizer> normalizers) {
+    long totalSize = 0;
     List<String> results = new ArrayList<>();
     try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
         ZipInputStream zipInputStream = new ZipInputStream(byteArrayInputStream)) {
-      for (ZipEntry zipEntry = zipInputStream.getNextEntry();
-          zipEntry != null;
-          zipEntry = zipInputStream.getNextEntry()) {
-        results.add(stringifyZipEntry(zipEntry, zipInputStream.readAllBytes(), normalizers));
+      for (int numberOfEntries = 0; numberOfEntries < MAX_ENTRIES; numberOfEntries++) {
+        ZipEntry zipEntry = zipInputStream.getNextEntry();
+        if (zipEntry == null) {
+          return results.stream()
+              .map(String::stripTrailing)
+              .collect(Collectors.joining(System.lineSeparator()));
+        }
+        byte[] entryContent = readBytes(zipInputStream);
+        totalSize += entryContent.length;
+        if (totalSize > MAX_BYTES) {
+          throw new IllegalStateException(EXPANDED_CONTENT_TOO_LARGE);
+        }
+        results.add(stringifyZipEntry(zipEntry, entryContent, normalizers));
       }
+      throw new IllegalStateException(TOO_MANY_ZIP_ENTRIES);
     } catch (IOException e) {
       throw new UncheckedIOException(e);
     }
-    return results.stream()
-        .map(String::stripTrailing)
-        .collect(Collectors.joining(System.lineSeparator()));
   }
 
   private static String stringifyZipEntry(
@@ -120,4 +138,12 @@ public class ZipUtil {
     }
     return source;
   }
+
+  private static byte[] readBytes(ZipInputStream zipInputStream) throws IOException {
+    byte[] result = zipInputStream.readNBytes(MAX_BYTES);
+    if (zipInputStream.readNBytes(1).length > 0) {
+      throw new IllegalArgumentException(EXPANDED_CONTENT_TOO_LARGE);
+    }
+    return result;
+  }
 }
diff --git a/backend/test-helper-commons-api/gradle.lockfile b/backend/test-helper-commons-api/gradle.lockfile
index f7af9e94fd2830ba8c91f01f42aa78daf4970cac..da1f0d31c882eb0013b2658258605ac601e9a55f 100644
--- a/backend/test-helper-commons-api/gradle.lockfile
+++ b/backend/test-helper-commons-api/gradle.lockfile
@@ -9,7 +9,7 @@ com.jayway.jsonpath:json-path:2.9.0=testCompileClasspath,testRuntimeClasspath
 com.vaadin.external.google:android-json:0.0.20131108.vaadin1=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
@@ -24,10 +24,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -40,9 +40,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/test-helper-commons-spring/gradle.lockfile b/backend/test-helper-commons-spring/gradle.lockfile
index 2424c4def42de9adb7c6c16e3d3eb910baf6a454..23de517272894c96f92f18e3927352927e75a598 100644
--- a/backend/test-helper-commons-spring/gradle.lockfile
+++ b/backend/test-helper-commons-spring/gradle.lockfile
@@ -20,10 +20,10 @@ org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath
 org.assertj:assertj-core:3.26.3=testCompileClasspath,testRuntimeClasspath
 org.awaitility:awaitility:4.2.2=testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-params:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -36,9 +36,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=testCompileClasspath,testRuntimeClasspath
diff --git a/backend/test-helper-commons/gradle.lockfile b/backend/test-helper-commons/gradle.lockfile
index 9c8bed43355f7bf6536320d16669e4a4eeb49dfa..bd3ebd849f08db93bfc297d8d9b014c190937fef 100644
--- a/backend/test-helper-commons/gradle.lockfile
+++ b/backend/test-helper-commons/gradle.lockfile
@@ -55,10 +55,10 @@ io.prometheus:prometheus-metrics-exposition-formats:1.3.5=testRuntimeClasspath
 io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.3.5=testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.persistence:jakarta.persistence-api:3.1.0=compileClasspath
@@ -99,10 +99,10 @@ org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
 org.hdrhistogram:HdrHistogram:2.2.2=testRuntimeClasspath
 org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath
 org.hibernate.validator:hibernate-validator:8.0.2.Final=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -120,16 +120,17 @@ org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspa
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/test-helper-commons/src/main/java/de/eshg/testhelper/DefaultTestHelperService.java b/backend/test-helper-commons/src/main/java/de/eshg/testhelper/DefaultTestHelperService.java
index 0069e193e6771bac545c5a3fd1240e7094244260..7fe639a351222685eb6efbb2e5867c15cb85424c 100644
--- a/backend/test-helper-commons/src/main/java/de/eshg/testhelper/DefaultTestHelperService.java
+++ b/backend/test-helper-commons/src/main/java/de/eshg/testhelper/DefaultTestHelperService.java
@@ -111,12 +111,16 @@ public class DefaultTestHelperService implements TestHelperWithDatabaseService {
   public void resetResettableProperties() {
     environmentConfig.assertIsNotProduction();
     for (ResettableProperties resettableProperties : resettableProperties) {
-      String resettablePropertiesSnapshot =
-          initialResettablePropertiesSnapshots.get(resettableProperties);
-      SnapshotUtil.restoreSnapshot(resettablePropertiesSnapshot, resettableProperties);
+      resetProperties(resettableProperties);
     }
   }
 
+  public void resetProperties(ResettableProperties resettableProperties) {
+    String resettablePropertiesSnapshot =
+        initialResettablePropertiesSnapshots.get(resettableProperties);
+    SnapshotUtil.restoreSnapshot(resettablePropertiesSnapshot, resettableProperties);
+  }
+
   protected String[] getTablesToExclude() {
     return new String[] {};
   }
diff --git a/backend/travel-medicine/build.gradle b/backend/travel-medicine/build.gradle
index d6e4afe3cefb093831d57d41fbee1018c3f0420f..50625463685b125e01c6212944fbf7c83155614d 100644
--- a/backend/travel-medicine/build.gradle
+++ b/backend/travel-medicine/build.gradle
@@ -23,6 +23,7 @@ dependencies {
     testImplementation testFixtures(project(':lib-procedures'))
     testImplementation testFixtures(project(':base-api'))
     testImplementation testFixtures(project(':lib-procedures'))
+    testImplementation testFixtures(project(':lib-auditlog'))
 }
 
 dockerCompose {
diff --git a/backend/travel-medicine/gradle.lockfile b/backend/travel-medicine/gradle.lockfile
index 30a32d8e7f87e6107aa55520e11d6d31c97fd3ee..2537c3d60fb85d9bd8c4c4002797fcc0f8b74829 100644
--- a/backend/travel-medicine/gradle.lockfile
+++ b/backend/travel-medicine/gradle.lockfile
@@ -72,10 +72,10 @@ io.prometheus:prometheus-metrics-exposition-textformats:1.3.5=productionRuntimeC
 io.prometheus:prometheus-metrics-model:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.prometheus:prometheus-metrics-tracer-common:1.3.5=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 io.smallrye:jandex:3.2.0=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations:2.2.27=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-core-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-models-jakarta:2.2.27=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations:2.2.28=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-core-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-models-jakarta:2.2.28=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 jakarta.inject:jakarta.inject-api:2.0.1=annotationProcessor,productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
@@ -161,10 +161,10 @@ org.hibernate.orm:hibernate-core:6.6.4.Final=annotationProcessor,compileClasspat
 org.hibernate.orm:hibernate-envers:6.6.4.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hibernate.orm:hibernate-jpamodelgen:6.6.4.Final=annotationProcessor
 org.hibernate.validator:hibernate-validator:8.0.2.Final=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jboss.logging:jboss-logging:3.6.1.Final=annotationProcessor,compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.jetbrains:annotations:17.0.0=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
@@ -183,16 +183,17 @@ org.mozilla:rhino:1.7.13=productionRuntimeClasspath,runtimeClasspath,testRuntime
 org.objenesis:objenesis:3.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=productionRuntimeClasspath,runtimeClasspath,testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testCompileClasspath,testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
 org.slf4j:jul-to-slf4j:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.slf4j:slf4j-api:2.0.16=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-common:2.8.3=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
-org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3=testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-common:2.8.4=productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
+org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.4=testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-actuator:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.springframework.boot:spring-boot-autoconfigure:3.4.1=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
diff --git a/backend/travel-medicine/openApi.json b/backend/travel-medicine/openApi.json
index 1bed10406d1ab93c4e3c3f7346699300eec05fa9..3f3ad546a3865db888f6264f4ec623ea300f338e 100644
--- a/backend/travel-medicine/openApi.json
+++ b/backend/travel-medicine/openApi.json
@@ -3436,18 +3436,7 @@
     },
     "/test-helper/archiving-job" : {
       "post" : {
-        "operationId" : "runArchivingJob",
-        "responses" : {
-          "200" : {
-            "description" : "OK"
-          }
-        },
-        "tags" : [ "TestHelper" ]
-      }
-    },
-    "/test-helper/audit-log-storage" : {
-      "delete" : {
-        "operationId" : "clearAuditLogStorageDirectory",
+        "operationId" : "runAuditLogArchivingJob",
         "responses" : {
           "200" : {
             "description" : "OK"
@@ -5039,9 +5028,9 @@
             "format" : "uuid"
           },
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
@@ -9474,9 +9463,9 @@
         "type" : "object",
         "properties" : {
           "standardDurationInMinutes" : {
-            "minimum" : 0,
+            "minimum" : 1,
             "type" : "integer",
-            "format" : "int32"
+            "format" : "int64"
           }
         }
       },
diff --git a/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/testhelper/TravelMedicineTestHelperController.java b/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/testhelper/TravelMedicineTestHelperController.java
index 344fcddfde501d4579896b431dcc7110e102072a..58d8c3418fe1a6bc243a8ac65bd463910b73ec7b 100644
--- a/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/testhelper/TravelMedicineTestHelperController.java
+++ b/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/testhelper/TravelMedicineTestHelperController.java
@@ -5,7 +5,7 @@
 
 package de.eshg.travelmedicine.testhelper;
 
-import de.eshg.auditlog.SharedAuditLogTestHelperApi;
+import de.eshg.auditlog.AuditLogClientTestHelperApi;
 import de.eshg.lib.auditlog.AuditLogTestHelperService;
 import de.eshg.testhelper.ConditionalOnTestHelperEnabled;
 import de.eshg.testhelper.TestHelperApi;
@@ -19,7 +19,6 @@ import de.eshg.travelmedicine.testhelper.api.PostPopulateProcedureRequest;
 import de.eshg.travelmedicine.testhelper.api.PostPopulateProcedureResponse;
 import io.swagger.v3.oas.annotations.Operation;
 import jakarta.validation.Valid;
-import java.io.IOException;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
@@ -28,7 +27,7 @@ import org.springframework.web.service.annotation.PostExchange;
 @RestController
 @ConditionalOnTestHelperEnabled
 public class TravelMedicineTestHelperController extends TestHelperController
-    implements SharedAuditLogTestHelperApi {
+    implements AuditLogClientTestHelperApi {
 
   public static final String TEST_POPULATION_PATH = "/population";
   public static final String TEST_POPULATION_URL = TestHelperApi.BASE_URL + TEST_POPULATION_PATH;
@@ -76,12 +75,7 @@ public class TravelMedicineTestHelperController extends TestHelperController
   }
 
   @Override
-  public void clearAuditLogStorageDirectory() throws IOException {
-    auditLogTestHelperService.clearAuditLogStorageDirectory();
-  }
-
-  @Override
-  public void runArchivingJob() {
-    auditLogTestHelperService.runArchivingJob();
+  public void runAuditLogArchivingJob() {
+    auditLogTestHelperService.runAuditLogArchivingJob();
   }
 }
diff --git a/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/vaccinationconsultation/PersonClient.java b/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/vaccinationconsultation/PersonClient.java
index 6c0ca06e4e9dacddd75598902baca9da83a0a661..97669ebb4f5fb1b07594e8e48e823506dc602b25 100644
--- a/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/vaccinationconsultation/PersonClient.java
+++ b/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/vaccinationconsultation/PersonClient.java
@@ -146,22 +146,22 @@ public class PersonClient {
             .orElseThrow(() -> new BadRequestException("Reference person not found."));
     boolean dataAdded =
         addEmailAndPhoneNumberToReferencePerson(referencePerson, personFromCentralFile);
-    PersonDetailsDto personDetailsDto = mapToPersonDetailsDto(referencePerson);
+    UpdatePersonRequest updatePersonRequest = mapToUpdatePersonRequest(referencePerson);
     AddPersonFileStateResponse addPersonFileStateResponse;
     if (dataAdded) {
       UpdateReferencePersonRequest updateReferencePersonRequest =
-          new UpdateReferencePersonRequest(personDetailsDto, referencePerson.version());
+          new UpdateReferencePersonRequest(updatePersonRequest, referencePerson.version());
       addPersonFileStateResponse =
           personApi.updateReferencePerson(referencePersonId, updateReferencePersonRequest);
     } else {
-      AddPersonFileStateRequest addPersonRequest = mapToAddPeronRequest(referencePerson);
+      AddPersonFileStateRequest addPersonRequest = mapToAddPersonRequest(referencePerson);
       addPersonFileStateResponse = personApi.addPersonFileState(addPersonRequest);
     }
 
     return addPersonFileStateResponse.id();
   }
 
-  private AddPersonFileStateRequest mapToAddPeronRequest(
+  private AddPersonFileStateRequest mapToAddPersonRequest(
       GetReferencePersonResponse referencePerson) {
     return new AddPersonFileStateRequest(
         referencePerson.id(),
@@ -339,8 +339,8 @@ public class PersonClient {
         personFromCentralFile.differentBillingAddress());
   }
 
-  private PersonDetailsDto mapToPersonDetailsDto(GetReferencePersonResponse referencePerson) {
-    return new PersonDetailsDto(
+  private UpdatePersonRequest mapToUpdatePersonRequest(GetReferencePersonResponse referencePerson) {
+    return new UpdatePersonRequest(
         referencePerson.title(),
         referencePerson.salutation(),
         referencePerson.gender(),
diff --git a/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/vaccinationconsultation/VaccinationConsultationController.java b/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/vaccinationconsultation/VaccinationConsultationController.java
index b71ca6c77fdd13ea3084adb3d944eea2fa93335b..5a018325b1b235abc8cb28a054c5b9cf299f37c2 100644
--- a/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/vaccinationconsultation/VaccinationConsultationController.java
+++ b/backend/travel-medicine/src/main/java/de/eshg/travelmedicine/vaccinationconsultation/VaccinationConsultationController.java
@@ -153,7 +153,7 @@ public class VaccinationConsultationController {
 
   @GetMapping(path = "/{procedureId}" + DETAILS_URL)
   @Operation(summary = "Get vaccination consultation details")
-  @Transactional(readOnly = true)
+  @Transactional
   public GetVaccinationConsultationDetailsResponse getVaccinationConsultationDetails(
       @PathVariable("procedureId") UUID procedureId) {
     GetVaccinationConsultationDetailsResponse vaccinationConsultationDetails =
diff --git a/backend/travel-medicine/src/main/resources/migrations/0057_add_auditlog_entry.xml b/backend/travel-medicine/src/main/resources/migrations/0057_add_auditlog_entry.xml
new file mode 100644
index 0000000000000000000000000000000000000000..123233c564a61e3312bf33ae50680e5b2f8c2c7c
--- /dev/null
+++ b/backend/travel-medicine/src/main/resources/migrations/0057_add_auditlog_entry.xml
@@ -0,0 +1,55 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 SCOOP Software GmbH, cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="1737664353337-1">
+    <createSequence cacheSize="1" cycle="false" dataType="bigint" incrementBy="50"
+      maxValue="9223372036854775807" minValue="1" sequenceName="audit_log_entry_seq"
+      startValue="1"/>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-2">
+    <createTable tableName="audit_log_entry">
+      <column name="id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true" primaryKeyName="pk_audit_log_entry"/>
+      </column>
+      <column name="version" type="BIGINT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="category" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+      <column name="created_at" type="TIMESTAMP WITH TIME ZONE">
+        <constraints nullable="false"/>
+      </column>
+      <column name="function" type="TEXT">
+        <constraints nullable="false"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-3">
+    <createTable tableName="audit_log_entry_additional_data">
+      <column name="audit_log_entry_id" type="BIGINT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+      <column name="additional_data" type="TEXT"/>
+      <column name="additional_data_key" type="TEXT">
+        <constraints nullable="false" primaryKey="true"
+          primaryKeyName="pk_audit_log_entry_additional_data"/>
+      </column>
+    </createTable>
+  </changeSet>
+  <changeSet author="GA-Lotse" id="1737664353337-4">
+    <addForeignKeyConstraint constraintName="fk_audit_log_entry_additional_data_audit_log_entry"
+      baseTableName="audit_log_entry_additional_data" baseColumnNames="audit_log_entry_id"
+      referencedTableName="audit_log_entry" referencedColumnNames="id"
+      deferrable="false" initiallyDeferred="false" onDelete="NO ACTION"
+      onUpdate="NO ACTION" validate="true"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/travel-medicine/src/main/resources/migrations/0058_convert_duration_columns_to_interval.xml b/backend/travel-medicine/src/main/resources/migrations/0058_convert_duration_columns_to_interval.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ce7f10863e636b7220101bc017412b9630a40b27
--- /dev/null
+++ b/backend/travel-medicine/src/main/resources/migrations/0058_convert_duration_columns_to_interval.xml
@@ -0,0 +1,30 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<!--
+ Copyright 2025 SCOOP Software GmbH, cronn GmbH
+ SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
+  <changeSet author="GA-Lotse" id="use_interval_for_durations">
+    <sql>
+      ALTER TABLE appointment_type_config
+      ALTER COLUMN standard_duration_in_minutes TYPE interval second(6)
+      USING (standard_duration_in_minutes * INTERVAL '1 minute');
+    </sql>
+    <renameColumn tableName="appointment_type_config"
+                  oldColumnName="standard_duration_in_minutes"
+                  newColumnName="standard_duration"/>
+
+    <sql>
+      ALTER TABLE appointment_block_group
+      ALTER COLUMN slot_duration_in_minutes TYPE interval second(6)
+      USING (slot_duration_in_minutes * INTERVAL '1 minute');
+    </sql>
+    <renameColumn tableName="appointment_block_group"
+                  oldColumnName="slot_duration_in_minutes"
+                  newColumnName="slot_duration"/>
+  </changeSet>
+</databaseChangeLog>
+
diff --git a/backend/travel-medicine/src/main/resources/migrations/changelog.xml b/backend/travel-medicine/src/main/resources/migrations/changelog.xml
index 3a0fd7858d775d3c10b7fa68cce515aa326a3065..2788bc867f320d1dbac35f2306c77b1b91db6042 100644
--- a/backend/travel-medicine/src/main/resources/migrations/changelog.xml
+++ b/backend/travel-medicine/src/main/resources/migrations/changelog.xml
@@ -64,5 +64,7 @@
   <include file="migrations/0054_make_appointment_block_users_non_nullable.xml"/>
   <include file="migrations/0055_add_cemetery_delete_at.xml"/>
   <include file="migrations/0056_add_previous_file_state_id_to_system_progress_entry.xml"/>
+  <include file="migrations/0057_add_auditlog_entry.xml"/>
+  <include file="migrations/0058_convert_duration_columns_to_interval.xml"/>
 
 </databaseChangeLog>
diff --git a/backend/util-commons/gradle.lockfile b/backend/util-commons/gradle.lockfile
index c1378d07d2ad1be30441741a5552ac0912fbf1b4..7721f3d489477cb40c2ca01a82fe075c9294a7cd 100644
--- a/backend/util-commons/gradle.lockfile
+++ b/backend/util-commons/gradle.lockfile
@@ -33,7 +33,7 @@ de.cronn:test-utils:1.1.1=testCompileClasspath,testRuntimeClasspath
 de.cronn:validation-file-assertions:0.8.0=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-commons:1.14.2=testCompileClasspath,testRuntimeClasspath
 io.micrometer:micrometer-observation:1.14.2=testCompileClasspath,testRuntimeClasspath
-io.swagger.core.v3:swagger-annotations-jakarta:2.2.27=testCompileClasspath,testRuntimeClasspath
+io.swagger.core.v3:swagger-annotations-jakarta:2.2.28=testCompileClasspath,testRuntimeClasspath
 jakarta.activation:jakarta.activation-api:2.1.3=testCompileClasspath,testRuntimeClasspath
 jakarta.annotation:jakarta.annotation-api:2.1.1=testCompileClasspath,testRuntimeClasspath
 jakarta.validation:jakarta.validation-api:3.0.2=testCompileClasspath,testRuntimeClasspath
@@ -58,10 +58,10 @@ org.bouncycastle:bcutil-jdk18on:1.80=testRuntimeClasspath
 org.checkerframework:checker-qual:3.43.0=compileClasspath,productionRuntimeClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
 org.hamcrest:hamcrest-core:2.2=testRuntimeClasspath
 org.hamcrest:hamcrest:2.2=testCompileClasspath,testRuntimeClasspath
-org.jacoco:org.jacoco.agent:0.8.11=jacocoAgent,jacocoAnt
-org.jacoco:org.jacoco.ant:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.core:0.8.11=jacocoAnt
-org.jacoco:org.jacoco.report:0.8.11=jacocoAnt
+org.jacoco:org.jacoco.agent:0.8.12=jacocoAgent,jacocoAnt
+org.jacoco:org.jacoco.ant:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.core:0.8.12=jacocoAnt
+org.jacoco:org.jacoco.report:0.8.12=jacocoAnt
 org.jetbrains:annotations:17.0.0=testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.11.4=testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-engine:5.11.4=testRuntimeClasspath
@@ -75,9 +75,10 @@ org.mockito:mockito-core:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.mockito:mockito-junit-jupiter:5.14.2=testCompileClasspath,testRuntimeClasspath
 org.objenesis:objenesis:3.3=testRuntimeClasspath
 org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath
-org.ow2.asm:asm-commons:9.6=jacocoAnt
-org.ow2.asm:asm-tree:9.6=jacocoAnt
-org.ow2.asm:asm:9.6=jacocoAnt,testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm-commons:9.7=jacocoAnt
+org.ow2.asm:asm-tree:9.7=jacocoAnt
+org.ow2.asm:asm:9.6=testCompileClasspath,testRuntimeClasspath
+org.ow2.asm:asm:9.7=jacocoAnt
 org.postgresql:postgresql:42.7.4=testRuntimeClasspath
 org.rnorth.duct-tape:duct-tape:1.0.8=testRuntimeClasspath
 org.skyscreamer:jsonassert:1.5.3=testCompileClasspath,testRuntimeClasspath
diff --git a/build.gradle b/build.gradle
index 4a9958f606305388f82701d0f8739a779a8188d5..12e749843ee8399186a43aba9a5d4bf3ecc77972 100644
--- a/build.gradle
+++ b/build.gradle
@@ -28,7 +28,7 @@ dockerCompose {
 //CAUTION: run ./gradlew wrapper (twice) after changes to this task!
 //See https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:upgrading_wrapper
 wrapper {
-  gradleVersion = '8.9'
+  gradleVersion = '8.12.1'
   distributionType = Wrapper.DistributionType.ALL
 }
 
diff --git a/buildSrc/src/main/groovy/node.gradle b/buildSrc/src/main/groovy/node.gradle
index 776d575db3b73bfaf76850558b07185697a16f09..de48161a891d5a5d251b91b735f88d670f0f23ed 100644
--- a/buildSrc/src/main/groovy/node.gradle
+++ b/buildSrc/src/main/groovy/node.gradle
@@ -4,7 +4,7 @@ plugins {
 
 node {
   version = '22.13.1'
-  pnpmVersion = '9.15.4'
+  pnpmVersion = '10.1.0'
   download = true
   workDir = file("${rootProject.projectDir}/.gradle/nodejs")
   pnpmWorkDir = file("${rootProject.projectDir}/.gradle/pnpm")
diff --git a/buildSrc/src/main/groovy/openapi-generator.gradle b/buildSrc/src/main/groovy/openapi-generator.gradle
deleted file mode 100644
index 11be10e5a7441c2b587e0412322987c4f8478f53..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/groovy/openapi-generator.gradle
+++ /dev/null
@@ -1,116 +0,0 @@
-import org.apache.commons.io.FilenameUtils
-import org.openapitools.generator.gradle.plugin.tasks.GenerateTask
-import de.eshg.frontend.OpenapiGeneratorPluginConfiguration
-
-import java.nio.file.Files
-
-plugins {
-  id 'workspace-package'
-}
-
-def groupName = 'generated api';
-def generateTaskName = 'generateApi'
-def srcDir = layout.projectDirectory.dir('src')
-
-def openapiGeneratorExtension = project.extensions.create('openapiGenerator', OpenapiGeneratorPluginConfiguration)
-
-def generateMetaTaskProvider = tasks.register(generateTaskName) {
-  group = groupName
-}
-
-tasks.named('compile') {
-  dependsOn generateMetaTaskProvider
-  inputs.files("${rootDir}/config/tsconfig.lib-legacy.json")
-}
-
-static String emulateSymlinkIfNecessary(java.nio.file.Path path) {
-  if (Files.isSymbolicLink(path)) {
-    return path.toString()
-  } else if (Files.isRegularFile(path)) {
-    // Try to emulate git symlinks on Windows
-    def lines = Files.readAllLines(path)
-    if (lines.size() == 1) {
-      String symlink = lines.get(0)
-      return path.getParent().resolve(symlink)
-    } else {
-      // Required for the opencode pipeline
-      return path.toString();
-    }
-  } else {
-    throw new IllegalArgumentException("${path} is neither a symlink nor a regular file")
-  }
-}
-
-project.afterEvaluate {
-  // We have multiple spec files in the project and create dynamic generate tasks for each.
-  // They are added as dependency to the meta generate task.
-  openapiGeneratorExtension.inputSpecs.get().each { apiName, specFile ->
-    {
-      def generatedApiDir = srcDir.file(apiName).asFile.path
-      def generateTaskProvider = tasks.register("${generateTaskName}_${apiName}", GenerateTask) {
-        group = groupName
-        dependsOn rootProject.tasks.installDependencies
-        generatorName = 'typescript-fetch'
-        inputSpec = emulateSymlinkIfNecessary(specFile.asFile.toPath())
-        outputDir = generatedApiDir
-        modelNamePrefix = 'Api'
-        additionalProperties = [
-          'supportsES6'                : 'true',
-          'withInterfaces'             : 'true',
-          'useSingleRequestParameter'  : 'false',
-          // We need the "modern" discriminator behavior for the discriminator columns.
-          // See https://blog.cronn.de/en/java/rest/2024/01/02/grand-cronn-pet-hotel.html
-          // However, it seems to be not as battle tested and thus it generates duplicated imports that we fix via fixDuplicateImports()
-          'legacyDiscriminatorBehavior': 'false',
-          // Override default enum suffix 'Enum'
-          'enumNameSuffix'             : ''
-        ]
-
-        doFirst {
-          delete generatedApiDir
-        }
-
-        doLast {
-          // See the comment at the "legacyDiscriminatorBehavior" property
-          fixDuplicateImports(generatedApiDir)
-        }
-      }
-
-      generateMetaTaskProvider.configure {
-        dependsOn generateTaskProvider
-      }
-    }
-  }
-}
-
-// Fix/workaround for https://github.com/OpenAPITools/openapi-generator/issues/15637
-private void fixDuplicateImports(openApiOutputDir) {
-  fileTree("${openApiOutputDir}/models").matching {
-    include "**/*.ts"
-  }.visit { FileVisitDetails details ->
-    details.file.text = details.file.text.replaceAll(/(?m)import \{(\s*.*?FromJSONTyped,?)+\s*\} from '\.\/index';/, "// removed duplicate import here")
-
-    // Self imports, needed when discriminator for self exists
-    def importName = FilenameUtils.removeExtension(details.file.name)
-    details.file.text = details.file.text.replaceAll(/(?m)import type \{\s+$importName\s+} from '\.\/$importName';/, "// removed self import here")
-    details.file.text = details.file.text.replaceAll(/(?m)import \{\s+(?:\w+(?:FromJSON|FromJSONTyped|ToJSON),\s+){3}} from '\.\/$importName';/, "// removed self import here")
-  }
-}
-
-tasks.register('assemble') {
-  dependsOn 'compile'
-}
-
-tasks.register('build') {
-  dependsOn 'check'
-  dependsOn 'assemble'
-}
-
-def cleanGeneratedApiProvider = tasks.register('cleanGeneratedApi', Delete) {
-  group = groupName
-  delete srcDir
-}
-
-tasks.named('clean').configure {
-  dependsOn cleanGeneratedApiProvider
-}
diff --git a/citizen-portal-api/.gitignore b/citizen-portal-api/.gitignore
deleted file mode 100644
index 39f8bdd3b0bff4ce3f1319012653f59f5b97b6c4..0000000000000000000000000000000000000000
--- a/citizen-portal-api/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-src/**
diff --git a/citizen-portal-api/build.gradle b/citizen-portal-api/build.gradle
deleted file mode 100644
index d9315d2f6821e70ed28a5974b422d0f1372efb8a..0000000000000000000000000000000000000000
--- a/citizen-portal-api/build.gradle
+++ /dev/null
@@ -1,14 +0,0 @@
-plugins {
-  id 'openapi-generator'
-}
-
-def backendDir = rootProject.layout.projectDirectory.dir('backend')
-
-openapiGenerator {
-  inputSpecs = [
-    'businessProcedures' : backendDir.file('lib-procedures/openApi.json'), // TODO: use separate OpenAPI specification for citizen-portal
-    'officialMedicalService' : backendDir.file('official-medical-service/openApi.json'), // TODO: use separate OpenAPI specification for citizen-portal
-    'medicalRegistry' : backendDir.file('medical-registry/openApi.json'), // TODO: use separate OpenAPI specification for citizen-portal
-    'openData' : backendDir.file('opendata/openApi.json'), // TODO: use separate OpenAPI specification for citizen-portal
-  ]
-}
diff --git a/citizen-portal-api/package.json b/citizen-portal-api/package.json
deleted file mode 100644
index 2a2bee28fd2eac7af362c7dbf292ab6dcf280004..0000000000000000000000000000000000000000
--- a/citizen-portal-api/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "name": "@eshg/citizen-portal-api",
-  "version": "0.0.1",
-  "type": "module",
-  "private": true,
-  "exports": {
-    "./*": "./build/dist/src/*/index.js"
-  }
-}
diff --git a/citizen-portal-api/tsconfig.json b/citizen-portal-api/tsconfig.json
deleted file mode 100644
index f3bf745a5f0f3fbae682f4146c44713edda84dcd..0000000000000000000000000000000000000000
--- a/citizen-portal-api/tsconfig.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "extends": "../config/tsconfig.lib-legacy.json"
-}
diff --git a/citizen-portal/gradleDependencies.json b/citizen-portal/gradleDependencies.json
index 24f5ae4853d6f9da32af1b77af8d7277fcc61282..d06419508bcfd1ed35341ee1d63df57d87347f31 100644
--- a/citizen-portal/gradleDependencies.json
+++ b/citizen-portal/gradleDependencies.json
@@ -1,9 +1,12 @@
 {
   "dependencies": [
     ":base-api",
-    ":citizen-portal-api",
     ":lib-portal",
+    ":lib-procedures-api",
     ":measles-protection-api",
+    ":medical-registry-api",
+    ":official-medical-service-api",
+    ":opendata-api",
     ":school-entry-api",
     ":travel-medicine-api"
   ]
diff --git a/citizen-portal/package.json b/citizen-portal/package.json
index a977c658e93e37b55b7cfff5d50330f4f6051be2..5c8b7d22d518d75db670841f99e2d8502cf32ca2 100644
--- a/citizen-portal/package.json
+++ b/citizen-portal/package.json
@@ -7,9 +7,12 @@
     "@emotion/react": "catalog:joy",
     "@emotion/styled": "catalog:joy",
     "@eshg/base-api": "workspace:*",
-    "@eshg/citizen-portal-api": "workspace:*",
     "@eshg/lib-portal": "workspace:*",
+    "@eshg/lib-procedures-api": "workspace:*",
     "@eshg/measles-protection-api": "workspace:*",
+    "@eshg/medical-registry-api": "workspace:*",
+    "@eshg/official-medical-service-api": "workspace:*",
+    "@eshg/opendata-api": "workspace:*",
     "@eshg/school-entry-api": "workspace:*",
     "@eshg/travel-medicine-api": "workspace:*",
     "@fontsource/poppins": "catalog:joy",
diff --git a/citizen-portal/src/lib/baseModule/api/queries/gdpr.ts b/citizen-portal/src/lib/baseModule/api/queries/gdpr.ts
index 431ed00ccd5fd4b4e7f08a20fa5b3241f320a008..2e9031f540b0f6442fe27d611ff5f16ed79b4845 100644
--- a/citizen-portal/src/lib/baseModule/api/queries/gdpr.ts
+++ b/citizen-portal/src/lib/baseModule/api/queries/gdpr.ts
@@ -3,15 +3,15 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { STATIC_QUERY_OPTIONS } from "@eshg/lib-portal/api/queryOptions";
+import { PortalErrorCode } from "@eshg/lib-portal/errorHandling/PortalErrorCode";
+import { resolveError } from "@eshg/lib-portal/errorHandling/errorResolvers";
 import {
   ApiBusinessModule,
   ApiGdprDownloadPackageInfo,
   ApiGetGdprDownloadPackagesInfoResponse,
   GdprValidationTaskApiInterface,
-} from "@eshg/citizen-portal-api/businessProcedures";
-import { STATIC_QUERY_OPTIONS } from "@eshg/lib-portal/api/queryOptions";
-import { PortalErrorCode } from "@eshg/lib-portal/errorHandling/PortalErrorCode";
-import { resolveError } from "@eshg/lib-portal/errorHandling/errorResolvers";
+} from "@eshg/lib-procedures-api";
 import { queryOptions, useSuspenseQueries } from "@tanstack/react-query";
 import assert from "assert";
 import { isDefined } from "remeda";
diff --git a/citizen-portal/src/lib/baseModule/components/gdpr/GdprProcedureStatusChip.tsx b/citizen-portal/src/lib/baseModule/components/gdpr/GdprProcedureStatusChip.tsx
index c3eac31e4c41f618bb3e6b7832c4c321275cc23a..7d93d9209d401a45fb26f8263d29cb09c22c8712 100644
--- a/citizen-portal/src/lib/baseModule/components/gdpr/GdprProcedureStatusChip.tsx
+++ b/citizen-portal/src/lib/baseModule/components/gdpr/GdprProcedureStatusChip.tsx
@@ -23,7 +23,6 @@ export function GdprProcedureStatusChip({
 
 const gdprProcedureStatusColor = {
   [ApiGdprProcedureStatus.Draft]: "warning",
-  [ApiGdprProcedureStatus.Open]: "neutral",
   [ApiGdprProcedureStatus.InProgress]: "primary",
   [ApiGdprProcedureStatus.Closed]: "success",
   [ApiGdprProcedureStatus.Aborted]: "danger",
diff --git a/citizen-portal/src/lib/businessModules/measlesProtection/components/reportCase/subforms/MinimalPersonForm.tsx b/citizen-portal/src/lib/businessModules/measlesProtection/components/reportCase/subforms/MinimalPersonForm.tsx
index 726f51b3b86cd6beca4872c89dd7d1642bd80903..20854aff764402d79f03f1aab43a143b37caf234 100644
--- a/citizen-portal/src/lib/businessModules/measlesProtection/components/reportCase/subforms/MinimalPersonForm.tsx
+++ b/citizen-portal/src/lib/businessModules/measlesProtection/components/reportCase/subforms/MinimalPersonForm.tsx
@@ -8,7 +8,10 @@
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
-import { validateLength } from "@eshg/lib-portal/helpers/validators";
+import {
+  validateDateOfBirth,
+  validateLength,
+} from "@eshg/lib-portal/helpers/validators";
 import { Grid, Stack } from "@mui/joy";
 
 import {
@@ -69,6 +72,7 @@ export function MinimalPersonForm(props: Readonly<NestedFormProps>) {
             name={fieldName("dateOfBirth")}
             label={minimalPersonFormConfig.dateOfBirth.label}
             required={minimalPersonFormConfig.dateOfBirth.required}
+            validate={validateDateOfBirth}
           />
         </Grid>
       </Grid>
diff --git a/citizen-portal/src/lib/businessModules/medicalRegistry/api/clients.ts b/citizen-portal/src/lib/businessModules/medicalRegistry/api/clients.ts
index 7ec4b47153b4f52d850d3c31b33ffb18bade765a..8147327de37f08dee90764a6a5cd76e37b63bc2c 100644
--- a/citizen-portal/src/lib/businessModules/medicalRegistry/api/clients.ts
+++ b/citizen-portal/src/lib/businessModules/medicalRegistry/api/clients.ts
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
 import {
   Configuration,
   MedicalRegistryApi,
   MedicalRegistryFeatureTogglesPublicApi,
   MedicalRegistryPublicCitizenApi,
-} from "@eshg/citizen-portal-api/medicalRegistry";
-import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
+} from "@eshg/medical-registry-api";
 
 function useConfiguration() {
   const configurationParameters = useApiConfiguration(
diff --git a/citizen-portal/src/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries.ts b/citizen-portal/src/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries.ts
index 81abf68f3a7bc32caea738713e4078d385330b58..f05b51b01b1b99836664f54690bb86806da948e0 100644
--- a/citizen-portal/src/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries.ts
+++ b/citizen-portal/src/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries.ts
@@ -3,10 +3,10 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { CreateProcedureRequest } from "@eshg/citizen-portal-api/medicalRegistry/apis";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { CreateProcedureRequest } from "@eshg/medical-registry-api";
 
 import { useMedicalRegistryApi } from "@/lib/businessModules/medicalRegistry/api/clients";
 import { useTranslation } from "@/lib/i18n/client";
diff --git a/citizen-portal/src/lib/businessModules/medicalRegistry/api/queries/featureTogglesApi.ts b/citizen-portal/src/lib/businessModules/medicalRegistry/api/queries/featureTogglesApi.ts
index 0725066fb1c16fbb4473a6db934aece8a1074a8c..03e6e0af8365a44270e6e66189fb94033e3b8e2d 100644
--- a/citizen-portal/src/lib/businessModules/medicalRegistry/api/queries/featureTogglesApi.ts
+++ b/citizen-portal/src/lib/businessModules/medicalRegistry/api/queries/featureTogglesApi.ts
@@ -3,15 +3,15 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiGetMedicalRegistryFeatureTogglesResponse,
-  ApiMedicalRegistryFeature,
-} from "@eshg/citizen-portal-api/medicalRegistry";
 import {
   selectDisabledOldFeature,
   selectEnabledNewFeature,
   useGetFeatureToggle,
 } from "@eshg/lib-portal/api/featureToggles";
+import {
+  ApiGetMedicalRegistryFeatureTogglesResponse,
+  ApiMedicalRegistryFeature,
+} from "@eshg/medical-registry-api";
 
 import { useFeatureTogglesApi } from "@/lib/businessModules/medicalRegistry/api/clients";
 import { medicalRegistryFeatureTogglesPublicApiQueryKey } from "@/lib/businessModules/medicalRegistry/api/queries/apiQueryKeys";
diff --git a/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/ProfessionalRegistrationStepper.tsx b/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/ProfessionalRegistrationStepper.tsx
index 6c39ef93005c1911c2b3c16ff29714b4d726fa8c..70dd6cdb1dd9048b3e9b0e9bfd215b2708eb76c5 100644
--- a/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/ProfessionalRegistrationStepper.tsx
+++ b/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/ProfessionalRegistrationStepper.tsx
@@ -3,7 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiTypeOfChange } from "@eshg/citizen-portal-api/medicalRegistry";
 import { MedicalRegistryCreateProcedureFormValues } from "@eshg/lib-portal/businessModules/medicalRegistry/medicalRegistryCreateProcedureFormValues";
 import { shouldEnable } from "@eshg/lib-portal/businessModules/medicalRegistry/sections";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
@@ -12,6 +11,7 @@ import {
   StepFactory,
 } from "@eshg/lib-portal/components/form/MultiStepForm";
 import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+import { ApiTypeOfChange } from "@eshg/medical-registry-api";
 import { Typography } from "@mui/joy";
 import { FormikProps, useFormikContext } from "formik";
 
diff --git a/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepFour.tsx b/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepFour.tsx
index 51316bd2c0171aba8663c50280d23fd7c1095043..e93b1d900cfad880bf20224ed33d7c23c4b4c6d2 100644
--- a/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepFour.tsx
+++ b/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepFour.tsx
@@ -3,10 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiCountryCode,
-  ApiTypeOfChange,
-} from "@eshg/citizen-portal-api/medicalRegistry";
 import {
   EmployeeInformationFormValues,
   MedicalRegistryCreateProcedureFormValues,
@@ -15,6 +11,7 @@ import {
 import { shouldEnable } from "@eshg/lib-portal/businessModules/medicalRegistry/sections";
 import { FileType } from "@eshg/lib-portal/components/formFields/file/FileType";
 import { validateFile } from "@eshg/lib-portal/helpers/validators";
+import { ApiCountryCode, ApiTypeOfChange } from "@eshg/medical-registry-api";
 import { Add, DeleteOutlined } from "@mui/icons-material";
 import { Button, Grid, IconButton, Sheet, Stack, Typography } from "@mui/joy";
 import { FieldArray, useFormikContext } from "formik";
diff --git a/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepOne.tsx b/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepOne.tsx
index e55fca689174f337156166284be4b377f0c0be64..f2f4dcc9fba2ebc1b88fd185e14e7a14a51b46ab 100644
--- a/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepOne.tsx
+++ b/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepOne.tsx
@@ -3,7 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiTypeOfChange } from "@eshg/citizen-portal-api/medicalRegistry";
 import { changeTypeNames } from "@eshg/lib-portal/businessModules/medicalRegistry/constants";
 import {
   GeneralInformationFormValues,
@@ -21,6 +20,7 @@ import {
   validateLength,
   validatePastOrTodayDate,
 } from "@eshg/lib-portal/helpers/validators";
+import { ApiTypeOfChange } from "@eshg/medical-registry-api";
 import { Grid, Typography } from "@mui/joy";
 import { useFormikContext } from "formik";
 import { useMemo } from "react";
diff --git a/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepTwo.tsx b/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepTwo.tsx
index 573c8f258b770fa4e8eb5051aafd9042bfad9c68..218b9e2fb12254b4cb196873c61c6d7c650c9038 100644
--- a/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepTwo.tsx
+++ b/citizen-portal/src/lib/businessModules/medicalRegistry/pages/professionalRegistrationForm/steps/ProfessionalRegistrationFormStepTwo.tsx
@@ -3,11 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiEmploymentStatus,
-  ApiEmploymentType,
-  ApiTypeOfChange,
-} from "@eshg/citizen-portal-api/medicalRegistry";
 import { professionalTitleNames } from "@eshg/lib-portal/businessModules/medicalRegistry/constants";
 import {
   MedicalRegistryCreateProcedureFormValues,
@@ -24,6 +19,11 @@ import {
   validateLength,
   validatePastOrTodayDate,
 } from "@eshg/lib-portal/helpers/validators";
+import {
+  ApiEmploymentStatus,
+  ApiEmploymentType,
+  ApiTypeOfChange,
+} from "@eshg/medical-registry-api";
 import { Grid, Radio, Typography } from "@mui/joy";
 import { useFormikContext } from "formik";
 import { useMemo } from "react";
diff --git a/citizen-portal/src/lib/businessModules/medicalRegistry/shared/navigationItems.tsx b/citizen-portal/src/lib/businessModules/medicalRegistry/shared/navigationItems.tsx
index 6c0c7d54ef96c6ce320efb01a5590eb58d1eab04..14438f1f3c62a758c30d7ed72cd3941e8ad54fab 100644
--- a/citizen-portal/src/lib/businessModules/medicalRegistry/shared/navigationItems.tsx
+++ b/citizen-portal/src/lib/businessModules/medicalRegistry/shared/navigationItems.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiMedicalRegistryFeature } from "@eshg/citizen-portal-api/medicalRegistry";
+import { ApiMedicalRegistryFeature } from "@eshg/medical-registry-api";
 import { StickyNote2Outlined } from "@mui/icons-material";
 
 import { NavigationItem } from "@/lib/baseModule/components/layout/types";
diff --git a/citizen-portal/src/lib/businessModules/officialMedicalService/api/clients.ts b/citizen-portal/src/lib/businessModules/officialMedicalService/api/clients.ts
index eaf67b8aa8f96ae32d25cac81649c6a157ddcab1..256dec1fadf1d5836279704912b7e2c3e0c71851 100644
--- a/citizen-portal/src/lib/businessModules/officialMedicalService/api/clients.ts
+++ b/citizen-portal/src/lib/businessModules/officialMedicalService/api/clients.ts
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
 import {
   CitizenPublicApi,
   Configuration,
-} from "@eshg/citizen-portal-api/officialMedicalService";
-import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
+} from "@eshg/official-medical-service-api";
 
 function useConfiguration() {
   const configurationParameters = useApiConfiguration(
diff --git a/citizen-portal/src/lib/businessModules/opendata/api/clients.ts b/citizen-portal/src/lib/businessModules/opendata/api/clients.ts
index 4a7bb309afaeb2585129cec7e5a4187f01106528..e81b19d19f83a7a6c6202978ef3f010307314509 100644
--- a/citizen-portal/src/lib/businessModules/opendata/api/clients.ts
+++ b/citizen-portal/src/lib/businessModules/opendata/api/clients.ts
@@ -3,11 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  Configuration,
-  OpenDataPublicCitizenApi,
-} from "@eshg/citizen-portal-api/openData";
 import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
+import { Configuration, OpenDataPublicCitizenApi } from "@eshg/opendata-api";
 
 function useConfiguration() {
   const configurationParameters = useApiConfiguration(
diff --git a/citizen-portal/src/lib/businessModules/opendata/api/queries/citizenPublicApi.ts b/citizen-portal/src/lib/businessModules/opendata/api/queries/citizenPublicApi.ts
index 594b01fe2b29442d0d986e681d6855fe6926f607..3ffd06619bc24280cf18873b55f5d2b48913a86d 100644
--- a/citizen-portal/src/lib/businessModules/opendata/api/queries/citizenPublicApi.ts
+++ b/citizen-portal/src/lib/businessModules/opendata/api/queries/citizenPublicApi.ts
@@ -3,20 +3,43 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { GetOpenDocuments1Request } from "@eshg/citizen-portal-api/openData";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
-import { useSuspenseQuery } from "@tanstack/react-query";
+import {
+  ApiGetOpenDocumentsResponse,
+  ApiVersion,
+  GetOpenDocuments1Request,
+} from "@eshg/opendata-api";
+import {
+  InfiniteData,
+  useInfiniteQuery,
+  useSuspenseQuery,
+} from "@tanstack/react-query";
 
 import { useOpenDataPublicCitizenApi } from "@/lib/businessModules/opendata/api/clients";
 import { publicCitizenApiQueryKey } from "@/lib/businessModules/opendata/api/queries/apiQueryKeys";
 
-export function useGetOpenDocuments(request: GetOpenDocuments1Request) {
+interface GetOpenDataOverviewResponse {
+  versions: ApiVersion[];
+  totalElements: number;
+  totalPages: number;
+}
+
+export function useGetOpenDocuments(
+  request: Omit<GetOpenDocuments1Request, "pageNumber">,
+) {
   const openDataApi = useOpenDataPublicCitizenApi();
 
-  return useSuspenseQuery({
+  return useInfiniteQuery({
     queryKey: publicCitizenApiQueryKey(["getOpenDocuments1Raw", request]),
-    queryFn: () =>
-      openDataApi.getOpenDocuments1Raw(request).then(unwrapRawResponse),
+    queryFn: ({ pageParam }) =>
+      openDataApi
+        .getOpenDocuments1Raw({ ...request, pageNumber: pageParam })
+        .then(unwrapRawResponse),
+    initialPageParam: 0,
+    getNextPageParam: (lastPage, pages) => {
+      return pages.length < lastPage.totalPages ? pages.length : null;
+    },
+    select: mapToOpenDataOverview,
   });
 }
 
@@ -28,3 +51,16 @@ export function useGetVersion(versionId: string) {
     queryFn: () => openDataApi.getVersion1(versionId),
   });
 }
+
+export function mapToOpenDataOverview(
+  data: InfiniteData<ApiGetOpenDocumentsResponse, number>,
+) {
+  return {
+    versions:
+      data.pages
+        .flatMap((page) => page.elements)
+        .flatMap(({ versions }) => versions) ?? [],
+    totalElements: data.pages[0]?.totalElements ?? 0,
+    totalPages: data.pages[0]?.totalPages ?? 0,
+  } satisfies GetOpenDataOverviewResponse;
+}
diff --git a/citizen-portal/src/lib/businessModules/opendata/components/OpenDataDetailsContent.tsx b/citizen-portal/src/lib/businessModules/opendata/components/OpenDataDetailsContent.tsx
index cb36a0002e42fb49d0b22ee6a55c4222a7dca1cc..23cf3026a226e07592e2d762a080b3b1954b3db7 100644
--- a/citizen-portal/src/lib/businessModules/opendata/components/OpenDataDetailsContent.tsx
+++ b/citizen-portal/src/lib/businessModules/opendata/components/OpenDataDetailsContent.tsx
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiVersion } from "@eshg/citizen-portal-api/openData";
 import { useFileDownload } from "@eshg/lib-portal/api/files/download";
 import { ExternalLink } from "@eshg/lib-portal/components/navigation/ExternalLink";
 import { InternalLink } from "@eshg/lib-portal/components/navigation/InternalLink";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { formatFileSize } from "@eshg/lib-portal/helpers/file";
 import { RequiresChildren } from "@eshg/lib-portal/types/react";
+import { ApiVersion } from "@eshg/opendata-api";
 import { DownloadOutlined, FileCopyOutlined } from "@mui/icons-material";
 import { Button, Card, Chip, Stack, Typography } from "@mui/joy";
 import { visuallyHidden } from "@mui/utils";
diff --git a/citizen-portal/src/lib/businessModules/opendata/components/OpenDataFilters.tsx b/citizen-portal/src/lib/businessModules/opendata/components/OpenDataFilters.tsx
index 768552474818aa6c8b8bde75c8435a0ca111d94d..dad4a546ce8f1e78690a1a229cf33dbd95c9ee58 100644
--- a/citizen-portal/src/lib/businessModules/opendata/components/OpenDataFilters.tsx
+++ b/citizen-portal/src/lib/businessModules/opendata/components/OpenDataFilters.tsx
@@ -3,7 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiBusinessModule } from "@eshg/citizen-portal-api/openData";
 import { ButtonLink } from "@eshg/lib-portal/components/buttons/ButtonLink";
 import {
   SelectOptions,
@@ -11,6 +10,7 @@ import {
 } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import { YearInput } from "@eshg/lib-portal/components/inputs/YearInput";
 import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
+import { ApiBusinessModule } from "@eshg/opendata-api";
 import {
   CloseOutlined,
   DateRangeOutlined,
diff --git a/citizen-portal/src/lib/businessModules/opendata/components/OpenDataOverviewContent.tsx b/citizen-portal/src/lib/businessModules/opendata/components/OpenDataOverviewContent.tsx
index c36eef00503af101914e594e2188a61b8bcd0202..598c6fb22695b6dba1fc31fd2b3ea50237ca438c 100644
--- a/citizen-portal/src/lib/businessModules/opendata/components/OpenDataOverviewContent.tsx
+++ b/citizen-portal/src/lib/businessModules/opendata/components/OpenDataOverviewContent.tsx
@@ -3,24 +3,30 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiVersion } from "@eshg/citizen-portal-api/openData";
 import { InternalLink } from "@eshg/lib-portal/components/navigation/InternalLink";
-import { parseOptionalNonNegativeInt } from "@eshg/lib-portal/helpers/searchParams";
-import { ChevronRightOutlined } from "@mui/icons-material";
-import { Card, CardContent, List, ListItem, Stack, Typography } from "@mui/joy";
-import { useSearchParams } from "next/navigation";
-import { isEmpty } from "remeda";
+import { ApiVersion } from "@eshg/opendata-api";
+import { ChevronRightOutlined, RefreshOutlined } from "@mui/icons-material";
+import {
+  Button,
+  Card,
+  CardContent,
+  List,
+  ListItem,
+  Stack,
+  Typography,
+} from "@mui/joy";
+import { startTransition } from "react";
+import { Trans } from "react-i18next";
+import { isDefined, isEmpty } from "remeda";
 
 import { theme } from "@/lib/baseModule/theme/theme";
 import { useGetOpenDocuments } from "@/lib/businessModules/opendata/api/queries/citizenPublicApi";
 import { OpenDataFilters } from "@/lib/businessModules/opendata/components/OpenDataFilters";
-import { SEARCH_PARAMS } from "@/lib/businessModules/opendata/components/helpers";
 import { useOpenDataFilterValues } from "@/lib/businessModules/opendata/components/useOpenDataFilterValues";
 import { fileTypeNames } from "@/lib/businessModules/opendata/shared/constants";
 import { useCitizenRoutes } from "@/lib/businessModules/opendata/shared/routes";
 import { useTranslation } from "@/lib/i18n/client";
 import { MobileBreakpoint, byBreakpoint } from "@/lib/shared/breakpoints";
-import { Pagination } from "@/lib/shared/components/Pagination";
 import { PageContent } from "@/lib/shared/components/layout/PageContent";
 import {
   ContentSheet,
@@ -28,7 +34,6 @@ import {
 } from "@/lib/shared/components/layout/contentSheet";
 import { GridColumnStack } from "@/lib/shared/components/layout/grid";
 import { PageTitle } from "@/lib/shared/components/layout/page";
-import { useReplaceSearchParams } from "@/lib/shared/hooks/searchParams/useReplaceSearchParams";
 import { useIsMobile } from "@/lib/shared/hooks/useIsMobile";
 
 const PAGE_SIZE = 10;
@@ -37,20 +42,14 @@ export function OpenDataOverviewContent() {
   const { t } = useTranslation(["opendata/overview"]);
   const isMobile = useIsMobile();
 
-  const { pageNumber, setPageNumber } = usePagination();
-
   const filterValues = useOpenDataFilterValues();
-  const {
-    data: { totalElements, elements },
-  } = useGetOpenDocuments({
-    pageNumber,
+  const { data, fetchNextPage, hasNextPage, isFetching } = useGetOpenDocuments({
     pageSize: PAGE_SIZE,
     searchString: filterValues.search,
     sourcesFilter: filterValues.topic,
     fileTypeFilter: filterValues.fileType,
     statisticsYearFilter: filterValues.year,
   });
-  const versions = elements.flatMap(({ versions }) => versions);
 
   return (
     <PageContent>
@@ -70,30 +69,55 @@ export function OpenDataOverviewContent() {
             </Stack>
           )}
           <Typography level="h3" sx={{ marginTop: 1 }}>
-            {totalElements === 1
-              ? t("resultSection.foundSingular", { totalElements })
-              : t("resultSection.foundPlural", { totalElements })}
+            {t("resultSection.found", {
+              count: data?.totalElements ?? 0,
+            })}
           </Typography>
 
-          <List
-            sx={{ padding: 0, gap: "inherit" }}
-            aria-label={t("resultSection.results")}
-          >
-            {versions.map((version) => (
-              <ListItem key={version.externalId} sx={{ padding: 0 }}>
-                <OpenDataCard version={version} />
-              </ListItem>
-            ))}
-          </List>
-
-          {/* TODO: ISSUE-7233: replace pagination with "Show more" button  */}
-          {totalElements > PAGE_SIZE && (
-            <Pagination
-              totalCount={totalElements}
-              pageSize={PAGE_SIZE}
-              pageNumber={pageNumber}
-              onPageChange={setPageNumber}
-            />
+          {isDefined(data) && (
+            <>
+              <List
+                sx={{ padding: 0, gap: "inherit" }}
+                aria-label={t("resultSection.results")}
+              >
+                {data.versions.map((version) => (
+                  <ListItem key={version.externalId} sx={{ padding: 0 }}>
+                    <OpenDataCard version={version} />
+                  </ListItem>
+                ))}
+              </List>
+
+              <Stack gap={2} alignItems="center">
+                {hasNextPage && (
+                  <Button
+                    loading={isFetching}
+                    variant="soft"
+                    endDecorator={<RefreshOutlined />}
+                    sx={{ margin: "auto" }}
+                    onClick={() => {
+                      startTransition(async () => {
+                        await fetchNextPage();
+                      });
+                    }}
+                  >
+                    {t("pagination.loadMore")}
+                  </Button>
+                )}
+                <Typography
+                  sx={{
+                    color: (theme) => theme.palette.text.primary,
+                  }}
+                >
+                  <Trans
+                    i18nKey="opendata/overview:pagination.shown"
+                    count={data.totalElements}
+                    values={{
+                      shownElements: data.versions.length,
+                    }}
+                  ></Trans>
+                </Typography>
+              </Stack>
+            </>
           )}
         </ContentSheet>
       </GridColumnStack>
@@ -154,19 +178,3 @@ function OpenDataCard({ version }: { version: ApiVersion }) {
     </Card>
   );
 }
-
-function usePagination() {
-  const searchParams = useSearchParams();
-  const replaceSearchParams = useReplaceSearchParams();
-  const pageNumber =
-    parseOptionalNonNegativeInt(searchParams.get(SEARCH_PARAMS.pageNumber)) ??
-    0;
-
-  function setPageNumber(newPageNumber: number) {
-    replaceSearchParams([
-      { name: SEARCH_PARAMS.pageNumber, value: newPageNumber },
-    ]);
-  }
-
-  return { pageNumber, setPageNumber };
-}
diff --git a/citizen-portal/src/lib/businessModules/opendata/components/useOpenDataFilterValues.ts b/citizen-portal/src/lib/businessModules/opendata/components/useOpenDataFilterValues.ts
index 8fbb279d1ea3cbc71d0f9a03c8c25f600a756ef3..d9a2ec972f77a013bc41cdf8fabd9bda0f711a7f 100644
--- a/citizen-portal/src/lib/businessModules/opendata/components/useOpenDataFilterValues.ts
+++ b/citizen-portal/src/lib/businessModules/opendata/components/useOpenDataFilterValues.ts
@@ -4,8 +4,8 @@
  */
 
 import { ApiBusinessModule } from "@eshg/base-api";
-import { ApiOpenDataFileType } from "@eshg/citizen-portal-api/openData";
 import { parseOptionalEnum } from "@eshg/lib-portal/helpers/searchParams";
+import { ApiOpenDataFileType } from "@eshg/opendata-api";
 import { useSearchParams } from "next/navigation";
 import { isNonNullish } from "remeda";
 
diff --git a/citizen-portal/src/lib/businessModules/opendata/locales/de/overview.json b/citizen-portal/src/lib/businessModules/opendata/locales/de/overview.json
index f11a5501bb7c772325a1e41f5f209c67a97e39a2..65985438d6e399c12066c6c17db5ba90cfda4d53 100644
--- a/citizen-portal/src/lib/businessModules/opendata/locales/de/overview.json
+++ b/citizen-portal/src/lib/businessModules/opendata/locales/de/overview.json
@@ -16,8 +16,13 @@
   },
   "resultSection": {
     "results": "Ergebnisse",
-    "foundSingular": "{{totalElements}} Ergebnis gefunden",
-    "foundPlural": "{{totalElements}} Ergebnisse gefunden",
+    "found_one": "{{count}} Ergebnis gefunden",
+    "found_other": "{{count}} Ergebnisse gefunden",
     "version": "Version"
+  },
+  "pagination": {
+    "loadMore": "Mehr anzeigen",
+    "shown_one": "<strong>{{shownElements}}</strong> von <strong>{{count}}</strong> Ergebnis werden angezeigt",
+    "shown_other": "<strong>{{shownElements}}</strong> von <strong>{{count}}</strong> Ergebnissen werden angezeigt"
   }
 }
diff --git a/citizen-portal/src/lib/businessModules/opendata/locales/en/overview.json b/citizen-portal/src/lib/businessModules/opendata/locales/en/overview.json
index 399ff6eb93ffe099125768b2902e217e95552fa3..bf06e5247c06487d0dad6f5a04f6e568ba061628 100644
--- a/citizen-portal/src/lib/businessModules/opendata/locales/en/overview.json
+++ b/citizen-portal/src/lib/businessModules/opendata/locales/en/overview.json
@@ -16,8 +16,13 @@
   },
   "resultSection": {
     "results": "Results",
-    "foundSingular": "{{totalElements}} result found",
-    "foundPlural": "{{totalElements}} results found",
+    "found_one": "{{count}} result found",
+    "found_other": "{{count}} results found",
     "version": "Version"
+  },
+  "pagination": {
+    "loadMore": "Show more",
+    "shown_one": "<strong>{{shownElements}}</strong> of <strong>{{count}}</strong> result is shown",
+    "shown_other": "<strong>{{shownElements}}</strong> of <strong>{{count}}</strong> results are shown"
   }
 }
diff --git a/citizen-portal/src/lib/businessModules/opendata/shared/constants.ts b/citizen-portal/src/lib/businessModules/opendata/shared/constants.ts
index 52f18995648b271ddebffc036917f3b6a266bf22..e257dac50a160e2476811b264c9216aad0b54c61 100644
--- a/citizen-portal/src/lib/businessModules/opendata/shared/constants.ts
+++ b/citizen-portal/src/lib/businessModules/opendata/shared/constants.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiOpenDataFileType } from "@eshg/citizen-portal-api/openData";
+import { ApiOpenDataFileType } from "@eshg/opendata-api";
 
 export const fileTypeNames = {
   [ApiOpenDataFileType.Csv]: "CSV",
diff --git a/citizen-portal/src/lib/shared/api/clients.ts b/citizen-portal/src/lib/shared/api/clients.ts
index 3ba677568c711db02b68c90b334e8d1e7d84aa9f..8e413fa982f20cdf44dc7edbc0cb6f9be5c9b0b1 100644
--- a/citizen-portal/src/lib/shared/api/clients.ts
+++ b/citizen-portal/src/lib/shared/api/clients.ts
@@ -4,16 +4,16 @@
  */
 
 import { Configuration, DepartmentApi, PublicConfigApi } from "@eshg/base-api";
+import {
+  ApiConfiguration,
+  useApiConfiguration,
+} from "@eshg/lib-portal/api/ApiProvider";
 import {
   ApiBusinessModule,
   Configuration as BusinessModuleConfiguration,
   ConfigurationParameters,
   GdprValidationTaskApi,
-} from "@eshg/citizen-portal-api/businessProcedures";
-import {
-  ApiConfiguration,
-  useApiConfiguration,
-} from "@eshg/lib-portal/api/ApiProvider";
+} from "@eshg/lib-procedures-api";
 
 export const BUSINESS_MODULE_URLS = {
   [ApiBusinessModule.SchoolEntry]: "PUBLIC_SCHOOL_ENTRY_BACKEND_URL",
diff --git a/config/eslint.next.js b/config/eslint.next.js
index 33d2aa2b578f63655d49771cde63c2200709e41d..6c9543b88f5a3d9e1956e38e8677b1c9828f98ce 100644
--- a/config/eslint.next.js
+++ b/config/eslint.next.js
@@ -95,6 +95,11 @@ function noRestrictedImportsRuleOptions(packageType) {
         importNames: ["Form"],
         message: "Use 'FormPlus' from '@eshg/lib-portal' instead.",
       },
+      {
+        name: "zustand/middleware",
+        importNames: ["devtools"],
+        message: "Remove before committing.",
+      },
     ],
   };
 }
diff --git a/config/vitest.base.ts b/config/vitest.base.ts
index 87257ace1634f62707a473c8c6c2623eaf8cd970..f445badb922e7d209dfcc43b93c2facdf06cbbf2 100644
--- a/config/vitest.base.ts
+++ b/config/vitest.base.ts
@@ -8,7 +8,7 @@ import tsconfigPaths from "vite-tsconfig-paths";
 import { UserConfigExport, configDefaults } from "vitest/config";
 
 export const VITEST_OUT_DIR = "./build/vitest";
-export const VITEST_COVERAGE_EXCLUDES = ["**/*.tsx", "**/*.d.ts"];
+export const VITEST_COVERAGE_EXCLUDES = ["**/*.d.ts"];
 
 // https://vitejs.dev/config/
 export const VITEST_BASE_CONFIG: UserConfigExport = {
@@ -16,14 +16,15 @@ export const VITEST_BASE_CONFIG: UserConfigExport = {
   test: {
     exclude: configDefaults.exclude,
     environment: "node",
-    reporters: ["basic"],
+    reporters: ["default"],
     globals: true,
     coverage: {
       provider: "istanbul",
       all: true,
       reportsDirectory: `${VITEST_OUT_DIR}/coverage`,
-      reporter: ["html","lcov"],
+      reporter: ["html", "lcov"],
       include: ["src/**/*"],
       exclude: VITEST_COVERAGE_EXCLUDES,
-    },}
+    },
+  },
 };
diff --git a/docs/frontend.adoc b/docs/frontend.adoc
index 50ca1ba4ce897b13090e64d0c65bbc3dc6281c87..f6a7f80d5c1b118647b656418e83ebe102bbeb3f 100644
--- a/docs/frontend.adoc
+++ b/docs/frontend.adoc
@@ -58,8 +58,9 @@ The Lib Portal serves as shared library for components that can be used in all s
 
 === Api Clients
 
-The portal applications depend on generated api clients for fetching data from the backend services.
-For example, the `employee-portal-api` folder contains a module that generates all needed api clients for the `employee-portal` from OpenApi specifications. The api clients are automatically generated when starting the application.
+The portal applications and business module library packages depend on generated api clients for fetching data from the backend services.
+For example, the `packages/dental-api` folder contains a module that generates the api client for the `packages/dental` package from a OpenAPI specification.
+The api clients are automatically generated when starting the application (or running any other gradle task depending on them).
 
 === Naming Convention
 
diff --git a/employee-portal-api/.gitignore b/employee-portal-api/.gitignore
deleted file mode 100644
index 39f8bdd3b0bff4ce3f1319012653f59f5b97b6c4..0000000000000000000000000000000000000000
--- a/employee-portal-api/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-src/**
diff --git a/employee-portal-api/build.gradle b/employee-portal-api/build.gradle
deleted file mode 100644
index 7d45fc5d0ccd49ff650904b8416dea766768c76a..0000000000000000000000000000000000000000
--- a/employee-portal-api/build.gradle
+++ /dev/null
@@ -1,20 +0,0 @@
-plugins {
-  id 'openapi-generator'
-}
-
-def backendDir = rootProject.layout.projectDirectory.dir('backend')
-
-openapiGenerator {
-  inputSpecs = [
-    'auditlog'              : backendDir.file('auditlog/openApi.json'),
-    'businessProcedures'    : backendDir.file('lib-procedures/openApi.json'),
-    'libEditor'             : backendDir.file('lib-editor/openApi.json'),
-    'libStatistics'         : backendDir.file('lib-statistics/openApi.json'),
-    'inspection'            : backendDir.file('inspection/openApi.json'),
-    'opendata'              : backendDir.file('opendata/openApi.json'),
-    'chatManagement'        : backendDir.file('chat-management/openApi.json'),
-    'stiProtection'         : backendDir.file('sti-protection/openApi.json'),
-    'medicalRegistry'       : backendDir.file('medical-registry/openApi.json'),
-    'officialMedicalService': backendDir.file('official-medical-service/openApi.json')
-  ]
-}
diff --git a/employee-portal-api/package.json b/employee-portal-api/package.json
deleted file mode 100644
index 78f2b564dfbb1840ee30ce3e5b69a923ff3023e6..0000000000000000000000000000000000000000
--- a/employee-portal-api/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "name": "@eshg/employee-portal-api",
-  "version": "0.0.1",
-  "type": "module",
-  "private": true,
-  "exports": {
-    "./*": "./build/dist/src/*/index.js"
-  }
-}
diff --git a/employee-portal-api/tsconfig.json b/employee-portal-api/tsconfig.json
deleted file mode 100644
index f3bf745a5f0f3fbae682f4146c44713edda84dcd..0000000000000000000000000000000000000000
--- a/employee-portal-api/tsconfig.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "extends": "../config/tsconfig.lib-legacy.json"
-}
diff --git a/employee-portal/gradleDependencies.json b/employee-portal/gradleDependencies.json
index 0d59661c671176c26e408610dfae5579e9ead6d9..7bc579885c823be0a2c71509e86beef500d02567 100644
--- a/employee-portal/gradleDependencies.json
+++ b/employee-portal/gradleDependencies.json
@@ -1,14 +1,23 @@
 {
   "dependencies": [
+    ":auditlog-api",
     ":base-api",
+    ":chat-management-api",
     ":dental",
     ":dental-api",
-    ":employee-portal-api",
+    ":inspection-api",
+    ":lib-editor-api",
     ":lib-employee-portal",
     ":lib-portal",
+    ":lib-procedures-api",
+    ":lib-statistics-api",
     ":measles-protection-api",
+    ":medical-registry-api",
+    ":official-medical-service-api",
+    ":opendata-api",
     ":school-entry-api",
     ":statistics-api",
+    ":sti-protection-api",
     ":travel-medicine-api"
   ]
 }
diff --git a/employee-portal/package.json b/employee-portal/package.json
index 0a36af8f42dade7040e8fc7747758c33781930ce..780032375904543ded5de4b40bfe3eff3e6cb36d 100644
--- a/employee-portal/package.json
+++ b/employee-portal/package.json
@@ -7,15 +7,24 @@
     "@ducanh2912/next-pwa": "10.2.9",
     "@emotion/react": "catalog:joy",
     "@emotion/styled": "catalog:joy",
+    "@eshg/auditlog-api": "workspace:*",
     "@eshg/base-api": "workspace:*",
+    "@eshg/chat-management-api": "workspace:*",
     "@eshg/dental": "workspace:*",
     "@eshg/dental-api": "workspace:*",
-    "@eshg/employee-portal-api": "workspace:*",
+    "@eshg/inspection-api": "workspace:*",
+    "@eshg/lib-editor-api": "workspace:*",
     "@eshg/lib-employee-portal": "workspace:*",
     "@eshg/lib-portal": "workspace:*",
+    "@eshg/lib-procedures-api": "workspace:*",
+    "@eshg/lib-statistics-api": "workspace:*",
     "@eshg/measles-protection-api": "workspace:*",
+    "@eshg/medical-registry-api": "workspace:*",
+    "@eshg/official-medical-service-api": "workspace:*",
+    "@eshg/opendata-api": "workspace:*",
     "@eshg/school-entry-api": "workspace:*",
     "@eshg/statistics-api": "workspace:*",
+    "@eshg/sti-protection-api": "workspace:*",
     "@eshg/travel-medicine-api": "workspace:*",
     "@fontsource/poppins": "catalog:joy",
     "@fontsource/source-code-pro": "catalog:joy",
diff --git a/employee-portal/src/app/(baseModule)/gdpr/validation-tasks/[businessModule]/overview/page.tsx b/employee-portal/src/app/(baseModule)/gdpr/validation-tasks/[businessModule]/overview/page.tsx
index d2fd223dd13240923325cdd7b1a3ec80bff0e083..f96fbb7c2b37e68f8aa53716a49e55393ff3ccf0 100644
--- a/employee-portal/src/app/(baseModule)/gdpr/validation-tasks/[businessModule]/overview/page.tsx
+++ b/employee-portal/src/app/(baseModule)/gdpr/validation-tasks/[businessModule]/overview/page.tsx
@@ -5,15 +5,15 @@
 
 "use client";
 
-import {
-  ApiGdprValidationTaskSortKey,
-  ApiSortDirection,
-  GetAllGdprValidationTasksRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
 import {
   parseOptionalEnum,
   parseReadonlyPageParams,
 } from "@eshg/lib-portal/helpers/searchParams";
+import {
+  ApiGdprValidationTaskSortKey,
+  ApiSortDirection,
+  GetAllGdprValidationTasksRequest,
+} from "@eshg/lib-procedures-api";
 import { ReadonlyURLSearchParams, useSearchParams } from "next/navigation";
 
 import { ValidationTasksTable } from "@/lib/baseModule/components/gdpr/validationTasks/ValidationTasksTable";
diff --git a/employee-portal/src/app/(baseModule)/inbox-procedures/page.tsx b/employee-portal/src/app/(baseModule)/inbox-procedures/page.tsx
index f9d8d67511d081b6eb8418b28f04eb7c3f6602c3..1c67c4c5c007642e2f4af2b14b8a69879a4741eb 100644
--- a/employee-portal/src/app/(baseModule)/inbox-procedures/page.tsx
+++ b/employee-portal/src/app/(baseModule)/inbox-procedures/page.tsx
@@ -6,7 +6,7 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiInboxProcedure } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiInboxProcedure } from "@eshg/lib-procedures-api";
 import { useState } from "react";
 
 import { useCreateInboxProcedure } from "@/lib/baseModule/api/mutations/inboxProcedures";
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/inspection/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/inspection/page.tsx
index 8994c177de0e0a4d376ffd5a110ba39cec9298c8..a0f805067602d958e6c4f8a6fc3da6355e0716fa 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/inspection/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/inspection/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import {
   useBulkUpdateProceduresArchivingRelevance,
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/measles-protection/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/measles-protection/page.tsx
index 2175e03cb4c57e5afd9b504f276b1e241b0a470d..b2b9f101e66a5bffcd9d5bf286334eae326c9f5e 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/measles-protection/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/measles-protection/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import {
   useBulkUpdateProceduresArchivingRelevance,
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/medical-registry/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/medical-registry/page.tsx
index 76c64936a8d184ae667affcf90aca4887cc6ff0a..49520a800a6286b582f7130e33e67edc98b3bb41 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/medical-registry/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/medical-registry/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import {
   useBulkUpdateProceduresArchivingRelevance,
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/school-entry/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/school-entry/page.tsx
index 19f27a6339061955ca73266fd5d5b42b5f8d1e67..0a26e7c6aae35675f9b382d30e88e9902b002957 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/school-entry/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/school-entry/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import {
   useBulkUpdateProceduresArchivingRelevance,
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/sti-protection/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/sti-protection/page.tsx
index c425118a255d10e9fe432421e117fadc54f623ba..edba4a6130684577e38d35d9795bd0f787e3635a 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/sti-protection/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/sti-protection/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import {
   useBulkUpdateProceduresArchivingRelevance,
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/travel-medicine/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/travel-medicine/page.tsx
index 776c1273b262e44efc60cfc90c7a60d09be6cd30..690273526a775e7ffbda508c65b8aa7cd80dbcc7 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/travel-medicine/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving-admin/travel-medicine/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import {
   useBulkUpdateProceduresArchivingRelevance,
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving/inspection/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving/inspection/page.tsx
index 8b2de4d075403c8782d34d0f99f56a43bffa464a..03832b2fcc85ea09ad93ea5640f455e03bd21ae8 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving/inspection/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving/inspection/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import { useBulkUpdateProceduresArchivingRelevance } from "@/lib/businessModules/inspection/api/mutations/archiving";
 import {
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving/measles-protection/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving/measles-protection/page.tsx
index 92a3ec5a99f7faa34c8ac304d99756122774f5fe..dce64cd80bafcd77fdcdf0a6a28845069b4dda9e 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving/measles-protection/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving/measles-protection/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import { useBulkUpdateProceduresArchivingRelevance } from "@/lib/businessModules/measlesProtection/api/mutations/archiving";
 import {
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving/medical-registry/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving/medical-registry/page.tsx
index 2b107cb112f1c8575198f33e160e8fa71acbf16d..a70f5c6ef534ed43365c33b651772167abdb0e6e 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving/medical-registry/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving/medical-registry/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import { useBulkUpdateProceduresArchivingRelevance } from "@/lib/businessModules/medicalRegistry/api/mutations/archiving";
 import {
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving/school-entry/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving/school-entry/page.tsx
index e88d46b0f967f0db822ed44c4f251459c23c7312..b8e01743f065ed49dfb4f1e323c6749c52bd500d 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving/school-entry/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving/school-entry/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import { useBulkUpdateProceduresArchivingRelevance } from "@/lib/businessModules/schoolEntry/api/mutations/archiving";
 import {
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving/sti-protection/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving/sti-protection/page.tsx
index 152f5097c50fb92795fa4e5a929f4b16f387291b..ffdeb8268625acb47f1c7e2b895178f08a1c6612 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving/sti-protection/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving/sti-protection/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import { useBulkUpdateProceduresArchivingRelevance } from "@/lib/businessModules/stiProtection/api/mutations/archiving";
 import {
diff --git a/employee-portal/src/app/(businessModules)/(archiving)/archiving/travel-medicine/page.tsx b/employee-portal/src/app/(businessModules)/(archiving)/archiving/travel-medicine/page.tsx
index f0a2f3570e64073e16cd89899e7887cfa08eef92..32b7510f623bf72c23b59dacc91b883c6a2ddfdd 100644
--- a/employee-portal/src/app/(businessModules)/(archiving)/archiving/travel-medicine/page.tsx
+++ b/employee-portal/src/app/(businessModules)/(archiving)/archiving/travel-medicine/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 import { useBulkUpdateProceduresArchivingRelevance } from "@/lib/businessModules/travelMedicine/api/mutations/archiving";
 import {
diff --git a/employee-portal/src/app/(businessModules)/dental/children/[childId]/examinations/[examinationId]/page.tsx b/employee-portal/src/app/(businessModules)/dental/children/[childId]/examinations/[examinationId]/page.tsx
index f776e4accead3fd0b30401414155d586f740c353..b791d0bab9739e7fa67839d9c64e99053f94fb19 100644
--- a/employee-portal/src/app/(businessModules)/dental/children/[childId]/examinations/[examinationId]/page.tsx
+++ b/employee-portal/src/app/(businessModules)/dental/children/[childId]/examinations/[examinationId]/page.tsx
@@ -5,29 +5,17 @@
 
 "use client";
 
-import {
-  ApiExaminationResult,
-  UpdateExaminationRequest,
-} from "@eshg/dental-api";
-import { Examination } from "@eshg/dental/api/models/Examination";
-import { useUpdateExamination } from "@eshg/dental/api/mutations/childApi";
 import { getExaminationQuery } from "@eshg/dental/api/queries/childApi";
 import { useDentalApi } from "@eshg/dental/shared/DentalProvider";
-import {
-  mapOptionalValue,
-  mapRequiredValue,
-} from "@eshg/lib-portal/helpers/form";
 import { useSuspenseQuery } from "@tanstack/react-query";
 
 import { DentalChildPageProps } from "@/app/(businessModules)/dental/children/[childId]/layout";
 import { ChildExaminationForm } from "@/lib/businessModules/dental/features/children/details/ChildExaminationForm";
 import { AdditionalInformationFormSection } from "@/lib/businessModules/dental/features/examinations/AdditionalInformationFormSection";
-import {
-  ExaminationFormLayout,
-  ExaminationFormValues,
-  mapToExaminationFormValues,
-} from "@/lib/businessModules/dental/features/examinations/ExaminationFormLayout";
+import { ExaminationFormLayout } from "@/lib/businessModules/dental/features/examinations/ExaminationFormLayout";
 import { NoteFormSection } from "@/lib/businessModules/dental/features/examinations/NoteFormSection";
+import { DentalExaminationFormSection } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationFormSection";
+import { DentalExaminationStoreProvider } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
 
 export default function ExaminationDetailsPage(props: DentalChildPageProps) {
   const { childApi } = useDentalApi();
@@ -35,73 +23,25 @@ export default function ExaminationDetailsPage(props: DentalChildPageProps) {
   const { data: examination } = useSuspenseQuery(
     getExaminationQuery(childApi, examinationId),
   );
-  const updateExamination = useUpdateExamination(examinationId);
-
-  async function handleSubmit(values: ExaminationFormValues) {
-    await updateExamination.mutateAsync(
-      mapToRequest(examination, values, examination.version),
-    );
-  }
 
   return (
-    <ChildExaminationForm
-      initialValues={mapToExaminationFormValues(
-        examination.result,
-        examination.note,
-      )}
-      onSubmit={handleSubmit}
-    >
-      <ExaminationFormLayout
-        additionalInformation={
-          <AdditionalInformationFormSection
-            screening={examination.screening}
-            fluoridation={examination.fluoridation}
-            fluoridationConsentGiven={examination.fluoridationConsentGiven}
-          />
-        }
-        note={<NoteFormSection />}
-      />
-    </ChildExaminationForm>
+    <DentalExaminationStoreProvider examinationResult={examination.result}>
+      <ChildExaminationForm examination={examination}>
+        <ExaminationFormLayout
+          additionalInformation={
+            <AdditionalInformationFormSection
+              screening={examination.screening}
+              fluoridation={examination.fluoridation}
+              fluoridationConsentGiven={examination.fluoridationConsentGiven}
+              status={examination.status}
+            />
+          }
+          dentalExamination={
+            examination.screening ? <DentalExaminationFormSection /> : undefined
+          }
+          note={<NoteFormSection />}
+        />
+      </ChildExaminationForm>
+    </DentalExaminationStoreProvider>
   );
 }
-
-function mapToRequest(
-  examination: Examination,
-  formValues: ExaminationFormValues,
-  version: number,
-): UpdateExaminationRequest {
-  return {
-    examinationId: examination.id,
-    apiUpdateExaminationRequest: {
-      version,
-      note: mapOptionalValue(formValues.note),
-      result: mapExaminationResultRequest(examination, formValues),
-    },
-  };
-}
-
-function mapExaminationResultRequest(
-  examination: Examination,
-  formValues: ExaminationFormValues,
-): ApiExaminationResult | undefined {
-  if (examination.screening) {
-    return {
-      type: "ScreeningExaminationResult",
-      oralHygieneStatus: mapOptionalValue(formValues.oralHygieneStatus),
-      fluorideVarnishApplied:
-        mapOptionalValue(formValues.fluorideVarnishApplied) ?? false,
-      toothDiagnoses: [],
-    };
-  }
-
-  if (examination.fluoridation) {
-    return {
-      type: "FluoridationExaminationResult",
-      fluorideVarnishApplied: mapRequiredValue(
-        formValues.fluorideVarnishApplied,
-      ),
-    };
-  }
-
-  return undefined;
-}
diff --git a/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/details/page.tsx b/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/details/page.tsx
index bbd6bd6cd08d999cb02541991ce7b4c25719e8dd..de8cd6c227c27603e58d7610a4735408f9193fc0 100644
--- a/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/details/page.tsx
+++ b/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/details/page.tsx
@@ -8,7 +8,8 @@
 import { routes } from "@eshg/dental/shared/routes";
 
 import { ProphylaxisSessionDetails } from "@/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionDetails";
-import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider";
+import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
+import { useSyncOutgoingProphylaxisSessionChanges } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/useSyncOutgoingProphylaxisSessionChanges";
 import { MainContentLayout } from "@/lib/shared/components/layout/MainContentLayout";
 import { StickyToolbarLayout } from "@/lib/shared/components/layout/StickyToolbarLayout";
 import { Toolbar } from "@/lib/shared/components/layout/Toolbar";
@@ -19,6 +20,8 @@ export default function ProphylaxisSessionDetailsPage() {
   );
   const groupName = useProphylaxisSessionStore((state) => state.groupName);
 
+  useSyncOutgoingProphylaxisSessionChanges();
+
   return (
     <StickyToolbarLayout
       toolbar={
diff --git a/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/examinations/[participantIndex]/page.tsx b/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/examinations/[participantIndex]/page.tsx
index 3b8ba967993b0d0e0ebc3df626a09bfbe32aca5a..a57c61e46f05f25c4f0f8103b6d96b6c515bb491 100644
--- a/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/examinations/[participantIndex]/page.tsx
+++ b/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/examinations/[participantIndex]/page.tsx
@@ -5,25 +5,11 @@
 
 "use client";
 
-import { useRouter } from "next/navigation";
-import { useState } from "react";
-import { isDefined } from "remeda";
 import * as v from "valibot";
 
-import { AdditionalInformationFormSection } from "@/lib/businessModules/dental/features/examinations/AdditionalInformationFormSection";
-import { ExaminationFormLayout } from "@/lib/businessModules/dental/features/examinations/ExaminationFormLayout";
-import { NoteFormSection } from "@/lib/businessModules/dental/features/examinations/NoteFormSection";
-import { ProphylaxisSessionExaminationBottomBar } from "@/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationBottomBar";
-import { ProphylaxisSessionExaminationForm } from "@/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationForm";
-import { ProphylaxisSessionExaminationToolbar } from "@/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationToolbar";
-import { ADDITIONAL_INFO_FORM_COMPONENTS } from "@/lib/businessModules/dental/features/prophylaxisSessions/examination/formComponents";
-import { useProphylaxisSessionExaminationForm } from "@/lib/businessModules/dental/features/prophylaxisSessions/examination/useProphylaxisSessionExaminationForm";
-import { useProphylaxisSessionExaminationNavigation } from "@/lib/businessModules/dental/features/prophylaxisSessions/examination/useProphylaxisSessionExaminationNavigation";
-import {
-  useFilteredParticipants,
-  useProphylaxisSessionStore,
-} from "@/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider";
-import { StickyToolbarLayout } from "@/lib/shared/components/layout/StickyToolbarLayout";
+import { DentalExaminationStoreProvider } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
+import { ParticipantExaminationPage } from "@/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationPage";
+import { useFilteredParticipants } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
 
 const PageParamsSchema = v.object({
   participantIndex: v.pipe(
@@ -52,72 +38,13 @@ export default function ProphylaxisSessionExaminationPage(
     );
   }
 
-  const router = useRouter();
-  const prophylaxisSessionId = useProphylaxisSessionStore((state) => state.id);
-  const isScreening = useProphylaxisSessionStore((state) => state.isScreening);
-  const fluoridationVarnish = useProphylaxisSessionStore(
-    (state) => state.fluoridationVarnish,
-  );
-  const setExaminationResult = useProphylaxisSessionStore(
-    (state) => state.setExaminationResult,
-  );
-
-  const [nextRoute, setNextRoute] = useState<string>();
-  const examinationForm = useProphylaxisSessionExaminationForm({
-    examinationResult: participant.result,
-    note: participant.note,
-    onSubmit: (examinationResult) => {
-      setExaminationResult(participant.childId, examinationResult);
-      if (isDefined(nextRoute)) {
-        setNextRoute(undefined);
-        router.push(nextRoute);
-      }
-    },
-  });
-  const examinationNavigation = useProphylaxisSessionExaminationNavigation({
-    participantIndex,
-    participantsLength: filteredParticipants.length,
-    onNavigate: (nextRoute) => {
-      setNextRoute(nextRoute);
-      void examinationForm.submitForm();
-    },
-  });
-
   return (
-    <StickyToolbarLayout
-      toolbar={
-        <ProphylaxisSessionExaminationToolbar
-          prophylaxisSessionId={prophylaxisSessionId}
-          participant={participant}
-          participantIndex={participantIndex}
-          onBackClicked={examinationNavigation.gotoOverview}
-        />
-      }
-    >
-      <ProphylaxisSessionExaminationForm
-        form={examinationForm}
-        bottomBar={
-          <ProphylaxisSessionExaminationBottomBar
-            onPreviousParticipantClicked={
-              examinationNavigation.gotoPreviousParticipant
-            }
-            onNextParticipantClicked={examinationNavigation.gotoNextParticipant}
-            onOverviewClicked={examinationNavigation.gotoOverview}
-          />
-        }
-      >
-        <ExaminationFormLayout
-          additionalInformation={
-            <AdditionalInformationFormSection
-              screening={isScreening}
-              fluoridation={isDefined(fluoridationVarnish)}
-              fluoridationConsentGiven={participant.fluoridationConsentGiven}
-              components={ADDITIONAL_INFO_FORM_COMPONENTS}
-            />
-          }
-          note={<NoteFormSection />}
-        />
-      </ProphylaxisSessionExaminationForm>
-    </StickyToolbarLayout>
+    <DentalExaminationStoreProvider examinationResult={participant.result}>
+      <ParticipantExaminationPage
+        participant={participant}
+        participantIndex={participantIndex}
+        participantsLength={filteredParticipants.length}
+      />
+    </DentalExaminationStoreProvider>
   );
 }
diff --git a/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/layout.tsx b/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/layout.tsx
index 806458a00fe3d93f7c44d6fe221ffcd52805fc06..ead951ef21ef5826c79fd6552d3173fff63e2ecf 100644
--- a/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/layout.tsx
+++ b/employee-portal/src/app/(businessModules)/dental/prophylaxis-sessions/[prophylaxisSessionId]/layout.tsx
@@ -10,7 +10,7 @@ import { useDentalApi } from "@eshg/dental/shared/DentalProvider";
 import { useSuspenseQuery } from "@tanstack/react-query";
 import { PropsWithChildren } from "react";
 
-import { ProphylaxisSessionStoreProvider } from "@/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider";
+import { ProphylaxisSessionStoreProvider } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
 
 export type ProphylaxisSessionPageProps = Readonly<{
   params: ProphylaxisSessionPageParams;
diff --git a/employee-portal/src/app/(businessModules)/inspection/procedures/(subpages)/[id]/reportresult/edit/[reportId]/layout.tsx b/employee-portal/src/app/(businessModules)/inspection/procedures/(subpages)/[id]/reportresult/edit/[reportId]/layout.tsx
index 7a4c48489f8994ce61a951a9330315d5e902d5f3..6a8da6e70f18faac6194f8d38ae7757608ba6c20 100644
--- a/employee-portal/src/app/(businessModules)/inspection/procedures/(subpages)/[id]/reportresult/edit/[reportId]/layout.tsx
+++ b/employee-portal/src/app/(businessModules)/inspection/procedures/(subpages)/[id]/reportresult/edit/[reportId]/layout.tsx
@@ -3,6 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+"use client";
+
 import { PropsWithChildren } from "react";
 
 import { EditInspectionPageParams } from "@/app/(businessModules)/inspection/procedures/[id]/layout";
diff --git a/employee-portal/src/app/(businessModules)/inspection/procedures/[id]/execution/page.tsx b/employee-portal/src/app/(businessModules)/inspection/procedures/[id]/execution/page.tsx
index 49c5e6c55f7c333ab8dc89ae72c224af91179246..cc414ea4db5f24d7e29a99dc10dfbc719a782173 100644
--- a/employee-portal/src/app/(businessModules)/inspection/procedures/[id]/execution/page.tsx
+++ b/employee-portal/src/app/(businessModules)/inspection/procedures/[id]/execution/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionPhase } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionPhase } from "@eshg/inspection-api";
 
 import { useGetInspection } from "@/lib/businessModules/inspection/api/queries/inspection";
 import { InspectionTabDisabled } from "@/lib/businessModules/inspection/components/inspection/common/InspectionTabDisabled";
diff --git a/employee-portal/src/app/(businessModules)/inspection/procedures/[id]/reportresult/page.tsx b/employee-portal/src/app/(businessModules)/inspection/procedures/[id]/reportresult/page.tsx
index 5fd6a3433e0002a6f9e028be865a6b64ab714e9a..af13347497143a442063ee318c7fbf79c4a31f1b 100644
--- a/employee-portal/src/app/(businessModules)/inspection/procedures/[id]/reportresult/page.tsx
+++ b/employee-portal/src/app/(businessModules)/inspection/procedures/[id]/reportresult/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionPhase } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionPhase } from "@eshg/inspection-api";
 
 import { useGetInspection } from "@/lib/businessModules/inspection/api/queries/inspection";
 import { InspectionTabDisabled } from "@/lib/businessModules/inspection/components/inspection/common/InspectionTabDisabled";
diff --git a/employee-portal/src/app/(businessModules)/inspection/textblocks/page.tsx b/employee-portal/src/app/(businessModules)/inspection/textblocks/page.tsx
index 53a445d491d3f6d2fc8f3ac7ed010cfc3e5db3e4..4f3c8b2dcfa6b51283dd1489ca4b394c5ce4acaa 100644
--- a/employee-portal/src/app/(businessModules)/inspection/textblocks/page.tsx
+++ b/employee-portal/src/app/(businessModules)/inspection/textblocks/page.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { GetTextBlocksRequest } from "@eshg/employee-portal-api/inspection";
+import { GetTextBlocksRequest } from "@eshg/inspection-api";
 import { SearchParams } from "@eshg/lib-portal/helpers/searchParams";
 
 import { useGetTextBlocks } from "@/lib/businessModules/inspection/api/queries/textblocks";
diff --git a/employee-portal/src/app/(businessModules)/official-medical-service/procedures/[id]/documents/page.tsx b/employee-portal/src/app/(businessModules)/official-medical-service/procedures/[id]/documents/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7b07a7b2808cdeadd9391b8bddd03bc72803caf4
--- /dev/null
+++ b/employee-portal/src/app/(businessModules)/official-medical-service/procedures/[id]/documents/page.tsx
@@ -0,0 +1,15 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+"use client";
+
+import { OfficialMedicalServiceDetailsPageProps } from "@/app/(businessModules)/official-medical-service/procedures/[id]/layout";
+import { DocumentsTable } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentsTable";
+
+export default function OfficialMedicalServiceProcedureDetailsPage(
+  props: OfficialMedicalServiceDetailsPageProps,
+) {
+  return <DocumentsTable procedureId={props.params.id} />;
+}
diff --git a/employee-portal/src/app/(businessModules)/official-medical-service/waiting-room/page.tsx b/employee-portal/src/app/(businessModules)/official-medical-service/waiting-room/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..42113fd3a7f433e1f7968cc58af2e1447c69b552
--- /dev/null
+++ b/employee-portal/src/app/(businessModules)/official-medical-service/waiting-room/page.tsx
@@ -0,0 +1,19 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { WaitingRoomTable } from "@/lib/businessModules/officialMedicalService/components/waitingRoom/WaitingRoomTable";
+import { MainContentLayout } from "@/lib/shared/components/layout/MainContentLayout";
+import { StickyToolbarLayout } from "@/lib/shared/components/layout/StickyToolbarLayout";
+import { Toolbar } from "@/lib/shared/components/layout/Toolbar";
+
+export default function OmsWaitingRoomPage() {
+  return (
+    <StickyToolbarLayout toolbar={<Toolbar title="Wartezimmer" />}>
+      <MainContentLayout fullViewportHeight>
+        <WaitingRoomTable />
+      </MainContentLayout>
+    </StickyToolbarLayout>
+  );
+}
diff --git a/employee-portal/src/app/(businessModules)/statistics/evaluations/[id]/table/page.tsx b/employee-portal/src/app/(businessModules)/statistics/evaluations/[id]/table/page.tsx
index fb98cb49a4772913f91f2757b30584ea999fe61d..387f460aea7a38fd526dec5b934ba7ba754da934 100644
--- a/employee-portal/src/app/(businessModules)/statistics/evaluations/[id]/table/page.tsx
+++ b/employee-portal/src/app/(businessModules)/statistics/evaluations/[id]/table/page.tsx
@@ -5,12 +5,13 @@
 
 "use client";
 
-import { ApiSortDirection } from "@eshg/employee-portal-api/stiProtection";
+import { ApiSortDirection } from "@eshg/statistics-api";
 import { startTransition, useEffect, useState } from "react";
-import { isDefined, isNullish } from "remeda";
+import { isDefined } from "remeda";
 
 import {
   isValidAttributeKey,
+  mapAttributeSelectionToKey,
   mapKeyToAttributeSelection,
 } from "@/lib/businessModules/statistics/api/mapper/mapAttributeSelectionKey";
 import { ProcedureReferences } from "@/lib/businessModules/statistics/api/models/evaluationDetailsTableProcedureReferences";
@@ -56,20 +57,16 @@ export default function EvaluationDetailsTablePage(
     props.params.id,
   );
 
-  const sortableAccessorKey = evaluation.attributes.find(
-    (attribute) => attribute.type !== "ProcedureReferenceAttribute",
-  )?.key;
-
   const {
     sortKey: tableSortKey,
     sortDirection: tableSortDirection,
     manualSortingProps,
   } = useTableSorting({
     onSortingChange: () => resetPageNumber(),
-    initialSorting: isDefined(sortableAccessorKey)
+    initialSorting: evaluation.sortAttribute
       ? {
-          id: sortableAccessorKey,
-          desc: false,
+          id: mapAttributeSelectionToKey(evaluation.sortAttribute),
+          desc: evaluation.sortDirection === "DESC",
         }
       : undefined,
   });
@@ -95,7 +92,6 @@ export default function EvaluationDetailsTablePage(
         resetPageNumber();
       }),
     filterTemplates: filterTemplates,
-    loading: isNullish(sortKey),
   };
 
   return (
diff --git a/employee-portal/src/app/(businessModules)/sti-protection/text-templates/page.tsx b/employee-portal/src/app/(businessModules)/sti-protection/text-templates/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0e48f3d2a7e3edec9ba939e5f9bcba51fb8c6136
--- /dev/null
+++ b/employee-portal/src/app/(businessModules)/sti-protection/text-templates/page.tsx
@@ -0,0 +1,19 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { TextTemplatesOverviewTable } from "@/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesOverviewTable";
+import { MainContentLayout } from "@/lib/shared/components/layout/MainContentLayout";
+import { StickyToolbarLayout } from "@/lib/shared/components/layout/StickyToolbarLayout";
+import { Toolbar } from "@/lib/shared/components/layout/Toolbar";
+
+export default function TextTemplatesOverviewPage() {
+  return (
+    <StickyToolbarLayout toolbar={<Toolbar title="Textvorlagen" />}>
+      <MainContentLayout>
+        <TextTemplatesOverviewTable />
+      </MainContentLayout>
+    </StickyToolbarLayout>
+  );
+}
diff --git a/employee-portal/src/app/playground/charts/page.tsx b/employee-portal/src/app/playground/charts/page.tsx
index 8d2638b5c65618f55ae75f96f02360ac2239485f..1beced5edba9839820580266a6c00abd74a769dc 100644
--- a/employee-portal/src/app/playground/charts/page.tsx
+++ b/employee-portal/src/app/playground/charts/page.tsx
@@ -9,8 +9,6 @@ import { Option, Select, Sheet, Stack, Switch, Typography } from "@mui/joy";
 import { ReactNode, useState } from "react";
 
 import {
-  AnalysisLineDiagramConfiguration,
-  AnalysisScatterDiagramConfiguration,
   DiagramAxisRange,
   DiagramCharacteristicParameter,
   DiagramColorScheme,
@@ -19,7 +17,6 @@ import {
   DiagramScaling,
   DiagramType,
 } from "@/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes";
-import { FlatAttribute } from "@/lib/businessModules/statistics/api/models/flatAttribute";
 import { AnalysisDiagramBox } from "@/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisDiagramBox";
 import { BarChart } from "@/lib/businessModules/statistics/components/shared/charts/BarChart";
 import { ChoroplethMap } from "@/lib/businessModules/statistics/components/shared/charts/ChoroplethMap";
@@ -634,13 +631,13 @@ export default function PlaygroundChartsPage() {
       type: "IntegerAttribute",
       name: "Größe",
       unit: "m",
-    } as FlatAttribute,
+    },
     yAttribute: {
       type: "IntegerAttribute",
       name: "Gewicht",
       unit: "kg",
-    } as FlatAttribute,
-  } as AnalysisLineDiagramConfiguration;
+    },
+  };
 
   const lineChartGroupedWithLongValues = [
     {
@@ -676,13 +673,13 @@ export default function PlaygroundChartsPage() {
       type: "IntegerAttribute",
       name: "Die ganz besondere Einheit der gemessen Substanz gerundet nach Gefühl und Flexibilität",
       unit: "Einheitskürzel",
-    } as FlatAttribute,
+    },
     yAttribute: {
       type: "IntegerAttribute",
       name: "Die ganz besondere Einheit der gemessen Substanz gerundet nach Gefühl und Flexibilität",
       unit: "Einheitskürzel",
-    } as FlatAttribute,
-  } as AnalysisLineDiagramConfiguration;
+    },
+  };
 
   const scatterChartSimple = [
     {
@@ -745,13 +742,13 @@ export default function PlaygroundChartsPage() {
       type: "IntegerAttribute",
       name: "Größe",
       unit: "m",
-    } as FlatAttribute,
+    },
     yAttribute: {
       type: "IntegerAttribute",
       name: "Gewicht",
       unit: "kg",
-    } as FlatAttribute,
-  } as AnalysisScatterDiagramConfiguration;
+    },
+  };
 
   const choroplethData = [
     {
diff --git a/employee-portal/src/app/playground/filter-settings/page.tsx b/employee-portal/src/app/playground/filter-settings/page.tsx
index 7daab474fe76c44561faedd81ca34e8ebd34c14d..9f36e574fb3e8d505f366d2216b204cd3f2f0217 100644
--- a/employee-portal/src/app/playground/filter-settings/page.tsx
+++ b/employee-portal/src/app/playground/filter-settings/page.tsx
@@ -89,6 +89,7 @@ const filterDefinitions: FilterDefinition[] = [
     name: "Date Comparison",
   },
   { type: "Year", key: "year", name: "Year" },
+  { type: "Text", key: "text", name: "Text" },
 ];
 
 const initialValues: FilterValue[] = [
diff --git a/employee-portal/src/app/playground/page.tsx b/employee-portal/src/app/playground/page.tsx
index 0164fc27b481b602840c758cba3d4c69590de42e..65160e2ea4d8925e62ed6a32a48868ec92d877c4 100644
--- a/employee-portal/src/app/playground/page.tsx
+++ b/employee-portal/src/app/playground/page.tsx
@@ -115,6 +115,9 @@ export default function PlaygroundIndexPage() {
               Appointment Picker Field
             </InternalLink>
           </li>
+          <li>
+            <InternalLink href="/playground/teeth">Zahn-Icons</InternalLink>
+          </li>
         </ul>
       </MainContentLayout>
     </StickyToolbarLayout>
diff --git a/employee-portal/src/app/playground/teeth/page.tsx b/employee-portal/src/app/playground/teeth/page.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..263a214293539ccb00ebe91f9cd35690b5af0787
--- /dev/null
+++ b/employee-portal/src/app/playground/teeth/page.tsx
@@ -0,0 +1,180 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Grid, Typography } from "@mui/joy";
+
+import {
+  Cuspid,
+  Incisor,
+  Molar,
+  Premolar,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Teeth";
+import { MainContentLayout } from "@/lib/shared/components/layout/MainContentLayout";
+import { StickyToolbarLayout } from "@/lib/shared/components/layout/StickyToolbarLayout";
+import { Toolbar } from "@/lib/shared/components/layout/Toolbar";
+
+export default function TeethPlaygroundPage() {
+  return (
+    <StickyToolbarLayout
+      toolbar={<Toolbar title={"Teeth"} backHref="/playground" />}
+    >
+      <MainContentLayout>
+        <Grid container spacing={2}>
+          <Grid xxs={12}>
+            <Typography level="h3">Incisor (Schneidezahn)</Typography>
+          </Grid>
+
+          <Grid xxs={1}>
+            <Incisor variant="upperJaw" isPrimaryTooth />
+          </Grid>
+          <Grid xxs={1}>
+            <Incisor
+              variant="upperJaw"
+              isPrimaryTooth
+              hasPreviousExaminationResult
+            />
+          </Grid>
+          <Grid xxs={1}>
+            <Incisor variant="upperJaw" />
+          </Grid>
+          <Grid xxs={1}>
+            <Incisor variant="upperJaw" hasPreviousExaminationResult />
+          </Grid>
+
+          <Grid xxs={1}>
+            <Incisor variant="lowerJaw" isPrimaryTooth />
+          </Grid>
+          <Grid xxs={1}>
+            <Incisor
+              variant="lowerJaw"
+              isPrimaryTooth
+              hasPreviousExaminationResult
+            />
+          </Grid>
+          <Grid xxs={1}>
+            <Incisor variant="lowerJaw" />
+          </Grid>
+          <Grid xxs={1}>
+            <Incisor variant="lowerJaw" hasPreviousExaminationResult />
+          </Grid>
+
+          <Grid xxs={12}>
+            <Typography level="h3">Cuspid (Eckzahn)</Typography>
+          </Grid>
+
+          <Grid xxs={1}>
+            <Cuspid variant="upperJaw" isPrimaryTooth />
+          </Grid>
+          <Grid xxs={1}>
+            <Cuspid
+              variant="upperJaw"
+              isPrimaryTooth
+              hasPreviousExaminationResult
+            />
+          </Grid>
+          <Grid xxs={1}>
+            <Cuspid variant="upperJaw" />
+          </Grid>
+          <Grid xxs={1}>
+            <Cuspid variant="upperJaw" hasPreviousExaminationResult />
+          </Grid>
+
+          <Grid xxs={1}>
+            <Cuspid variant="lowerJaw" isPrimaryTooth />
+          </Grid>
+          <Grid xxs={1}>
+            <Cuspid
+              variant="lowerJaw"
+              isPrimaryTooth
+              hasPreviousExaminationResult
+            />
+          </Grid>
+          <Grid xxs={1}>
+            <Cuspid variant="lowerJaw" />
+          </Grid>
+          <Grid xxs={1}>
+            <Cuspid variant="lowerJaw" hasPreviousExaminationResult />
+          </Grid>
+
+          <Grid xxs={12}>
+            <Typography level="h3">Premolar (Backenzahn)</Typography>
+          </Grid>
+
+          <Grid xxs={1}>
+            <Premolar variant="upperJaw" isPrimaryTooth />
+          </Grid>
+          <Grid xxs={1}>
+            <Premolar
+              variant="upperJaw"
+              isPrimaryTooth
+              hasPreviousExaminationResult
+            />
+          </Grid>
+          <Grid xxs={1}>
+            <Premolar variant="upperJaw" />
+          </Grid>
+          <Grid xxs={1}>
+            <Premolar variant="upperJaw" hasPreviousExaminationResult />
+          </Grid>
+
+          <Grid xxs={1}>
+            <Premolar variant="lowerJaw" isPrimaryTooth />
+          </Grid>
+          <Grid xxs={1}>
+            <Premolar
+              variant="lowerJaw"
+              isPrimaryTooth
+              hasPreviousExaminationResult
+            />
+          </Grid>
+          <Grid xxs={1}>
+            <Premolar variant="lowerJaw" />
+          </Grid>
+          <Grid xxs={1}>
+            <Premolar variant="lowerJaw" hasPreviousExaminationResult />
+          </Grid>
+
+          <Grid xxs={12}>
+            <Typography level="h3">Molar (Mahlzahn)</Typography>
+          </Grid>
+
+          <Grid xxs={1}>
+            <Molar variant="upperJaw" isPrimaryTooth />
+          </Grid>
+          <Grid xxs={1}>
+            <Molar
+              variant="upperJaw"
+              isPrimaryTooth
+              hasPreviousExaminationResult
+            />
+          </Grid>
+          <Grid xxs={1}>
+            <Molar variant="upperJaw" />
+          </Grid>
+          <Grid xxs={1}>
+            <Molar variant="upperJaw" hasPreviousExaminationResult />
+          </Grid>
+
+          <Grid xxs={1}>
+            <Molar variant="lowerJaw" isPrimaryTooth />
+          </Grid>
+          <Grid xxs={1}>
+            <Molar
+              variant="lowerJaw"
+              isPrimaryTooth
+              hasPreviousExaminationResult
+            />
+          </Grid>
+          <Grid xxs={1}>
+            <Molar variant="lowerJaw" />
+          </Grid>
+          <Grid xxs={1}>
+            <Molar variant="lowerJaw" hasPreviousExaminationResult />
+          </Grid>
+        </Grid>
+      </MainContentLayout>
+    </StickyToolbarLayout>
+  );
+}
diff --git a/employee-portal/src/lib/auditlog/api/clients.ts b/employee-portal/src/lib/auditlog/api/clients.ts
index 1688468f787a754f99e79bb854dcb26550038c8f..8de634e509e2b995fd781842f52467d005e7c53e 100644
--- a/employee-portal/src/lib/auditlog/api/clients.ts
+++ b/employee-portal/src/lib/auditlog/api/clients.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { AuditLogApi, Configuration } from "@eshg/employee-portal-api/auditlog";
+import { AuditLogApi, Configuration } from "@eshg/auditlog-api";
 import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
 
 function useConfiguration() {
diff --git a/employee-portal/src/lib/auditlog/api/models/auditlog.ts b/employee-portal/src/lib/auditlog/api/models/auditlog.ts
index a2e841d4f148a78ca66ffdc30a2507b604455f20..ff4ec917a5739a6a735c306ef78acd8f345316d8 100644
--- a/employee-portal/src/lib/auditlog/api/models/auditlog.ts
+++ b/employee-portal/src/lib/auditlog/api/models/auditlog.ts
@@ -7,7 +7,7 @@ import {
   ApiAuditLogGrantedAccessCount,
   ApiAuditLogSource,
   ApiGetAvailableAuditLogsResponse,
-} from "@eshg/employee-portal-api/auditlog/models";
+} from "@eshg/auditlog-api";
 
 interface GetAvailableAuditLogsResponse {
   logs: AuditLog[];
diff --git a/employee-portal/src/lib/auditlog/components/AuditLogDecryptSidebar.tsx b/employee-portal/src/lib/auditlog/components/AuditLogDecryptSidebar.tsx
index 02e0cd2a1211d9eb5a8e86fd54486acccf3f07e6..a9f25be73e3cf96dff29f919e0dcdac707cb81bd 100644
--- a/employee-portal/src/lib/auditlog/components/AuditLogDecryptSidebar.tsx
+++ b/employee-portal/src/lib/auditlog/components/AuditLogDecryptSidebar.tsx
@@ -7,7 +7,7 @@ import {
   ApiAuditLogSource,
   ApiAuditLogSourceFromJSON,
   AuditLogApi,
-} from "@eshg/employee-portal-api/auditlog";
+} from "@eshg/auditlog-api";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import { encodeReservedHtmlCharacters } from "@eshg/lib-portal/helpers/htmlStringEncoder";
diff --git a/employee-portal/src/lib/auditlog/components/AuditLogSheet.tsx b/employee-portal/src/lib/auditlog/components/AuditLogSheet.tsx
index d22d012c2aefb40ef9460cc9ed61e115387db6d7..8e8053ce762f43f1796fe6ff2a297a0c1bfee856 100644
--- a/employee-portal/src/lib/auditlog/components/AuditLogSheet.tsx
+++ b/employee-portal/src/lib/auditlog/components/AuditLogSheet.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiAuditLogSourceFromJSON } from "@eshg/employee-portal-api/auditlog";
+import { ApiAuditLogSourceFromJSON } from "@eshg/auditlog-api";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { FeedOutlined } from "@mui/icons-material";
 import { Sheet } from "@mui/joy";
diff --git a/employee-portal/src/lib/auditlog/components/auditLogAccessibleColumns.tsx b/employee-portal/src/lib/auditlog/components/auditLogAccessibleColumns.tsx
index e94f14bde51359f7886dfebe7d972c6dab4a3f75..65df71f9cb2de2b1496df47ab3ff95372ec02aac 100644
--- a/employee-portal/src/lib/auditlog/components/auditLogAccessibleColumns.tsx
+++ b/employee-portal/src/lib/auditlog/components/auditLogAccessibleColumns.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiAccessibleAuditLog } from "@eshg/employee-portal-api/auditlog";
+import { ApiAccessibleAuditLog } from "@eshg/auditlog-api";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { VisibilityOutlined } from "@mui/icons-material";
 import { Chip, Typography } from "@mui/joy";
diff --git a/employee-portal/src/lib/auditlog/components/authorize/AuditLogAuthorizeSidebar.tsx b/employee-portal/src/lib/auditlog/components/authorize/AuditLogAuthorizeSidebar.tsx
index a8f390f28d11c08730afcf85c2428fc52e7835c8..b8668845bec3d6099a4888457bb754544a4aa427 100644
--- a/employee-portal/src/lib/auditlog/components/authorize/AuditLogAuthorizeSidebar.tsx
+++ b/employee-portal/src/lib/auditlog/components/authorize/AuditLogAuthorizeSidebar.tsx
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUser } from "@eshg/base-api";
 import {
   ApiAuditLogSource,
   ApiGetAuditLogGrantedAccessesResponse,
-} from "@eshg/employee-portal-api/auditlog";
+} from "@eshg/auditlog-api";
+import { ApiUser } from "@eshg/base-api";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { List, ListItem, Sheet, Stack, Typography } from "@mui/joy";
 import { Formik } from "formik";
diff --git a/employee-portal/src/lib/auditlog/components/authorize/useAuditLogAdminFilterSettings.ts b/employee-portal/src/lib/auditlog/components/authorize/useAuditLogAdminFilterSettings.ts
index 3ad45c4bff4338a2b18b3d78f60988e1809b0f11..d9279aab730e98e53ce3401999efcc10362d6dd1 100644
--- a/employee-portal/src/lib/auditlog/components/authorize/useAuditLogAdminFilterSettings.ts
+++ b/employee-portal/src/lib/auditlog/components/authorize/useAuditLogAdminFilterSettings.ts
@@ -6,7 +6,7 @@
 import {
   ApiAuditLogSource,
   ApiAuditLogSourceFromJSON,
-} from "@eshg/employee-portal-api/auditlog";
+} from "@eshg/auditlog-api";
 import { ensureArray } from "@eshg/lib-portal/helpers/guards";
 import { SearchParams } from "@eshg/lib-portal/helpers/searchParams";
 import { isString } from "remeda";
diff --git a/employee-portal/src/lib/auditlog/components/crypto.ts b/employee-portal/src/lib/auditlog/components/crypto.ts
index 23188c66979ab52fd659b82d89031e3e3fe8e42f..1d6179d06444b49bb92e0ceeee08805812145cdb 100644
--- a/employee-portal/src/lib/auditlog/components/crypto.ts
+++ b/employee-portal/src/lib/auditlog/components/crypto.ts
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { ApiGetEncryptedSymmetricKeyResponse } from "@eshg/auditlog-api";
 import { ApiEmployeeUserKeys } from "@eshg/base-api";
-import { ApiGetEncryptedSymmetricKeyResponse } from "@eshg/employee-portal-api/auditlog";
 import { AeadId, CipherSuite, KdfId, KemId } from "hpke-js";
 
 const suite = new CipherSuite({
diff --git a/employee-portal/src/lib/auditlog/mutations/auditlog.ts b/employee-portal/src/lib/auditlog/mutations/auditlog.ts
index 77f0c56e03c86b31038875cea8792d744f2ed0b5..486bc15c1063678880fad29619c77150b17fb0e3 100644
--- a/employee-portal/src/lib/auditlog/mutations/auditlog.ts
+++ b/employee-portal/src/lib/auditlog/mutations/auditlog.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGrantAuditLogAccessRequest } from "@eshg/employee-portal-api/auditlog";
+import { ApiGrantAuditLogAccessRequest } from "@eshg/auditlog-api";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 
diff --git a/employee-portal/src/lib/auditlog/queries/auditlog.ts b/employee-portal/src/lib/auditlog/queries/auditlog.ts
index 1637c16cf84488d606a83cd22231675b82ff8163..912a48d71a9a8001616ba07c8ad572dec2e5a0fd 100644
--- a/employee-portal/src/lib/auditlog/queries/auditlog.ts
+++ b/employee-portal/src/lib/auditlog/queries/auditlog.ts
@@ -8,7 +8,7 @@ import {
   GetAuditLogGrantedAccessesRequest,
   GetAuditLogGranteesCandidatesRequest,
   GetAvailableLogsRequest,
-} from "@eshg/employee-portal-api/auditlog";
+} from "@eshg/auditlog-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useSuspenseQuery } from "@tanstack/react-query";
 
diff --git a/employee-portal/src/lib/baseModule/api/mutations/facility.ts b/employee-portal/src/lib/baseModule/api/mutations/facility.ts
index 460ef864c7d0998090f9bb3a7865d08c43e23e18..02e6c6e396d970a1200ba3a13ac9f51b08514abc 100644
--- a/employee-portal/src/lib/baseModule/api/mutations/facility.ts
+++ b/employee-portal/src/lib/baseModule/api/mutations/facility.ts
@@ -4,7 +4,7 @@
  */
 
 import { ApiAddFacilityFileStateRequest } from "@eshg/base-api";
-import { ApiDataOrigin } from "@eshg/employee-portal-api/inspection";
+import { ApiDataOrigin } from "@eshg/inspection-api";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { isNullish } from "remeda";
diff --git a/employee-portal/src/lib/baseModule/api/mutations/gdpr.ts b/employee-portal/src/lib/baseModule/api/mutations/gdpr.ts
index 0495992498dd41ca0fc339d559938b90f838575d..ab6928acd7bd10ec1f5a019b193685b05bc58a40 100644
--- a/employee-portal/src/lib/baseModule/api/mutations/gdpr.ts
+++ b/employee-portal/src/lib/baseModule/api/mutations/gdpr.ts
@@ -8,12 +8,12 @@ import {
   ApiAddGdprProcedureRequest,
   ApiGdprProcedureStatus,
 } from "@eshg/base-api";
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiGdprProcedureType,
   GdprValidationTaskApiInterface,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+} from "@eshg/lib-procedures-api";
 
 import { useGdprProcedureApi } from "@/lib/baseModule/api/clients";
 
diff --git a/employee-portal/src/lib/baseModule/components/contacts/forms/merge/MergeStringField.tsx b/employee-portal/src/lib/baseModule/components/contacts/forms/merge/MergeStringField.tsx
index 4819b829fba333d7a1c0f856df88662c14d7fe3f..933cdb2b8908b42ebe7a43bd8676031360aa3096 100644
--- a/employee-portal/src/lib/baseModule/components/contacts/forms/merge/MergeStringField.tsx
+++ b/employee-portal/src/lib/baseModule/components/contacts/forms/merge/MergeStringField.tsx
@@ -33,6 +33,7 @@ export function MergeStringField({
   }
 
   function normalizeValue(value: string | undefined) {
+    // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
     return value === undefined || value === "" ? (emptyValue ?? " ") : value;
   }
 
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/constants.ts b/employee-portal/src/lib/baseModule/components/gdpr/constants.ts
index 8f50e49a22465832d5eb22e5583e163335cbb0e6..317471d165907d8e07f96991d2f367dbf46a9a69 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/constants.ts
+++ b/employee-portal/src/lib/baseModule/components/gdpr/constants.ts
@@ -7,7 +7,6 @@ import { ApiGdprProcedureStatus } from "@eshg/base-api";
 import { DefaultColorPalette } from "@mui/joy/styles/types";
 
 export const gdprProcedureStatusColor = {
-  OPEN: "neutral",
   DRAFT: "warning",
   IN_PROGRESS: "primary",
   CLOSED: "success",
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/helpers.ts b/employee-portal/src/lib/baseModule/components/gdpr/helpers.ts
index 35f8d1d015a226236aceb8e9529f3a3217152440..97d32bc1d824ee8bb965c871a8c3844b777fed4f 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/helpers.ts
+++ b/employee-portal/src/lib/baseModule/components/gdpr/helpers.ts
@@ -10,8 +10,8 @@ import {
   instanceOfApiGdprFacility,
   instanceOfApiGdprPerson,
 } from "@eshg/base-api";
-import { ApiGdprValidationTaskIdentificationData } from "@eshg/employee-portal-api/businessProcedures";
 import { formatPersonName } from "@eshg/lib-portal/formatters/person";
+import { ApiGdprValidationTaskIdentificationData } from "@eshg/lib-procedures-api";
 
 export function isGdprPerson(
   identificationData: ApiGdprIdentificationData,
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/i18n.ts b/employee-portal/src/lib/baseModule/components/gdpr/i18n.ts
index 13c2271beb32385eac11ffe7088f1af47003cfe7..9d9290ffd60892057a00907d890852cb3559d48f 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/i18n.ts
+++ b/employee-portal/src/lib/baseModule/components/gdpr/i18n.ts
@@ -8,7 +8,6 @@ import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 
 export const statusTranslation = {
   DRAFT: "Entwurf",
-  OPEN: "Offen",
   IN_PROGRESS: "In Bearbeitung",
   CLOSED: "Abgeschlossen",
   ABORTED: "Abgebrochen",
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/overview/CreateGDPRProcedureSidebar.tsx b/employee-portal/src/lib/baseModule/components/gdpr/overview/CreateGDPRProcedureSidebar.tsx
index c996d8cb3f5bd5f3e396cd79c6b1ae95e63ffab3..38f7d9b8ddfe5ba0c912f21fe202263099f09420 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/overview/CreateGDPRProcedureSidebar.tsx
+++ b/employee-portal/src/lib/baseModule/components/gdpr/overview/CreateGDPRProcedureSidebar.tsx
@@ -10,7 +10,10 @@ import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { SALUTATION_OPTIONS } from "@eshg/lib-portal/components/formFields/constants";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
-import { validateLength } from "@eshg/lib-portal/helpers/validators";
+import {
+  validateDateOfBirth,
+  validateLength,
+} from "@eshg/lib-portal/helpers/validators";
 import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
 import { Divider, Grid } from "@mui/joy";
 import { Formik } from "formik";
@@ -127,6 +130,7 @@ function CreateGDPRProcedureSidebar({
                   name={fieldName("dateOfBirth")}
                   label={"Geburtsdatum"}
                   required={"Bitte ein Geburtsdatum eingeben"}
+                  validate={validateDateOfBirth}
                 />
               </Grid>
               <Grid xxs={12}>
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/procedure/MatterOfConcernDisplayField.tsx b/employee-portal/src/lib/baseModule/components/gdpr/procedure/MatterOfConcernDisplayField.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e64140254f5b71a1d4f0a90e99cb6f51e2b34881
--- /dev/null
+++ b/employee-portal/src/lib/baseModule/components/gdpr/procedure/MatterOfConcernDisplayField.tsx
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import InfoIcon from "@mui/icons-material/InfoOutlined";
+import { isString } from "remeda";
+
+import { multiLineEllipsis } from "@/lib/baseModule/theme/theme";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
+
+export function MatterOfConcernDisplayField({
+  value,
+  editable,
+}: Readonly<{
+  value: string | undefined;
+  editable: boolean;
+}>) {
+  const isPresent = isString(value) && value.trim().length > 0;
+  return (
+    <DetailsItem
+      label="Anliegen"
+      value={isPresent || !editable ? value : "Bitte Anliegen eintragen."}
+      slotProps={{
+        value: {
+          startDecorator: isPresent ? undefined : (
+            <InfoIcon color="danger" size="md" />
+          ),
+          sx: {
+            maxWidth: "100%",
+            ...multiLineEllipsis(3),
+          },
+        },
+      }}
+    />
+  );
+}
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprDownloadPackagesTile.tsx b/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprDownloadPackagesTile.tsx
index 1eeba1854c65b463271a80ec71d2606966849c99..f6f05b32d15d4a8f8a8cf7efe1686987a82dda58 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprDownloadPackagesTile.tsx
+++ b/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprDownloadPackagesTile.tsx
@@ -4,8 +4,8 @@
  */
 
 import { ApiGetGdprProcedureResponse } from "@eshg/base-api";
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
 import { useFileDownload } from "@eshg/lib-portal/api/files/download";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 import CheckmarkIcon from "@mui/icons-material/Check";
 import DownloadIcon from "@mui/icons-material/SimCardDownloadOutlined";
 import {
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprFacilityDataTile.tsx b/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprFacilityDataTile.tsx
index ec553086d2bbf517f66d3b701d2ea938c88f36a0..393eb971a2c0136f32a2e1cdb2da1aad1e55c59b 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprFacilityDataTile.tsx
+++ b/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprFacilityDataTile.tsx
@@ -4,16 +4,16 @@
  */
 
 import { ApiGdprFacility } from "@eshg/base-api";
-import { ExternalLink } from "@eshg/lib-portal/components/navigation/ExternalLink";
 import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
 import VerifiedIcon from "@mui/icons-material/VerifiedOutlined";
-import { Stack, Typography } from "@mui/joy";
+import { Stack } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 
 import { ResponsiveDivider } from "@/lib/shared/components/ResponsiveDivider";
 import { BaseAddressDetails } from "@/lib/shared/components/address/BaseAddressDetails";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsColumn } from "@/lib/shared/components/detailsSection/DetailsColumn";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
+import { ExternalLinkDetailsItem } from "@/lib/shared/components/detailsSection/items/ExternalLinkDetailsItem";
 import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 
 export function GdprFacilityDataTile({
@@ -31,19 +31,17 @@ export function GdprFacilityDataTile({
         divider={<ResponsiveDivider />}
       >
         <DetailsColumn sx={columnSx}>
-          <DetailsCell name="name" label="Name" value={identity.name} />
+          <DetailsItem label="Name" value={identity.name} />
           {identity.dataTransmitterPseudonymId && (
-            <DetailsCell
-              name="dataTransmitterPseudonymId"
+            <DetailsItem
               label="Mein Unternehmenskonto"
-              value={
-                <Typography
-                  startDecorator={<VerifiedIcon color="success" />}
-                  noWrap
-                >
-                  Authentifiziert
-                </Typography>
-              }
+              value="Authentifiziert"
+              slotProps={{
+                value: {
+                  startDecorator: <VerifiedIcon color="success" />,
+                  noWrap: true,
+                },
+              }}
             />
           )}
         </DetailsColumn>
@@ -53,22 +51,12 @@ export function GdprFacilityDataTile({
         {(isNonEmptyString(identity.emailAddress) ||
           isNonEmptyString(identity.phoneNumber)) && (
           <DetailsColumn sx={columnSx}>
-            {isNonEmptyString(identity.emailAddress) && (
-              <DetailsCell
-                name={"emailAddress"}
-                label={"E-Mail-Adresse"}
-                value={
-                  <ExternalLink href={`mailto:${identity.emailAddress}`}>
-                    {identity.emailAddress}
-                  </ExternalLink>
-                }
-              />
-            )}
-            <DetailsCell
-              name={"phoneNumber"}
-              label={"Telefonnummer"}
-              value={identity.phoneNumber}
+            <ExternalLinkDetailsItem
+              label={"E-Mail-Adresse"}
+              value={identity.emailAddress}
+              href={(value) => `mailto:${value}`}
             />
+            <DetailsItem label={"Telefonnummer"} value={identity.phoneNumber} />
           </DetailsColumn>
         )}
       </Stack>
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprPersonDataTile.tsx b/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprPersonDataTile.tsx
index e0b56222c686f4e2479568586ec42388b83d22bc..36cd741e1b63be9ab799538a3cd772707c9b34bf 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprPersonDataTile.tsx
+++ b/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/GdprPersonDataTile.tsx
@@ -11,7 +11,7 @@ import {
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
 import VerifiedIcon from "@mui/icons-material/VerifiedOutlined";
-import { Stack, Typography } from "@mui/joy";
+import { Stack } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 
 import {
@@ -20,10 +20,10 @@ import {
 } from "@/lib/baseModule/components/gdpr/procedure/tiles/SectionTile";
 import { ResponsiveDivider } from "@/lib/shared/components/ResponsiveDivider";
 import { BaseAddressDetails } from "@/lib/shared/components/address/BaseAddressDetails";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsColumn } from "@/lib/shared/components/detailsSection/DetailsColumn";
 import { DetailsRow } from "@/lib/shared/components/detailsSection/DetailsRow";
-import { ExternalLinkDetailsCell } from "@/lib/shared/components/detailsSection/ExternalLinkDetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
+import { ExternalLinkDetailsItem } from "@/lib/shared/components/detailsSection/items/ExternalLinkDetailsItem";
 
 export function GdprPersonDataTile({
   identity,
@@ -46,46 +46,39 @@ export function GdprPersonDataTile({
           <DetailsRow>
             {isNonEmptyString(identity.salutation) &&
               identity.salutation !== ApiSalutation.NotSpecified && (
-                <DetailsCell
-                  name={"salutation"}
+                <DetailsItem
                   label={PERSON_FIELD_NAME.salutation}
                   value={SALUTATION_VALUES[identity.salutation]}
                 />
               )}
-            <DetailsCell
-              name={"title"}
+            <DetailsItem
               label={PERSON_FIELD_NAME.title}
               value={identity.title}
               avoidWrap
             />
           </DetailsRow>
-          <DetailsCell
-            name={"firstName"}
+          <DetailsItem
             label={PERSON_FIELD_NAME.firstName}
             value={identity.firstName}
           />
-          <DetailsCell
-            name={"lastName"}
+          <DetailsItem
             label={PERSON_FIELD_NAME.lastName}
             value={identity.lastName}
           />
-          <DetailsCell
-            name={"dateOfBirth"}
+          <DetailsItem
             label={PERSON_FIELD_NAME.dateOfBirth}
             value={formatDate(identity.dateOfBirth)}
           />
           {identity.bpk2 && (
-            <DetailsCell
-              name="bpk2"
+            <DetailsItem
               label="BundID"
-              value={
-                <Typography
-                  startDecorator={<VerifiedIcon color="success" />}
-                  noWrap
-                >
-                  Authentifiziert
-                </Typography>
-              }
+              value="Authentifiziert"
+              slotProps={{
+                value: {
+                  startDecorator: <VerifiedIcon color="success" />,
+                  noWrap: true,
+                },
+              }}
             />
           )}
         </DetailsColumn>
@@ -95,16 +88,12 @@ export function GdprPersonDataTile({
         {(isNonEmptyString(identity.emailAddress) ||
           isNonEmptyString(identity.phoneNumber)) && (
           <DetailsColumn sx={columnSx}>
-            {isNonEmptyString(identity.emailAddress) && (
-              <ExternalLinkDetailsCell
-                name={"emailAddress"}
-                label={PERSON_FIELD_NAME.emailAddresses}
-                value={identity.emailAddress}
-                href={(value) => `mailto:${value}`}
-              />
-            )}
-            <DetailsCell
-              name={"phoneNumber"}
+            <ExternalLinkDetailsItem
+              label={PERSON_FIELD_NAME.emailAddresses}
+              value={identity.emailAddress}
+              href={(value: string) => `mailto:${value}`}
+            />
+            <DetailsItem
               label={PERSON_FIELD_NAME.phoneNumbers}
               value={identity.phoneNumber}
             />
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/ProcedureDetailsTile.tsx b/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/ProcedureDetailsTile.tsx
index 856e783c9e7d31016851051f958b8c620ca425da..a0742c7f963b000bab0add40c55e2b5d11c4d070 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/ProcedureDetailsTile.tsx
+++ b/employee-portal/src/lib/baseModule/components/gdpr/procedure/tiles/ProcedureDetailsTile.tsx
@@ -18,7 +18,6 @@ import {
 } from "@eshg/lib-portal/errorHandling/AlertContext";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import EditIcon from "@mui/icons-material/EditOutlined";
-import InfoIcon from "@mui/icons-material/InfoOutlined";
 import RefreshIcon from "@mui/icons-material/Refresh";
 import { Button, Divider, IconButton, Stack, Typography } from "@mui/joy";
 import { Formik } from "formik";
@@ -37,14 +36,14 @@ import {
   typeTranslation,
 } from "@/lib/baseModule/components/gdpr/i18n";
 import { DownloadReportButton } from "@/lib/baseModule/components/gdpr/procedure/DownloadReportButton";
+import { MatterOfConcernDisplayField } from "@/lib/baseModule/components/gdpr/procedure/MatterOfConcernDisplayField";
 import { useEditMatterOfConcernSidebar } from "@/lib/baseModule/components/gdpr/procedure/sidebars/EditMatterOfConcernSidebar";
 import {
   SectionTile,
   SectionTitle,
 } from "@/lib/baseModule/components/gdpr/procedure/tiles/SectionTile";
-import { multiLineEllipsis } from "@/lib/baseModule/theme/theme";
 import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
 import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
 
@@ -115,13 +114,11 @@ export function ProcedureDetailsTile({
 
         <AlertSlot />
 
-        <DetailsCell
-          name={"createdAt"}
+        <DetailsItem
           label={"Erstellt"}
           value={formatDateTime(procedure.createdAt)}
         />
-        <DetailsCell
-          name={"type"}
+        <DetailsItem
           label={"Vorgangsart"}
           value={
             isGdprPerson(procedure.identificationData)
@@ -130,13 +127,11 @@ export function ProcedureDetailsTile({
           }
           avoidWrap
         />
-        <DetailsCell
-          name={"status"}
+        <DetailsItem
           label={"Status"}
           value={statusTranslation[procedure.status]}
         />
-        <DetailsCell
-          name="internalNote"
+        <DetailsItem
           label={
             procedure.status === ApiGdprProcedureStatus.Closed
               ? "Ergebnis"
@@ -147,25 +142,9 @@ export function ProcedureDetailsTile({
           value={procedure.internalNote}
         />
         {requiresMatterOfConcern && (
-          <DetailsCell
-            name="matterOfConcern"
-            label="Anliegen"
-            value={
-              procedure.matterOfConcern ??
-              (isEditable ? (
-                <Typography
-                  startDecorator={<InfoIcon color="danger" size="md" />}
-                >
-                  Bitte Anliegen eintragen.
-                </Typography>
-              ) : (
-                ""
-              ))
-            }
-            valueSx={{
-              ...multiLineEllipsis(3),
-              maxWidth: "100%",
-            }}
+          <MatterOfConcernDisplayField
+            value={procedure.matterOfConcern}
+            editable={isEditable}
           />
         )}
 
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/UseCloseValidationTaskDialog.tsx b/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/UseCloseValidationTaskDialog.tsx
index 20e91c74431fd921789eb16e377959af80cb0018..0e640c22e56605972bac90c6e8a08a063a5392c5 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/UseCloseValidationTaskDialog.tsx
+++ b/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/UseCloseValidationTaskDialog.tsx
@@ -8,7 +8,7 @@ import {
   ApiBusinessProcedureWithInclusionStatus,
   ApiGdprProcedureType,
   GdprValidationTaskApiInterface,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 import { Typography } from "@mui/joy";
 
 import { useCloseValidationTask } from "@/lib/baseModule/api/mutations/gdpr";
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/ValidationTaskProceduresTable.tsx b/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/ValidationTaskProceduresTable.tsx
index f1365341157fced9437d7e0e3ed81205f08be02c..82eaebf706006d9192959af83f18f9d138129975 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/ValidationTaskProceduresTable.tsx
+++ b/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/ValidationTaskProceduresTable.tsx
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import {
   ApiBusinessProcedureInclusionStatus,
   ApiBusinessProcedureWithInclusionStatus,
@@ -11,8 +12,7 @@ import {
   ApiProcedure,
   ApiProcedureStatus,
   GdprValidationTaskApiInterface,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+} from "@eshg/lib-procedures-api";
 import IncludedIcon from "@mui/icons-material/CheckOutlined";
 import UndecidedIcon from "@mui/icons-material/ClearOutlined";
 import { Button, Chip, Typography } from "@mui/joy";
diff --git a/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/ValidationTasksTable.tsx b/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/ValidationTasksTable.tsx
index 50a3aa11cd81535fc4a5abdfba76b054e5f39113..bf8939b75617a6dd03480f32d9039c2a23753c08 100644
--- a/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/ValidationTasksTable.tsx
+++ b/employee-portal/src/lib/baseModule/components/gdpr/validationTasks/ValidationTasksTable.tsx
@@ -10,7 +10,7 @@ import {
   ApiGdprValidationTask,
   ApiGdprValidationTaskStatus,
   GetAllGdprValidationTasksRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 import { Chip } from "@mui/joy";
 import { useSuspenseQuery } from "@tanstack/react-query";
 import { createColumnHelper } from "@tanstack/react-table";
diff --git a/employee-portal/src/lib/baseModule/components/inboxProcedures/ContactForm.tsx b/employee-portal/src/lib/baseModule/components/inboxProcedures/ContactForm.tsx
index d4a3c75e338cbfcf516d9352f2a36429425cd44b..3dead1f47c49bef24ea4f160c1c42e6689c0d669 100644
--- a/employee-portal/src/lib/baseModule/components/inboxProcedures/ContactForm.tsx
+++ b/employee-portal/src/lib/baseModule/components/inboxProcedures/ContactForm.tsx
@@ -4,7 +4,6 @@
  */
 
 import { ApiSalutation } from "@eshg/base-api";
-import { ApiContactType } from "@eshg/employee-portal-api/businessProcedures";
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
@@ -17,11 +16,13 @@ import {
   buildEnumOptions,
   createFieldNameMapper,
 } from "@eshg/lib-portal/helpers/form";
+import { validateDateOfBirth } from "@eshg/lib-portal/helpers/validators";
 import {
   NestedFormProps,
   OptionalFieldValue,
 } from "@eshg/lib-portal/types/form";
 import { EnumMap } from "@eshg/lib-portal/types/helpers";
+import { ApiContactType } from "@eshg/lib-procedures-api";
 import { Divider, Grid, Stack, Typography } from "@mui/joy";
 import { useFormikContext } from "formik";
 
@@ -114,7 +115,11 @@ export function ContactForm(props: NestedFormProps) {
                 : undefined
             }
           />
-          <DateField name={fieldName("dateOfBirth")} label="Geburtsdatum" />
+          <DateField
+            name={fieldName("dateOfBirth")}
+            label="Geburtsdatum"
+            validate={validateDateOfBirth}
+          />
           <Divider />
           <AddressForm name={fieldName("address")} />
         </Stack>
diff --git a/employee-portal/src/lib/baseModule/components/inboxProcedures/CreateInboxProcedureForm.tsx b/employee-portal/src/lib/baseModule/components/inboxProcedures/CreateInboxProcedureForm.tsx
index 6ec1f34419f30a33ef5654c036e6ace7d23ee9b4..8c9a568b2f6befc0d14caa391739311e37318766 100644
--- a/employee-portal/src/lib/baseModule/components/inboxProcedures/CreateInboxProcedureForm.tsx
+++ b/employee-portal/src/lib/baseModule/components/inboxProcedures/CreateInboxProcedureForm.tsx
@@ -4,11 +4,11 @@
  */
 
 import { ApiBaseFeature, ApiBusinessModule } from "@eshg/base-api";
-import { ApiProcedureType } from "@eshg/employee-portal-api/businessProcedures";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+import { ApiProcedureType } from "@eshg/lib-procedures-api";
 import { Box, Grid, Typography } from "@mui/joy";
 import { Formik } from "formik";
 import { useMemo } from "react";
diff --git a/employee-portal/src/lib/baseModule/components/inboxProcedures/InboxProgressEntryForm.tsx b/employee-portal/src/lib/baseModule/components/inboxProcedures/InboxProgressEntryForm.tsx
index 0bbc40eb4b19c3a3f5c7cbcb59691c4b9be89959..5910be1e5d0825ec752e2446824018cbc2df7b02 100644
--- a/employee-portal/src/lib/baseModule/components/inboxProcedures/InboxProgressEntryForm.tsx
+++ b/employee-portal/src/lib/baseModule/components/inboxProcedures/InboxProgressEntryForm.tsx
@@ -5,7 +5,6 @@
 
 "use client";
 
-import { ApiInboxProgressEntryType } from "@eshg/employee-portal-api/businessProcedures";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { FileType } from "@eshg/lib-portal/components/formFields/file/FileType";
@@ -19,6 +18,7 @@ import {
   OptionalFieldValue,
 } from "@eshg/lib-portal/types/form";
 import { EnumMap } from "@eshg/lib-portal/types/helpers";
+import { ApiInboxProgressEntryType } from "@eshg/lib-procedures-api";
 import { Grid, Stack, Typography } from "@mui/joy";
 import { useFormikContext } from "formik";
 
diff --git a/employee-portal/src/lib/baseModule/components/inboxProcedures/mapper.ts b/employee-portal/src/lib/baseModule/components/inboxProcedures/mapper.ts
index 136563a0b8a514e80c862264328336c5719e6ac6..73db9e0329c298261b180ef6fb2a644fccfa040f 100644
--- a/employee-portal/src/lib/baseModule/components/inboxProcedures/mapper.ts
+++ b/employee-portal/src/lib/baseModule/components/inboxProcedures/mapper.ts
@@ -3,6 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { AcademicTitle } from "@eshg/lib-portal/components/formFields/constants";
+import { toUtcDate } from "@eshg/lib-portal/helpers/dateTime";
+import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
 import {
   ApiContactDetails,
   ApiContactType,
@@ -11,10 +14,7 @@ import {
   ApiInboxProcedureAddress,
   ApiInboxProgressEntryType,
   ApiTitle,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { AcademicTitle } from "@eshg/lib-portal/components/formFields/constants";
-import { toUtcDate } from "@eshg/lib-portal/helpers/dateTime";
-import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
+} from "@eshg/lib-procedures-api";
 import { isEmpty } from "remeda";
 
 import { AddressValues } from "@/lib/baseModule/components/inboxProcedures/AddressForm";
diff --git a/employee-portal/src/lib/baseModule/components/layout/sideNavigation/NavigationListCollapsed.tsx b/employee-portal/src/lib/baseModule/components/layout/sideNavigation/NavigationListCollapsed.tsx
index 073ff5c488dcb16c18e7c3713ec66a3a54165dfb..28bda5c383d52b4c7ae51340b4e8fc437417563a 100644
--- a/employee-portal/src/lib/baseModule/components/layout/sideNavigation/NavigationListCollapsed.tsx
+++ b/employee-portal/src/lib/baseModule/components/layout/sideNavigation/NavigationListCollapsed.tsx
@@ -38,45 +38,52 @@ export function NavigationListCollapsed({
   setCollapsed?: Dispatch<SetStateAction<boolean>>;
   itemGroups: SideNavItemGroups;
 }) {
-  const [menuIndex, setMenuIndex] = useState<null | number>(null);
+  const [openMenuItemName, setOpenMenuItemName] = useState<string | null>(null);
 
   const itemProps = {
-    onClick: () => setMenuIndex(null),
+    onClick: () => setOpenMenuItemName(null),
   };
   const pathname = usePathname();
-  // eslint-disable-next-line func-style
-  const createHandleLeaveMenu =
-    (index: number) => (getIsOnButton: () => boolean) => {
+
+  function createHandleLeaveMenu(itemName: string) {
+    return (getIsOnButton: () => boolean) => {
       setTimeout(() => {
         const isOnButton = getIsOnButton();
         if (!isOnButton) {
-          setMenuIndex((latestIndex: null | number) => {
-            if (index === latestIndex) {
+          setOpenMenuItemName((previousOpenMenuItemName) => {
+            if (itemName === previousOpenMenuItemName) {
               return null;
             }
-            return latestIndex;
+            return previousOpenMenuItemName;
           });
         }
       }, 200);
     };
+  }
 
   function getNavItemGroup(itemGroup: SideNavigationItem[]) {
-    if (itemGroup.length > 0) {
-      const list = itemGroup.map((item, index) =>
-        "subItems" in item ? (
+    if (itemGroup.length === 0) {
+      return undefined;
+    }
+
+    const list = itemGroup.map((item) => {
+      if ("subItems" in item) {
+        const isItemMenuOpen = openMenuItemName === item.name;
+
+        return (
           <NavigationIconItemWithSubItems
             key={item.name}
             item={item}
-            open={menuIndex === index}
-            onOpen={() => setMenuIndex(index)}
-            onLeaveMenu={createHandleLeaveMenu(index)}
+            open={isItemMenuOpen}
+            onOpen={() => setOpenMenuItemName(item.name)}
+            onLeaveMenu={createHandleLeaveMenu(item.name)}
             selected={
-              menuIndex !== index &&
+              !isItemMenuOpen &&
               item.subItems.some((subItem) => isItemSelected(subItem, pathname))
             }
             menu={
               <Menu
-                onClose={() => setMenuIndex(null)}
+                onClose={() => setOpenMenuItemName(null)}
                 keepMounted={true}
                 disablePortal={true}
               >
@@ -110,16 +117,17 @@ export function NavigationListCollapsed({
           >
             {item.decorator}
           </NavigationIconItemWithSubItems>
-        ) : (
-          <NavigationIconItemWithoutSubItems
-            key={`${item.href}-${item.name}`}
-            item={item}
-            resetActiveIndex={() => setMenuIndex(index)}
-          />
-        ),
+        );
+      }
+      return (
+        <NavigationIconItemWithoutSubItems
+          key={item.name}
+          item={item}
+          resetActiveIndex={() => setOpenMenuItemName(null)}
+        />
       );
-      return <StyledList sx={listStyling}>{list}</StyledList>;
-    } else return undefined;
+    });
+    return <StyledList sx={listStyling}>{list}</StyledList>;
   }
 
   return (
diff --git a/employee-portal/src/lib/baseModule/components/procedureMetrics/ProcedureMetricsDisplay.tsx b/employee-portal/src/lib/baseModule/components/procedureMetrics/ProcedureMetricsDisplay.tsx
index 9ffb533c9b7e2d24e6dc517f663cf1f65bf35f74..7d016a9adb660c09514186bb0461a10f688cfbc2 100644
--- a/employee-portal/src/lib/baseModule/components/procedureMetrics/ProcedureMetricsDisplay.tsx
+++ b/employee-portal/src/lib/baseModule/components/procedureMetrics/ProcedureMetricsDisplay.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiProcedureMetric } from "@eshg/employee-portal-api/inspection";
+import { ApiProcedureMetric } from "@eshg/inspection-api";
 import {
   CheckOutlined,
   DeviceHubOutlined,
diff --git a/employee-portal/src/lib/baseModule/components/task/Teamview.tsx b/employee-portal/src/lib/baseModule/components/task/Teamview.tsx
index 49a342be85820c9c850d5a471629bdfca761514b..e1a528478201f2b615114378e07c50fe70644c55 100644
--- a/employee-portal/src/lib/baseModule/components/task/Teamview.tsx
+++ b/employee-portal/src/lib/baseModule/components/task/Teamview.tsx
@@ -5,11 +5,7 @@
 
 "use client";
 
-import {
-  ApiBusinessModule,
-  ApiTask,
-  ApiUser,
-} from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule, ApiTask, ApiUser } from "@eshg/lib-procedures-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { differenceInDays } from "date-fns";
 import { useState } from "react";
diff --git a/employee-portal/src/lib/baseModule/theme/theme.ts b/employee-portal/src/lib/baseModule/theme/theme.ts
index 1da006b037580c46c1379f4e9e624313e44c8e74..ba1d5d77c42f79151c13c63f1c85df9aa782e7a9 100644
--- a/employee-portal/src/lib/baseModule/theme/theme.ts
+++ b/employee-portal/src/lib/baseModule/theme/theme.ts
@@ -35,6 +35,12 @@ declare module "@mui/joy/styles/types/zIndex" {
   }
 }
 
+declare module "@mui/joy/ToggleButtonGroup" {
+  interface ToggleButtonGroupPropsVariantOverrides {
+    tabs: true;
+  }
+}
+
 type FontSizeOverrides = { [_k in keyof FontSize]: true };
 declare module "@mui/joy/SvgIcon" {
   // eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -49,7 +55,7 @@ const noBoxShadow = {
   boxShadow: "none",
 };
 
-export function multiLineEllipsis(linesToShow = 2): SxProps {
+export function multiLineEllipsis(linesToShow = 2) {
   return {
     display: "-webkit-box",
     WebkitBoxOrient: "vertical",
@@ -57,7 +63,7 @@ export function multiLineEllipsis(linesToShow = 2): SxProps {
     lineClamp: String(linesToShow),
     overflow: "hidden",
     textOverflow: "ellipsis",
-  };
+  } satisfies SxProps;
 }
 
 function fixOutlinedHeight(variant?: string, size?: string) {
@@ -447,16 +453,33 @@ export const theme = extendTheme({
     },
     JoyToggleButtonGroup: {
       styleOverrides: {
-        root: ({ ownerState }) => {
-          if (ownerState.color === "primary") {
-            return {
-              ".MuiButton-variantOutlined": {
-                color: "var(--joy-palette-primary-600)",
+        root: ({ ownerState, theme }) => ({
+          ...(ownerState.color === "primary" && {
+            ".MuiButton-variantOutlined": {
+              color: "var(--joy-palette-primary-600)",
+            },
+          }),
+          ...(ownerState.variant === "tabs" && {
+            ".MuiButton-variantTabs": {
+              backgroundColor: theme.palette.background.level1,
+              "--ButtonGroup-separatorColor": "#636B744D",
+              "&[aria-pressed=true]": {
+                zIndex: 2,
+                backgroundColor: theme.palette.primary.solidBg,
+                color: "white",
+                "&[data-first-child]": {
+                  borderLeft: `1px solid ${theme.palette.primary.solidBg}`,
+                },
               },
-            };
-          }
-          return {};
-        },
+              "&[aria-pressed=false]": {
+                fontWeight: 400,
+                "&:hover": {
+                  zIndex: 1,
+                },
+              },
+            },
+          }),
+        }),
       },
     },
     JoyCheckbox: {
diff --git a/employee-portal/src/lib/businessModules/chat/api/clients.ts b/employee-portal/src/lib/businessModules/chat/api/clients.ts
index f098d50cfaa402111ef77e56ca10c208decdd32c..ec71169b9a9690d29c03b03bd6e67a00a03b48a0 100644
--- a/employee-portal/src/lib/businessModules/chat/api/clients.ts
+++ b/employee-portal/src/lib/businessModules/chat/api/clients.ts
@@ -7,7 +7,7 @@ import {
   ChatFeatureTogglesApi,
   Configuration,
   UserSettingsApi,
-} from "@eshg/employee-portal-api/chatManagement";
+} from "@eshg/chat-management-api";
 import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
 
 function useConfiguration() {
diff --git a/employee-portal/src/lib/businessModules/chat/api/mutations/userSettingsApi.ts b/employee-portal/src/lib/businessModules/chat/api/mutations/userSettingsApi.ts
index 94854799a22656e718aba224bb8bdd48713c8ac9..fef4629e67b730eb4a9f2518c2b3eb7d94214c49 100644
--- a/employee-portal/src/lib/businessModules/chat/api/mutations/userSettingsApi.ts
+++ b/employee-portal/src/lib/businessModules/chat/api/mutations/userSettingsApi.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUserSettingsRequest } from "@eshg/employee-portal-api/chatManagement";
+import { ApiUserSettingsRequest } from "@eshg/chat-management-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { useMutation } from "@tanstack/react-query";
 
diff --git a/employee-portal/src/lib/businessModules/chat/api/queries/featureTogglesApi.ts b/employee-portal/src/lib/businessModules/chat/api/queries/featureTogglesApi.ts
index 5ee36065830c96254b6182ffe95b84a0f6be40a8..a1068c6a5f64626b9c28208e009eaa2197bd4ff9 100644
--- a/employee-portal/src/lib/businessModules/chat/api/queries/featureTogglesApi.ts
+++ b/employee-portal/src/lib/businessModules/chat/api/queries/featureTogglesApi.ts
@@ -6,7 +6,7 @@
 import {
   ApiChatFeature,
   ApiGetFeatureTogglesResponse,
-} from "@eshg/employee-portal-api/chatManagement";
+} from "@eshg/chat-management-api";
 import {
   FeatureToggleQueryOptions,
   selectDisabledOldFeature,
diff --git a/employee-portal/src/lib/businessModules/chat/components/ChatAvatar.tsx b/employee-portal/src/lib/businessModules/chat/components/ChatAvatar.tsx
index b68e637e32cfcb9182d70c6dd59f66492ebda8d0..b93cc951412778709da306b33985b88161ef9301 100644
--- a/employee-portal/src/lib/businessModules/chat/components/ChatAvatar.tsx
+++ b/employee-portal/src/lib/businessModules/chat/components/ChatAvatar.tsx
@@ -42,7 +42,7 @@ export function ChatAvatar({
       variant="solid"
       color="warning"
       size={size}
-      src={props.avatarUrl ? props.avatarUrl : undefined}
+      src={props.avatarUrl ?? undefined}
     >
       <GroupOutlinedIcon size="md" sx={{ color: "white" }} />
     </Avatar>
diff --git a/employee-portal/src/lib/businessModules/chat/shared/ChatProvider.tsx b/employee-portal/src/lib/businessModules/chat/shared/ChatProvider.tsx
index 3e25f2a30a092ebe3b2963380faae5cfdf2c65fc..a5b86ee1289f84ecfa01c394fb2f2d6d7cb97339 100644
--- a/employee-portal/src/lib/businessModules/chat/shared/ChatProvider.tsx
+++ b/employee-portal/src/lib/businessModules/chat/shared/ChatProvider.tsx
@@ -6,7 +6,7 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiChatFeature } from "@eshg/employee-portal-api/chatManagement";
+import { ApiChatFeature } from "@eshg/chat-management-api";
 import { RequiresChildren } from "@eshg/lib-portal/types/react";
 import { createContext, useContext, useMemo } from "react";
 import { doNothing, isNullish, omit } from "remeda";
diff --git a/employee-portal/src/lib/businessModules/dental/features/children/ChildrenFilterSettings.tsx b/employee-portal/src/lib/businessModules/dental/features/children/ChildrenFilterSettings.tsx
index bd39d03a755b79eef48cfbd7d392b49704dc5b51..1c93e5276c56a9048ff4b3d1ea3603f8be1dca9f 100644
--- a/employee-portal/src/lib/businessModules/dental/features/children/ChildrenFilterSettings.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/children/ChildrenFilterSettings.tsx
@@ -85,6 +85,7 @@ export function ChildrenFilterSettings(props: ChildrenFilterSettingsProps) {
             onChange={(institutionId) => {
               props.setFilterFormValue("institutionIdFilter", institutionId);
             }}
+            placeholder="Schule/Kita suchen"
           />
         </FormControl>
         <FormControl>
diff --git a/employee-portal/src/lib/businessModules/dental/features/children/ChildrenTable.tsx b/employee-portal/src/lib/businessModules/dental/features/children/ChildrenTable.tsx
index df1acbe3a19ec7b1e271151aa92f546832d4cb7b..f8b1eb8ffb0b78e3091846172279b886107ac5f2 100644
--- a/employee-portal/src/lib/businessModules/dental/features/children/ChildrenTable.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/children/ChildrenTable.tsx
@@ -9,9 +9,9 @@ import { ApiChildSortKey } from "@eshg/dental-api";
 import { Child } from "@eshg/dental/api/models/Child";
 import { useGetChildrenQuery } from "@eshg/dental/api/queries/childApi";
 import { routes } from "@eshg/dental/shared/routes";
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { useToggleableState } from "@eshg/lib-portal/hooks/useToggleableState";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { ColumnSort, createColumnHelper } from "@tanstack/react-table";
 import { ReactNode } from "react";
diff --git a/employee-portal/src/lib/businessModules/dental/features/children/details/ChildDetails.tsx b/employee-portal/src/lib/businessModules/dental/features/children/details/ChildDetails.tsx
index 347031cee5caf4c74c92d6d2f9f21e5d33731e79..f95c7d0e3e33d8db59fbf085892e5eb39482cdf4 100644
--- a/employee-portal/src/lib/businessModules/dental/features/children/details/ChildDetails.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/children/details/ChildDetails.tsx
@@ -14,8 +14,8 @@ import { useUpdateAnnualChildSidebar } from "@/lib/businessModules/dental/featur
 import { IconTooltipButton } from "@/lib/shared/components/buttons/IconTooltipButton";
 import { CentralFilePersonDetails } from "@/lib/shared/components/centralFile/display/CentralFilePersonDetails";
 import { ContentPanel } from "@/lib/shared/components/contentPanel/ContentPanel";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsSection } from "@/lib/shared/components/detailsSection/DetailsSection";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { PageGrid } from "@/lib/shared/components/page/PageGrid";
 import { displayBoolean } from "@/lib/shared/helpers/booleans";
 
@@ -58,16 +58,8 @@ export function ChildDetailsPage(props: ChildDetailsProps) {
             canEdit={!disabled}
           >
             <Stack gap={1}>
-              <DetailsCell
-                name="institution"
-                label="Einrichtung"
-                value={child.institution.name}
-              />
-              <DetailsCell
-                name="group"
-                label="Gruppe"
-                value={child.groupName}
-              />
+              <DetailsItem label="Einrichtung" value={child.institution.name} />
+              <DetailsItem label="Gruppe" value={child.groupName} />
               {child.currentFluoridationConsent ? (
                 <>
                   <Divider />
@@ -84,22 +76,19 @@ export function ChildDetailsPage(props: ChildDetailsProps) {
                     />
                   </Typography>
                   <Stack direction="row" gap={2} flexWrap="wrap">
-                    <DetailsCell
-                      name="fluoridationConsent"
+                    <DetailsItem
                       label="Einverständis"
                       value={displayBoolean(
                         child.currentFluoridationConsent.consented,
                       )}
                     />
-                    <DetailsCell
-                      name="fluoridationConsentDate"
+                    <DetailsItem
                       label="Datum der Einverständniserklärung"
                       value={formatDate(
                         child.currentFluoridationConsent.dateOfConsent,
                       )}
                     />
-                    <DetailsCell
-                      name="allergy"
+                    <DetailsItem
                       label="Allergie"
                       value={displayBoolean(
                         child.currentFluoridationConsent.hasAllergy,
@@ -108,8 +97,7 @@ export function ChildDetailsPage(props: ChildDetailsProps) {
                   </Stack>
                 </>
               ) : (
-                <DetailsCell
-                  name="fluoridationConsent"
+                <DetailsItem
                   label="Einverständis zur Fluoridierung"
                   value="Liegt nicht vor"
                 />
diff --git a/employee-portal/src/lib/businessModules/dental/features/children/details/ChildExaminationForm.tsx b/employee-portal/src/lib/businessModules/dental/features/children/details/ChildExaminationForm.tsx
index 531130142f97686870ed2d09fe9a27df7a7b83ef..2afecf48329ef1ebfa5f961285fa3ea3e43aee5e 100644
--- a/employee-portal/src/lib/businessModules/dental/features/children/details/ChildExaminationForm.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/children/details/ChildExaminationForm.tsx
@@ -5,23 +5,57 @@
 
 "use client";
 
-import { FormProps } from "@eshg/lib-portal/types/form";
+import {
+  ApiExaminationResult,
+  UpdateExaminationRequest,
+} from "@eshg/dental-api";
+import { Examination } from "@eshg/dental/api/models/Examination";
+import { ToothDiagnoses } from "@eshg/dental/api/models/ExaminationResult";
+import { useUpdateExamination } from "@eshg/dental/api/mutations/childApi";
+import {
+  mapOptionalValue,
+  mapRequiredValue,
+} from "@eshg/lib-portal/helpers/form";
 import { RequiresChildren } from "@eshg/lib-portal/types/react";
 import { Formik } from "formik";
 
-import { ExaminationFormValues } from "@/lib/businessModules/dental/features/examinations/ExaminationFormLayout";
+import {
+  ExaminationFormValues,
+  mapToExaminationFormValues,
+} from "@/lib/businessModules/dental/features/examinations/ExaminationFormLayout";
+import { useDentalExaminationStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
 import { FormFooter } from "@/lib/businessModules/schoolEntry/features/procedures/examinations/FormFooter";
 import { FormStack } from "@/lib/shared/components/form/FormStack";
 
-interface ChildExaminationFormProps
-  extends FormProps<ExaminationFormValues>,
-    RequiresChildren {}
+interface ChildExaminationFormProps extends RequiresChildren {
+  examination: Examination;
+}
 
 export function ChildExaminationForm(props: ChildExaminationFormProps) {
+  const { examination } = props;
+  const getToothDiagnoses = useDentalExaminationStore(
+    (state) => state.getToothDiagnoses,
+  );
+  const updateExamination = useUpdateExamination(examination.id);
+
+  async function handleSubmit(values: ExaminationFormValues) {
+    try {
+      const toothDiagnoses = getToothDiagnoses();
+      await updateExamination.mutateAsync(
+        mapToRequest(examination, values, toothDiagnoses),
+      );
+    } catch {
+      // TODO handle invalid tooth diagnoses
+    }
+  }
+
   return (
     <Formik
-      initialValues={props.initialValues}
-      onSubmit={props.onSubmit}
+      initialValues={mapToExaminationFormValues(
+        examination.result,
+        examination.note,
+      )}
+      onSubmit={handleSubmit}
       enableReinitialize
     >
       {({ handleSubmit, isSubmitting }) => {
@@ -35,3 +69,49 @@ export function ChildExaminationForm(props: ChildExaminationFormProps) {
     </Formik>
   );
 }
+
+function mapToRequest(
+  examination: Examination,
+  formValues: ExaminationFormValues,
+  toothDiagnoses: ToothDiagnoses,
+): UpdateExaminationRequest {
+  return {
+    examinationId: examination.id,
+    apiUpdateExaminationRequest: {
+      version: examination.version,
+      note: mapOptionalValue(formValues.note),
+      result: mapExaminationResultRequest(
+        examination,
+        formValues,
+        toothDiagnoses,
+      ),
+    },
+  };
+}
+
+function mapExaminationResultRequest(
+  examination: Examination,
+  formValues: ExaminationFormValues,
+  toothDiagnoses: ToothDiagnoses,
+): ApiExaminationResult | undefined {
+  if (examination.screening) {
+    return {
+      type: "ScreeningExaminationResult",
+      oralHygieneStatus: mapOptionalValue(formValues.oralHygieneStatus),
+      fluorideVarnishApplied:
+        mapOptionalValue(formValues.fluorideVarnishApplied) ?? false,
+      toothDiagnoses: Object.values(toothDiagnoses),
+    };
+  }
+
+  if (examination.fluoridation) {
+    return {
+      type: "FluoridationExaminationResult",
+      fluorideVarnishApplied: mapRequiredValue(
+        formValues.fluorideVarnishApplied,
+      ),
+    };
+  }
+
+  return undefined;
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/children/new/CreateChildSidebar.tsx b/employee-portal/src/lib/businessModules/dental/features/children/new/CreateChildSidebar.tsx
index 9534a6f063f6f15e1179cf724bce47a9240dda91..fec50204e135f498b70affde5250c2b40f7743fc 100644
--- a/employee-portal/src/lib/businessModules/dental/features/children/new/CreateChildSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/children/new/CreateChildSidebar.tsx
@@ -73,6 +73,7 @@ function DentalSearchFormComponent(
         label="Einrichtung"
         categories={SCHOOL_OR_DAYCARE}
         required="Bitte eine Schule/Kita angeben."
+        placeholder="Schule/Kita suchen"
         getOptionLabel={getInstitutionOptionLabel}
       />
       <SearchGroupField
diff --git a/employee-portal/src/lib/businessModules/dental/features/examinations/AdditionalInformationFormSection.tsx b/employee-portal/src/lib/businessModules/dental/features/examinations/AdditionalInformationFormSection.tsx
index cf5decc3f088109a5e3cdd56c8b1b145b8a96267..20f7e9706ee8fcf4456044cf6448169899110e8a 100644
--- a/employee-portal/src/lib/businessModules/dental/features/examinations/AdditionalInformationFormSection.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/examinations/AdditionalInformationFormSection.tsx
@@ -4,29 +4,21 @@
  */
 
 import { ApiOralHygieneStatus } from "@eshg/dental-api";
+import { ExaminationStatus } from "@eshg/dental/api/models/ExaminationStatus";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import {
-  BooleanSelectField,
-  BooleanSelectFieldProps,
-} from "@eshg/lib-portal/components/formFields/BooleanSelectField";
-import {
-  SelectField,
-  SelectFieldProps,
-} from "@eshg/lib-portal/components/formFields/SelectField";
+  SoftRequiredBooleanSelectField,
+  SoftRequiredSelectField,
+} from "@eshg/lib-portal/components/form/fieldVariants";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
-import { ReactNode } from "react";
 
+import { ExaminationStatusChip } from "@/lib/businessModules/dental/features/examinations/ExaminationStatusChip";
 import { DetailsSection } from "@/lib/shared/components/detailsSection/DetailsSection";
 import { InformationSheet } from "@/lib/shared/components/infoTile/InformationSheet";
 
 import { ORAL_HYGIENE_STATUS } from "./translations";
 
-const DEFAULT_COMPONENTS: AdditionalInformationFormComponents = {
-  SelectField,
-  BooleanSelectField,
-};
-
 export const ORAL_HYGIENE_STATUS_OPTIONS =
   buildEnumOptions<ApiOralHygieneStatus>(ORAL_HYGIENE_STATUS, true);
 
@@ -35,44 +27,32 @@ export interface AdditionalInformationFormValues {
   fluorideVarnishApplied: OptionalFieldValue<boolean>;
 }
 
-export interface AdditionalInformationFormComponents {
-  SelectField: <
-    TMultiple extends boolean = false,
-    TOptionLabel extends string | ReactNode = string,
-  >(
-    props: SelectFieldProps<TMultiple, TOptionLabel>,
-  ) => ReactNode;
-  BooleanSelectField: (props: BooleanSelectFieldProps) => ReactNode;
-}
-
 interface AdditionalInformationFormSectionProps {
   screening: boolean;
   fluoridation: boolean;
   fluoridationConsentGiven?: boolean;
-  components?: AdditionalInformationFormComponents;
+  status: ExaminationStatus;
 }
 
 export function AdditionalInformationFormSection(
   props: AdditionalInformationFormSectionProps,
 ) {
-  const { screening, fluoridation, fluoridationConsentGiven, components } =
-    props;
-
-  const { SelectField, BooleanSelectField } = components ?? DEFAULT_COMPONENTS;
+  const { screening, fluoridation, fluoridationConsentGiven } = props;
 
   return (
     <InformationSheet>
       <DetailsSection title="Zusatzinfos">
+        <ExaminationStatusChip status={props.status} />
         {screening && (
-          <SelectField
+          <SoftRequiredSelectField
             name="oralHygieneStatus"
             label="Mundhygienestatus"
             options={ORAL_HYGIENE_STATUS_OPTIONS}
+            orientation="vertical"
           />
         )}
         {fluoridation && (
           <FluoridationField
-            component={BooleanSelectField}
             fluoridationConsentGiven={fluoridationConsentGiven}
           />
         )}
@@ -82,7 +62,6 @@ export function AdditionalInformationFormSection(
 }
 
 interface FluoridationFieldProps {
-  component: AdditionalInformationFormComponents["BooleanSelectField"];
   fluoridationConsentGiven?: boolean;
 }
 
@@ -96,13 +75,12 @@ function FluoridationField(props: FluoridationFieldProps) {
     );
   }
 
-  const FieldComponent = props.component;
-
   return (
-    <FieldComponent
+    <SoftRequiredBooleanSelectField
       name="fluorideVarnishApplied"
       label="Fluoridierung"
-      required="Bitte angeben, ob fluoridiert wurde."
+      orientation="vertical"
+      softRequired
     />
   );
 }
diff --git a/employee-portal/src/lib/businessModules/dental/features/examinations/ExaminationFormLayout.tsx b/employee-portal/src/lib/businessModules/dental/features/examinations/ExaminationFormLayout.tsx
index 6e5a4f30cb96cf576bae07ed3e8082e577067341..80a268ed7526a3b9f6a0058e478299f489e13e1d 100644
--- a/employee-portal/src/lib/businessModules/dental/features/examinations/ExaminationFormLayout.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/examinations/ExaminationFormLayout.tsx
@@ -9,6 +9,7 @@ import { ExaminationResult } from "@eshg/dental/api/models/ExaminationResult";
 import { parseOptionalValue } from "@eshg/lib-portal/helpers/form";
 import { Grid } from "@mui/joy";
 import { ReactNode } from "react";
+import { isDefined } from "remeda";
 
 import { PageGrid } from "@/lib/shared/components/page/PageGrid";
 
@@ -21,17 +22,21 @@ export interface ExaminationFormValues
 
 interface ExaminationFormLayoutProps {
   additionalInformation: ReactNode;
+  dentalExamination?: ReactNode;
   note: ReactNode;
 }
 
 export function ExaminationFormLayout(props: ExaminationFormLayoutProps) {
   return (
     <PageGrid>
-      <Grid xxs={12} md={4}>
+      <Grid xxs={12} md={3}>
         {props.additionalInformation}
       </Grid>
-      <Grid xxs={12} md={8}>
-        {props.note}
+      <Grid container xxs={12} md={9}>
+        {isDefined(props.dentalExamination) && (
+          <Grid xxs={12}>{props.dentalExamination}</Grid>
+        )}
+        <Grid xxs={12}>{props.note}</Grid>
       </Grid>
     </PageGrid>
   );
diff --git a/employee-portal/src/lib/businessModules/dental/features/examinations/ExaminationStatusChip.tsx b/employee-portal/src/lib/businessModules/dental/features/examinations/ExaminationStatusChip.tsx
index 0bff96c02b1deaca56da03440859384ede38c758..f1cb4c927e6e49af649140000211c30a77ad56f2 100644
--- a/employee-portal/src/lib/businessModules/dental/features/examinations/ExaminationStatusChip.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/examinations/ExaminationStatusChip.tsx
@@ -11,6 +11,7 @@ import { EXAMINATION_STATUS } from "./translations";
 const examinationStatusColors: Record<ExaminationStatus, ChipProps["color"]> = {
   OPEN: "neutral",
   CLOSED: "success",
+  NOT_PRESENT: "danger",
 };
 
 interface ExaminationStatusChipProps {
diff --git a/employee-portal/src/lib/businessModules/dental/features/examinations/translations.ts b/employee-portal/src/lib/businessModules/dental/features/examinations/translations.ts
index 42d96b8b95cea5547d8806a39d3989c280252da1..27bc982605a35421920b8f4e7520b8ff2cf3f758 100644
--- a/employee-portal/src/lib/businessModules/dental/features/examinations/translations.ts
+++ b/employee-portal/src/lib/businessModules/dental/features/examinations/translations.ts
@@ -9,6 +9,7 @@ import { ExaminationStatus } from "@eshg/dental/api/models/ExaminationStatus";
 export const EXAMINATION_STATUS: Record<ExaminationStatus, string> = {
   OPEN: "offen",
   CLOSED: "abgeschlossen",
+  NOT_PRESENT: "Nicht anwesend",
 };
 
 export const ORAL_HYGIENE_STATUS: Record<ApiOralHygieneStatus, string> = {
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ChangeReasonForAbsenceModal.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ChangeReasonForAbsenceModal.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b2e8bd084bbedd4dce2b61cb3c3dda95022b5c3f
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ChangeReasonForAbsenceModal.tsx
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  ApiReasonForAbsence,
+  UpdateExaminationRequest,
+} from "@eshg/dental-api";
+import { ChildExamination } from "@eshg/dental/api/models/ChildExamination";
+import { useUpdateExamination } from "@eshg/dental/api/mutations/childApi";
+import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
+import {
+  buildEnumOptions,
+  mapRequiredValue,
+} from "@eshg/lib-portal/helpers/form";
+import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+import { isDefined } from "remeda";
+
+import { FormDialog } from "@/lib/shared/components/formDialog/FormDialog";
+
+const ABSENCE_VALUES: Record<ApiReasonForAbsence, string> = {
+  [ApiReasonForAbsence.NotAppeared]: "Nicht erschienen",
+  [ApiReasonForAbsence.Refused]: "Verweigert",
+  [ApiReasonForAbsence.Shifted]: "Versetzt",
+  [ApiReasonForAbsence.Moved]: "Umgezogen",
+};
+
+const ABSENCE_OPTIONS = buildEnumOptions(ABSENCE_VALUES);
+
+interface ReasonForAbsenceFormValues {
+  reasonForAbsence: OptionalFieldValue<ApiReasonForAbsence>;
+}
+
+interface ChangeReasonForAbsenceModalProps {
+  onClose: () => void;
+  examination: ChildExamination;
+}
+
+export function ChangeReasonForAbsenceModal(
+  props: ChangeReasonForAbsenceModalProps,
+) {
+  const updateExamination = useUpdateExamination(
+    props.examination.examinationId,
+  );
+
+  async function onSubmit(values: ReasonForAbsenceFormValues) {
+    await updateExamination.mutateAsync(
+      mapToRequest(
+        props.examination.examinationId,
+        values,
+        props.examination.examinationVersion,
+      ),
+      { onSuccess: props.onClose },
+    );
+  }
+  const examinationResult = props.examination.result;
+  const initialReasonForAbsence =
+    isDefined(examinationResult) && examinationResult.type === "absence"
+      ? examinationResult.reasonForAbsence
+      : "";
+
+  return (
+    <FormDialog<ReasonForAbsenceFormValues>
+      open
+      onClose={props.onClose}
+      onSubmit={onSubmit}
+      initialValues={{ reasonForAbsence: initialReasonForAbsence }}
+      title="Abwesenheit vermerken"
+      description="Bitte geben Sie einen Grund für die Abwesenheit ein."
+      color="primary"
+      confirmLabel="Speichern"
+      cancelLabel="Abbrechen"
+    >
+      <SelectField
+        sx={{ paddingTop: 2 }}
+        name="reasonForAbsence"
+        label="Grund"
+        required="Bitte einen Grund angeben."
+        options={ABSENCE_OPTIONS}
+      />
+    </FormDialog>
+  );
+}
+
+function mapToRequest(
+  examinationId: string,
+  values: ReasonForAbsenceFormValues,
+  version: number,
+): UpdateExaminationRequest {
+  return {
+    examinationId,
+    apiUpdateExaminationRequest: {
+      version,
+      result: {
+        type: "AbsenceExaminationResult",
+        reasonForAbsence: mapRequiredValue(values.reasonForAbsence),
+      },
+    },
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/CreateProphylaxisSessionSidebar.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/CreateProphylaxisSessionSidebar.tsx
index caed5316b301aec9ae727eb7f6050b26662b2a96..3766357bd8197593675d82be77e3544f18833461 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/CreateProphylaxisSessionSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/CreateProphylaxisSessionSidebar.tsx
@@ -5,234 +5,88 @@
 
 "use client";
 
-import { ApiAddContact200Response } from "@eshg/base-api";
-import {
-  ApiCreateProphylaxisSessionRequest,
-  ApiFluoridationVarnish,
-  ApiProphylaxisType,
-} from "@eshg/dental-api";
 import { useCreateProphylaxisSession } from "@eshg/dental/api/mutations/prophylaxisSessionApi";
-import {
-  getAllDentalAssistantsQuery,
-  getAllDentistsQuery,
-} from "@eshg/dental/api/queries/staffApi";
-import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
-import { mapRequiredValue } from "@eshg/lib-portal/helpers/form";
-import { useHasChanged } from "@eshg/lib-portal/hooks/useHasChanged";
-import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
-import { Stack, Typography } from "@mui/joy";
-import { useSuspenseQueries } from "@tanstack/react-query";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { Formik } from "formik";
-import { forwardRef, useEffect } from "react";
 
-import { useUserApi } from "@/lib/baseModule/api/clients";
-import { SCHOOL_OR_DAYCARE } from "@/lib/baseModule/api/queries/contacts";
-import { FluoridationField } from "@/lib/businessModules/dental/features/prophylaxisSessions/FluoridationField";
-import { SearchGroupField } from "@/lib/businessModules/dental/features/prophylaxisSessions/SearchGroupField";
-import { PROPHYLAXIS_TYPE_OPTIONS } from "@/lib/businessModules/dental/features/prophylaxisSessions/options";
-import { AppointmentStaffField } from "@/lib/shared/components/appointmentBlocks/AppointmentStaffField";
-import { SelectionOption } from "@/lib/shared/components/appointmentBlocks/AppointmentStaffSelection";
-import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
 import {
-  SidebarForm,
-  SidebarFormHandle,
-} from "@/lib/shared/components/form/SidebarForm";
-import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
-import { DateTimeField } from "@/lib/shared/components/formFields/DateTimeField";
-import { SelectContactField } from "@/lib/shared/components/formFields/SelectContactField";
+  ProphylaxisSessionForm,
+  ProphylaxisSessionValues,
+  mapValues,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionForm";
+import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
+import { SidebarForm } from "@/lib/shared/components/form/SidebarForm";
 import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
 import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
-import { fullName } from "@/lib/shared/components/users/userFormatter";
-import { getInstitutionOptionLabel } from "@/lib/shared/helpers/selectOptionMapper";
 import {
   SidebarWithFormRefProps,
   useSidebarWithFormRef,
 } from "@/lib/shared/hooks/useSidebarWithFormRef";
 
+import { useGetStaff } from "./staff";
+
 export function useCreateProphylaxisSessionSidebar() {
   return useSidebarWithFormRef({
     component: CreateProphylaxisSessionSidebar,
   });
 }
 
-export interface CreateProphylaxisSessionValues {
-  dateAndTime: string;
-  institution: ApiAddContact200Response | null;
-  groupName: OptionalFieldValue<string>;
-  type: OptionalFieldValue<ApiProphylaxisType>;
-  isScreening: boolean;
-  isFluoridation: boolean;
-  fluoridationVarnish: OptionalFieldValue<ApiFluoridationVarnish>;
-  dentistIds: string[];
-  zfaIds: string[];
-}
-
 function CreateProphylaxisSessionSidebar(props: SidebarWithFormRefProps) {
   const createSession = useCreateProphylaxisSession();
-  const userApi = useUserApi();
-  const [{ data: allDentists }, { data: allDentalAssistants }] =
-    useSuspenseQueries({
-      queries: [
-        getAllDentistsQuery(userApi),
-        getAllDentalAssistantsQuery(userApi),
-      ],
-    });
+  const { allDentists, allDentalAssistants } = useGetStaff();
+  const snackbar = useSnackbar();
 
-  const dentistOptions = allDentists.map((dentist) => ({
-    value: dentist.userId,
-    label: fullName(dentist),
-  }));
+  const initialValues: ProphylaxisSessionValues = {
+    dateAndTime: "",
+    institution: "",
+    groupName: "",
+    type: "",
+    isScreening: false,
+    isFluoridation: false,
+    fluoridationVarnish: "",
+    dentistIds: [],
+    zfaIds: [],
+  };
 
-  const dentalAssistantOptions = allDentalAssistants.map((dentalAssistant) => ({
-    value: dentalAssistant.userId,
-    label: fullName(dentalAssistant),
-  }));
+  function onSubmit(values: ProphylaxisSessionValues) {
+    createSession
+      .mutateAsync(
+        {
+          ...mapValues(values),
+        },
+        {
+          onSuccess: () => props.onClose(true),
+        },
+      )
+      .catch(() =>
+        snackbar.error("Die Daten konnten nicht gespeichert werden."),
+      );
+  }
 
   return (
-    <Formik<CreateProphylaxisSessionValues>
-      initialValues={{
-        dateAndTime: "",
-        institution: null,
-        groupName: "",
-        type: "",
-        isScreening: false,
-        isFluoridation: false,
-        fluoridationVarnish: "",
-        dentistIds: [],
-        zfaIds: [],
-      }}
-      onSubmit={(values) =>
-        createSession.mutateAsync(mapValues(values), {
-          onSuccess: () => {
-            props.onClose(true);
-          },
-        })
-      }
+    <Formik<ProphylaxisSessionValues>
+      initialValues={initialValues}
+      onSubmit={onSubmit}
     >
       {({ values, handleSubmit, isSubmitting, setFieldValue }) => (
-        <CreateProphylaxisSessionSidebarForm
-          ref={props.formRef}
-          onSubmit={handleSubmit}
-          onClose={() => props.onClose(false)}
-          dentistOptions={dentistOptions}
-          zfaOptions={dentalAssistantOptions}
-          values={values}
-          isSubmitting={isSubmitting}
-          setFieldValue={setFieldValue}
-        />
+        <SidebarForm ref={props.formRef} onSubmit={handleSubmit}>
+          <SidebarContent title="Prophylaxe anlegen">
+            <ProphylaxisSessionForm
+              values={values}
+              setFieldValue={setFieldValue}
+              dentistOptions={allDentists}
+              dentalAssistantOptions={allDentalAssistants}
+            />
+          </SidebarContent>
+          <SidebarActions>
+            <FormButtonBar
+              submitLabel="Anlegen"
+              submitting={isSubmitting}
+              onCancel={() => props.onClose(false)}
+            />
+          </SidebarActions>
+        </SidebarForm>
       )}
     </Formik>
   );
 }
-
-interface CreateProphylaxisSessionSidebarFormProps {
-  onSubmit: () => void;
-  values: CreateProphylaxisSessionValues;
-  isSubmitting: boolean;
-  onClose: () => void;
-  dentistOptions: SelectionOption[];
-  zfaOptions: SelectionOption[];
-  setFieldValue: (field: "groupName", value: "") => void;
-}
-
-const CreateProphylaxisSessionSidebarForm = forwardRef<
-  SidebarFormHandle,
-  CreateProphylaxisSessionSidebarFormProps
->(function CreateProphylaxisSessionSidebarForm(
-  {
-    onSubmit,
-    values,
-    isSubmitting,
-    onClose,
-    dentistOptions,
-    zfaOptions,
-    setFieldValue,
-  }: CreateProphylaxisSessionSidebarFormProps,
-  ref,
-) {
-  const shouldClearGroupName = useHasChanged(values.institution);
-  useEffect(() => {
-    if (shouldClearGroupName) {
-      void setFieldValue("groupName", "");
-    }
-  }, [shouldClearGroupName, setFieldValue, values]);
-
-  return (
-    <SidebarForm ref={ref} onSubmit={onSubmit}>
-      <SidebarContent title="Prophylaxe anlegen">
-        <Stack gap={3}>
-          <DateTimeField
-            name="dateAndTime"
-            label="Datum und Uhrzeit"
-            required="Bitte ein Datum mit Uhrzeit angeben."
-          />
-          <SelectContactField
-            name="institution"
-            label="Einrichtung"
-            categories={SCHOOL_OR_DAYCARE}
-            required="Bitte eine Schule/Kita angeben."
-            getOptionLabel={getInstitutionOptionLabel}
-          />
-          <SearchGroupField
-            name="groupName"
-            label="Gruppe"
-            institutionId={values.institution?.id ?? ""}
-          />
-          <SelectField
-            name="type"
-            label="Typ"
-            options={PROPHYLAXIS_TYPE_OPTIONS}
-            required="Bitte den Typ der Prophylaxe angeben."
-          />
-          <CheckboxField name="isScreening" label="Reihenuntersuchung" />
-          <FluoridationField />
-          <Typography component="h3" level="title-sm">
-            Durchführende Personen
-          </Typography>
-          <AppointmentStaffField
-            name="dentistIds"
-            options={dentistOptions}
-            blockedStaff={[]}
-            freeStaff={[]}
-            label="Zahnarzt/-ärztin"
-            required="Bitte mindestens eine/n Zahnarzt/-ärztin angeben."
-          />
-          <AppointmentStaffField
-            name="zfaIds"
-            options={zfaOptions}
-            blockedStaff={[]}
-            freeStaff={[]}
-            label="ZFA"
-            required="Bitte mindestens eine/n ZFA angeben."
-          />
-        </Stack>
-      </SidebarContent>
-      <SidebarActions>
-        <FormButtonBar
-          submitLabel="Anlegen"
-          submitting={isSubmitting}
-          onCancel={() => {
-            onClose();
-          }}
-        />
-      </SidebarActions>
-    </SidebarForm>
-  );
-});
-
-function mapValues(
-  values: CreateProphylaxisSessionValues,
-): ApiCreateProphylaxisSessionRequest {
-  return {
-    dateAndTime: new Date(values.dateAndTime),
-    institutionId: mapRequiredValue(values.institution)?.id,
-    groupName: mapRequiredValue(values.groupName),
-    type: mapRequiredValue(values.type),
-    isScreening: values.isScreening,
-    fluoridationVarnish: values.isFluoridation
-      ? mapRequiredValue(values.fluoridationVarnish)
-      : undefined,
-    dentistIds: values.dentistIds,
-    zfaIds: values.zfaIds,
-  };
-}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/FluoridationField.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/FluoridationField.tsx
index 5e24c86e28c4d53d26db6faa53047e1d961e1aae..89d68da31c420991ed2c4e2a7459af99f4963dbd 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/FluoridationField.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/FluoridationField.tsx
@@ -10,18 +10,27 @@ import { useField } from "formik";
 import { FLUORIDATION_VARNISH_OPTIONS } from "@/lib/businessModules/dental/features/prophylaxisSessions/options";
 import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
 
-export function FluoridationField() {
+interface FluoridationFieldProps {
+  disabled?: boolean;
+}
+
+export function FluoridationField(props: FluoridationFieldProps) {
   const [isFluoridation] = useField<boolean>("isFluoridation");
 
   return (
     <Stack gap={3}>
-      <CheckboxField name="isFluoridation" label="Fluoridierung" />
+      <CheckboxField
+        name="isFluoridation"
+        label="Fluoridierung"
+        disabled={props.disabled}
+      />
       {isFluoridation.value && (
         <SelectField
           name="fluoridationVarnish"
           label="Lack"
           options={FLUORIDATION_VARNISH_OPTIONS}
           required="Bitte den Lack auswählen."
+          disabled={props.disabled}
         />
       )}
     </Stack>
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ParticipantFilter.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ParticipantFilter.tsx
index eb47d99b3e6e644efea2ab7a2f04b4aeae7bd10b..f3c6f936b67dfd1b197bee4bb71585564a5759a9 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ParticipantFilter.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ParticipantFilter.tsx
@@ -6,8 +6,8 @@
 import { Radio, RadioGroup, Typography } from "@mui/joy";
 import { useId } from "react";
 
-import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider";
-import { ParticipantFilters } from "@/lib/businessModules/dental/features/prophylaxisSessions/store/participantFilters";
+import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
+import { ParticipantFilters } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/participantFilters";
 
 export interface ParticipantFilterDef<TValue extends string> {
   label: string;
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionDetails.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionDetails.tsx
index 816a2290e4c259ed5b8ece3f1b7d75b221ae0aac..b73e79ce6ed29f375085130ac21339b82d353d0e 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionDetails.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionDetails.tsx
@@ -10,57 +10,64 @@ import { Person } from "@mui/icons-material";
 import { Stack, Typography } from "@mui/joy";
 
 import { ProphylaxisSessionParticipantsTable } from "@/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionParticipantsTable";
-import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider";
+import { useUpdateProphylaxisSessionSidebar } from "@/lib/businessModules/dental/features/prophylaxisSessions/UpdateProphylaxisSessionSidebar";
+import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
 import {
   PROPHYLAXIS_TYPES,
   fluoridationDescription,
 } from "@/lib/businessModules/dental/features/prophylaxisSessions/translations";
 import { ContentPanel } from "@/lib/shared/components/contentPanel/ContentPanel";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsColumn } from "@/lib/shared/components/detailsSection/DetailsColumn";
 import { DetailsRow } from "@/lib/shared/components/detailsSection/DetailsRow";
 import { DetailsSection } from "@/lib/shared/components/detailsSection/DetailsSection";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { displayBoolean } from "@/lib/shared/helpers/booleans";
 
 export function ProphylaxisSessionDetails() {
   const prophylaxisSession = useProphylaxisSessionStore((state) => state);
+  const updateProphylaxisSidebar = useUpdateProphylaxisSessionSidebar();
 
   return (
     <Stack gap={4}>
       <ContentPanel testId="prophylaxis-session-panel">
         <DetailsSection
           title="Allgemeine Informationen"
+          onEdit={() =>
+            updateProphylaxisSidebar.open({
+              prophylaxisSession: prophylaxisSession,
+            })
+          }
           data-testid="prophylaxis-details"
         >
           <DetailsRow>
             <DetailsColumn>
-              <DetailsCell
+              <DetailsItem
                 label="Datum"
                 value={formatDateTime(prophylaxisSession.dateAndTime)}
               />
-              <DetailsCell
+              <DetailsItem
                 label="Einrichtung"
                 value={prophylaxisSession.institution.name}
               />
-              <DetailsCell
+              <DetailsItem
                 label="Gruppe"
                 value={prophylaxisSession.groupName}
               />
             </DetailsColumn>
             <DetailsColumn>
-              <DetailsCell
+              <DetailsItem
                 label="Typ"
                 value={PROPHYLAXIS_TYPES[prophylaxisSession.type]}
               />
-              <DetailsCell
+              <DetailsItem
                 label="Reihenuntersuchung"
                 value={displayBoolean(prophylaxisSession.isScreening)}
               />
-              <DetailsCell
+              <DetailsItem
                 label="Teilnehmer"
                 value={prophylaxisSession.participants.length}
               />
-              <DetailsCell
+              <DetailsItem
                 label="Fluoridierung"
                 value={fluoridationDescription(
                   prophylaxisSession.fluoridationVarnish,
@@ -68,13 +75,13 @@ export function ProphylaxisSessionDetails() {
               />
             </DetailsColumn>
             <DetailsColumn>
-              <DetailsCell
+              <DetailsItem
                 label="Zahnarzt/-ärztin"
                 value={
                   <PerformingPersons persons={prophylaxisSession.dentists} />
                 }
               />
-              <DetailsCell
+              <DetailsItem
                 label="ZFA"
                 value={<PerformingPersons persons={prophylaxisSession.zfas} />}
               />
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionFilterSettings.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionFilterSettings.tsx
index ee43b017392f848159d544c8643eaa7c7d08bc4c..91c2981d109a319cae39c707a49326fc9ca03d50 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionFilterSettings.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionFilterSettings.tsx
@@ -71,6 +71,7 @@ export function ProphylaxisSessionFilterSettings(
             onChange={(institutionId) =>
               props.setFilterFormValue("institutionIdFilter", institutionId)
             }
+            placeholder="Schule/Kita suchen"
           />
         </FormControl>
         <FormControl>
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionForm.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..64b81425b0ff49af62e081c9bd5c0637b9e54f74
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionForm.tsx
@@ -0,0 +1,146 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiFluoridationVarnish, ApiProphylaxisType } from "@eshg/dental-api";
+import { Institution } from "@eshg/dental/api/models/Institution";
+import { Alert } from "@eshg/lib-portal/components/Alert";
+import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
+import {
+  mapOptionalValue,
+  mapRequiredValue,
+} from "@eshg/lib-portal/helpers/form";
+import { useHasChanged } from "@eshg/lib-portal/hooks/useHasChanged";
+import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+import { Stack, Typography } from "@mui/joy";
+import { useEffect } from "react";
+
+import { SCHOOL_OR_DAYCARE } from "@/lib/baseModule/api/queries/contacts";
+import { FluoridationField } from "@/lib/businessModules/dental/features/prophylaxisSessions/FluoridationField";
+import { SearchGroupField } from "@/lib/businessModules/dental/features/prophylaxisSessions/SearchGroupField";
+import { PROPHYLAXIS_TYPE_OPTIONS } from "@/lib/businessModules/dental/features/prophylaxisSessions/options";
+import {
+  AppointmentStaffField,
+  StaffUser,
+} from "@/lib/shared/components/appointmentBlocks/AppointmentStaffField";
+import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
+import { DateTimeField } from "@/lib/shared/components/formFields/DateTimeField";
+import { SelectContactField } from "@/lib/shared/components/formFields/SelectContactField";
+import { getInstitutionOptionLabel } from "@/lib/shared/helpers/selectOptionMapper";
+
+interface ProphylaxisSessionFormProps {
+  values: ProphylaxisSessionValues;
+  setFieldValue: (field: "groupName", value: "") => void;
+  dentistOptions: StaffUser[];
+  dentalAssistantOptions: StaffUser[];
+  hasExaminationResults?: boolean;
+}
+
+export interface ProphylaxisSessionValues {
+  dateAndTime: string;
+  institution: OptionalFieldValue<Institution>;
+  groupName: string;
+  type: OptionalFieldValue<ApiProphylaxisType>;
+  isScreening: boolean;
+  isFluoridation: boolean;
+  fluoridationVarnish: OptionalFieldValue<ApiFluoridationVarnish>;
+  dentistIds: string[];
+  zfaIds: string[];
+}
+
+export function ProphylaxisSessionForm(props: ProphylaxisSessionFormProps) {
+  const {
+    values,
+    setFieldValue,
+    dentistOptions,
+    dentalAssistantOptions,
+    hasExaminationResults,
+  } = props;
+
+  const shouldClearGroupName = useHasChanged(values.institution);
+  useEffect(() => {
+    if (shouldClearGroupName) {
+      void setFieldValue("groupName", "");
+    }
+  }, [shouldClearGroupName, setFieldValue, values]);
+
+  return (
+    <Stack gap={3}>
+      {hasExaminationResults && (
+        <Alert
+          color="primary"
+          message="Da es bereits Untersuchungsergebnisse zu dieser Prophylaxe gibt, können einige Daten nicht mehr geändert werden."
+        />
+      )}
+      <DateTimeField
+        name="dateAndTime"
+        label="Datum und Uhrzeit"
+        required="Bitte ein Datum mit Uhrzeit angeben."
+      />
+      <SelectContactField
+        name="institution"
+        label="Einrichtung"
+        placeholder="Schule/Kita suchen"
+        categories={SCHOOL_OR_DAYCARE}
+        required="Bitte eine Schule/Kita angeben."
+        getOptionLabel={(institution) =>
+          institution ? getInstitutionOptionLabel(institution) : ""
+        }
+        disabled={hasExaminationResults}
+      />
+      <SearchGroupField
+        name="groupName"
+        label="Gruppe"
+        institutionId={mapOptionalValue(values.institution)?.id ?? ""}
+        disabled={hasExaminationResults}
+      />
+      <SelectField
+        name="type"
+        label="Typ"
+        options={PROPHYLAXIS_TYPE_OPTIONS}
+        required="Bitte den Typ der Prophylaxe angeben."
+      />
+      <CheckboxField
+        name="isScreening"
+        label="Reihenuntersuchung"
+        disabled={hasExaminationResults}
+      />
+      <FluoridationField disabled={hasExaminationResults} />
+      <Typography component="h3" level="title-sm">
+        Durchführende Personen
+      </Typography>
+      <AppointmentStaffField
+        name="dentistIds"
+        options={dentistOptions}
+        blockedStaff={[]}
+        freeStaff={[]}
+        label="Zahnarzt/-ärztin"
+        required="Bitte mindestens eine/n Zahnarzt/-ärztin angeben."
+      />
+      <AppointmentStaffField
+        name="zfaIds"
+        options={dentalAssistantOptions}
+        blockedStaff={[]}
+        freeStaff={[]}
+        label="ZFA"
+        required="Bitte mindestens eine/n ZFA angeben."
+      />
+    </Stack>
+  );
+}
+
+export function mapValues(values: ProphylaxisSessionValues) {
+  return {
+    dateAndTime: new Date(values.dateAndTime),
+    institutionId: mapRequiredValue(values.institution)?.id,
+    groupName: mapRequiredValue(values.groupName),
+    type: mapRequiredValue(values.type),
+    isScreening: values.isScreening,
+    fluoridationVarnish: values.isFluoridation
+      ? mapRequiredValue(values.fluoridationVarnish)
+      : undefined,
+    dentistIds: values.dentistIds,
+    zfaIds: values.zfaIds,
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionParticipantsTable.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionParticipantsTable.tsx
index 0993924c0cbe032d9aff5c4c8c6d672af1631151..0f83d269f31c192d186e811bbe769332ec5d5a2f 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionParticipantsTable.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionParticipantsTable.tsx
@@ -10,14 +10,29 @@ import { GENDER_VALUES } from "@eshg/lib-portal/components/formFields/constants"
 import { InternalLinkButton } from "@eshg/lib-portal/components/navigation/InternalLinkButton";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { Add } from "@mui/icons-material";
+import CancelIcon from "@mui/icons-material/Cancel";
 import DeleteIcon from "@mui/icons-material/DeleteOutlined";
 import { Button, Divider, Stack, Typography } from "@mui/joy";
 import { createColumnHelper } from "@tanstack/react-table";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
 import { isDefined } from "remeda";
 
 import { ExaminationStatusChip } from "@/lib/businessModules/dental/features/examinations/ExaminationStatusChip";
 import { useAddChildToProphylaxisSessionSidebar } from "@/lib/businessModules/dental/features/prophylaxisSessions/AddChildToProphylaxisSessionSidebar";
+import { ChangeReasonForAbsenceModal } from "@/lib/businessModules/dental/features/prophylaxisSessions/ChangeReasonForAbsenceModal";
+import {
+  useFilteredParticipants,
+  useProphylaxisSessionStore,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
+import {
+  FluoridationConsentFilter,
+  GenderFilter,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/participantFilters";
+import {
+  ParticipantSortKey,
+  ParticipantSorting,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/participantSorting";
+import { OverlayBoundary } from "@/lib/shared/components/boundaries/OverlayBoundary";
 import { ActionsMenu } from "@/lib/shared/components/buttons/ActionsMenu";
 import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
 import { DataTable } from "@/lib/shared/components/table/DataTable";
@@ -30,18 +45,6 @@ import {
 import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
 
 import { ParticipantFilter, ParticipantFilterDef } from "./ParticipantFilter";
-import {
-  useFilteredParticipants,
-  useProphylaxisSessionStore,
-} from "./store/ProphylaxisSessionStoreProvider";
-import {
-  FluoridationConsentFilter,
-  GenderFilter,
-} from "./store/participantFilters";
-import {
-  ParticipantSortKey,
-  ParticipantSorting,
-} from "./store/participantSorting";
 
 const GENDER_FILTERS: ParticipantFilterDef<GenderFilter>[] = [
   { label: "Alle", value: "ANY" },
@@ -78,6 +81,10 @@ export function ProphylaxisSessionParticipantsTable() {
     prophylaxisSessionVersion,
     allParticipants,
   );
+  const [
+    openReasonForAbsenceModalOfParticipant,
+    setOpenReasonForAbsenceModalOfParticipant,
+  ] = useState<ChildExamination>();
 
   function handleRemoveParticipant(childExternalId: string) {
     openConfirmationDialog({
@@ -93,6 +100,14 @@ export function ProphylaxisSessionParticipantsTable() {
     });
   }
 
+  function handleAbsentParticipant(examination: ChildExamination) {
+    setOpenReasonForAbsenceModalOfParticipant(examination);
+  }
+
+  function closeAbsenceModal() {
+    setOpenReasonForAbsenceModalOfParticipant(undefined);
+  }
+
   function routeToExamination(participantIndex: number) {
     return routes.prophylaxisSessions
       .byId(prophylaxisSessionId)
@@ -153,9 +168,11 @@ export function ProphylaxisSessionParticipantsTable() {
           right={
             <>
               <AddChildButton />
-              <InternalLinkButton href={routeToExamination(0)}>
-                Reihenuntersuchung starten
-              </InternalLinkButton>
+              {filteredParticipants.length > 0 && (
+                <InternalLinkButton href={routeToExamination(0)}>
+                  Prophylaxe starten
+                </InternalLinkButton>
+              )}
             </>
           }
         />
@@ -163,10 +180,7 @@ export function ProphylaxisSessionParticipantsTable() {
     >
       <DataTable
         data={filteredParticipants}
-        columns={columnDefs(
-          filteredParticipants.length,
-          handleRemoveParticipant,
-        )}
+        columns={columnDefs(handleRemoveParticipant, handleAbsentParticipant)}
         rowNavigation={{
           focusColumnAccessorKey: "lastName",
           route: (row) => routeToExamination(row.index),
@@ -175,6 +189,14 @@ export function ProphylaxisSessionParticipantsTable() {
         enableSortingRemoval={false}
         minWidth={1200}
       />
+      {isDefined(openReasonForAbsenceModalOfParticipant) && (
+        <OverlayBoundary>
+          <ChangeReasonForAbsenceModal
+            onClose={closeAbsenceModal}
+            examination={openReasonForAbsenceModalOfParticipant}
+          />
+        </OverlayBoundary>
+      )}
     </TablePage>
   );
 }
@@ -182,10 +204,10 @@ export function ProphylaxisSessionParticipantsTable() {
 const columnHelper = createColumnHelper<ChildExamination>();
 
 function columnDefs(
-  participantsSize: number,
   onRemoveParticipant: (participantId: string) => void,
+  onAbsentParticipant: (examination: ChildExamination) => void,
 ) {
-  const columnDefs = [
+  return [
     columnHelper.accessor("firstName", {
       header: "Vorname",
       cell: (props) => props.getValue(),
@@ -252,17 +274,22 @@ function columnDefs(
         width: 110,
       },
     }),
-  ];
-
-  if (participantsSize > 1) {
-    return [
-      ...columnDefs,
-      columnHelper.display({
-        header: "Aktionen",
-        id: "actions",
-        cell: (props) => (
+    columnHelper.display({
+      header: "Aktionen",
+      id: "actions",
+      cell: (props) =>
+        childCanBeRemoved(props.row.original) ? (
           <ActionsMenu
             actionItems={[
+              ...(props.row.original.status !== "CLOSED"
+                ? [
+                    {
+                      label: "Nicht anwesend",
+                      startDecorator: <CancelIcon />,
+                      onClick: () => onAbsentParticipant(props.row.original),
+                    },
+                  ]
+                : []),
               {
                 label: "Entfernen",
                 startDecorator: <DeleteIcon />,
@@ -271,17 +298,14 @@ function columnDefs(
               },
             ]}
           />
-        ),
-        meta: {
-          width: 80,
-          cellStyle: "button",
-          textAlign: "right",
-        },
-      }),
-    ];
-  }
-
-  return columnDefs;
+        ) : undefined,
+      meta: {
+        width: 80,
+        cellStyle: "button",
+        textAlign: "right",
+      },
+    }),
+  ];
 }
 
 function resolveTableSorting(
@@ -331,3 +355,7 @@ function AddChildButton() {
     </Button>
   );
 }
+
+function childCanBeRemoved(child: ChildExamination) {
+  return child.result === undefined;
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/SearchGroupField.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/SearchGroupField.tsx
index 0b4c42496984683ff1a003f6ae962ba376bdfec9..0ac10f0392ad54b4d57d63d3b79cba3cb521afd7 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/SearchGroupField.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/SearchGroupField.tsx
@@ -5,7 +5,6 @@
 
 import { useSearchInstitutionGroups } from "@eshg/dental/api/queries/childApi";
 import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/autocomplete/SingleAutocompleteField";
-import { SearchOutlined } from "@mui/icons-material";
 
 import { mapToSelectOption } from "@/lib/shared/helpers/selectOptionMapper";
 
@@ -14,6 +13,7 @@ interface SearchGroupFieldProps {
   label: string;
   institutionId: string;
   freeSolo?: boolean;
+  disabled?: boolean;
 }
 
 export function SearchGroupField(props: SearchGroupFieldProps) {
@@ -28,9 +28,9 @@ export function SearchGroupField(props: SearchGroupFieldProps) {
       required="Bitte eine Gruppe angeben."
       options={options}
       placeholder="Gruppe suchen"
-      endDecorator={<SearchOutlined />}
       loading={searchGroups.isLoading}
       freeSolo={props.freeSolo}
+      disabled={props.disabled}
     />
   );
 }
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/UpdateProphylaxisSessionSidebar.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/UpdateProphylaxisSessionSidebar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..d0ed6cd5548ea470962208164546f5c2485c474c
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/UpdateProphylaxisSessionSidebar.tsx
@@ -0,0 +1,109 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+"use client";
+
+import { ProphylaxisSessionDetails } from "@eshg/dental/api/models/ProphylaxisSessionDetails";
+import { useUpdateProphylaxisSession } from "@eshg/dental/api/mutations/prophylaxisSessionApi";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { toDateTimeString } from "@eshg/lib-portal/helpers/dateTime";
+import { parseOptionalValue } from "@eshg/lib-portal/helpers/form";
+import { Formik } from "formik";
+
+import {
+  ProphylaxisSessionForm,
+  ProphylaxisSessionValues,
+  mapValues,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/ProphylaxisSessionForm";
+import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
+import { SidebarForm } from "@/lib/shared/components/form/SidebarForm";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+import {
+  SidebarWithFormRefProps,
+  UseSidebarWithFormRefResult,
+  useSidebarWithFormRef,
+} from "@/lib/shared/hooks/useSidebarWithFormRef";
+
+import { useGetStaff } from "./staff";
+
+export function useUpdateProphylaxisSessionSidebar(): UseSidebarWithFormRefResult<UpdateProphylaxisSessionSidebarProps> {
+  return useSidebarWithFormRef({
+    component: UpdateProphylaxisSessionSidebar,
+  });
+}
+
+interface UpdateProphylaxisSessionSidebarProps extends SidebarWithFormRefProps {
+  prophylaxisSession: ProphylaxisSessionDetails;
+}
+
+function UpdateProphylaxisSessionSidebar(
+  props: UpdateProphylaxisSessionSidebarProps,
+) {
+  const prophylaxisSession = props.prophylaxisSession;
+  const updateSession = useUpdateProphylaxisSession(prophylaxisSession.id);
+  const { allDentists, allDentalAssistants } = useGetStaff();
+  const snackbar = useSnackbar();
+
+  const hasExaminationResults = prophylaxisSession.participants.some(
+    (item) => !!item.result,
+  );
+
+  const initialValues: ProphylaxisSessionValues = {
+    dateAndTime: toDateTimeString(prophylaxisSession.dateAndTime),
+    institution: prophylaxisSession.institution,
+    groupName: prophylaxisSession.groupName,
+    type: prophylaxisSession.type,
+    isScreening: prophylaxisSession.isScreening,
+    isFluoridation: !!prophylaxisSession.fluoridationVarnish,
+    fluoridationVarnish: parseOptionalValue(
+      prophylaxisSession.fluoridationVarnish,
+    ),
+    dentistIds: prophylaxisSession.dentists.map((dentist) => dentist.id),
+    zfaIds: prophylaxisSession.zfas.map((zfa) => zfa.id),
+  };
+
+  function onSubmit(values: ProphylaxisSessionValues) {
+    updateSession
+      .mutateAsync(
+        {
+          version: prophylaxisSession.version,
+          ...mapValues(values),
+        },
+        {
+          onSuccess: () => props.onClose(true),
+        },
+      )
+      .catch(() => snackbar.error("Die Daten konnten nicht geändert werden."));
+  }
+
+  return (
+    <Formik<ProphylaxisSessionValues>
+      initialValues={initialValues}
+      onSubmit={onSubmit}
+    >
+      {({ values, handleSubmit, isSubmitting, setFieldValue }) => (
+        <SidebarForm ref={props.formRef} onSubmit={handleSubmit}>
+          <SidebarContent title="Prophylaxe ändern">
+            <ProphylaxisSessionForm
+              values={values}
+              setFieldValue={setFieldValue}
+              dentistOptions={allDentists}
+              dentalAssistantOptions={allDentalAssistants}
+              hasExaminationResults={hasExaminationResults}
+            />
+          </SidebarContent>
+          <SidebarActions>
+            <FormButtonBar
+              submitLabel="Ändern"
+              submitting={isSubmitting}
+              onCancel={() => props.onClose(false)}
+            />
+          </SidebarActions>
+        </SidebarForm>
+      )}
+    </Formik>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/AddToothButton.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/AddToothButton.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b3f5c30c3f7aa22ec4da839c92386aef629f8fc1
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/AddToothButton.tsx
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import AddCircleIcon from "@mui/icons-material/AddCircle";
+import { IconButton } from "@mui/joy";
+
+import { useDentalExaminationStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
+import { QuadrantNumber } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types";
+
+interface AddToothButtonProps {
+  index: number;
+  quadrantNumber: QuadrantNumber;
+}
+
+export function AddToothButton(props: AddToothButtonProps) {
+  const addTooth = useDentalExaminationStore((state) => state.addTooth);
+
+  return (
+    <IconButton
+      sx={{ padding: 2 }}
+      onClick={() => {
+        addTooth({
+          quadrantNumber: props.quadrantNumber,
+          toothIndex: props.index,
+        });
+      }}
+    >
+      <AddCircleIcon color="primary" />
+    </IconButton>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationFormSection.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationFormSection.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..73b753bd5fdcbbd9c082f788c3ba8110ab897722
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationFormSection.tsx
@@ -0,0 +1,24 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { DentalExaminationJawTabs } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationJawTabs";
+import { FullDentitionOverview } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/FullDentitionOverview";
+import { Legend } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Legend";
+import { LowerJawForm } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/LowerJawForm";
+import { UpperJawForm } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/UpperJawForm";
+import { InformationSheet } from "@/lib/shared/components/infoTile/InformationSheet";
+
+export function DentalExaminationFormSection() {
+  return (
+    <InformationSheet>
+      <DentalExaminationJawTabs
+        upperJaw={<UpperJawForm />}
+        lowerJaw={<LowerJawForm />}
+        fullDentition={<FullDentitionOverview />}
+      />
+      <Legend />
+    </InformationSheet>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationJawTabs.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationJawTabs.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..2de94be3720de15cd170abdf8b75b14ea73c8ada
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationJawTabs.tsx
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Box, Button, Stack, ToggleButtonGroup } from "@mui/joy";
+import { ReactNode } from "react";
+
+import { useDentalExaminationStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
+import { DentalExaminationView } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types";
+
+interface DentalExaminationJawTabsProps {
+  upperJaw: ReactNode;
+  lowerJaw: ReactNode;
+  fullDentition: ReactNode;
+}
+
+export function DentalExaminationJawTabs({
+  upperJaw,
+  lowerJaw,
+  fullDentition,
+}: DentalExaminationJawTabsProps) {
+  const currentView = useDentalExaminationStore((state) => state.currentView);
+  const setView = useDentalExaminationStore((state) => state.setView);
+
+  function getCurrentContent(view: DentalExaminationView) {
+    switch (view) {
+      case "UPPER_JAW":
+        return upperJaw;
+      case "LOWER_JAW":
+        return lowerJaw;
+      case "FULL_DENTITION":
+        return fullDentition;
+    }
+  }
+
+  return (
+    <Stack alignItems="center" spacing={2}>
+      <ToggleButtonGroup
+        variant="tabs"
+        color="primary"
+        size="md"
+        value={currentView}
+        onChange={(_, newValue) => setView(newValue ?? "UPPER_JAW")}
+        sx={{
+          width: { xxs: "100%", md: "65%" },
+          display: "flex",
+        }}
+      >
+        <Button sx={{ flex: "1 1 0%" }} value="UPPER_JAW">
+          Oberkiefer
+        </Button>
+        <Button sx={{ flex: "1 1 0%" }} value="LOWER_JAW">
+          Unterkiefer
+        </Button>
+        <Button sx={{ flex: "1 1 0%" }} value="FULL_DENTITION">
+          Gesamtgebiss
+        </Button>
+      </ToggleButtonGroup>
+      <Box
+        sx={{
+          overflow: "auto",
+          maxWidth: "100%",
+        }}
+      >
+        <Box sx={{ minWidth: "1121px" }}>{getCurrentContent(currentView)}</Box>
+      </Box>
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/FullDentitionOverview.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/FullDentitionOverview.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0ab8b95828d9c7096cf2a88e0297c936583aa6c4
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/FullDentitionOverview.tsx
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Button, Grid, Stack, Typography } from "@mui/joy";
+import { SxProps } from "@mui/joy/styles/types";
+
+import { Quadrant } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Quadrant";
+import {
+  QuadrantHeading,
+  QuadrantHeadingRow,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/QuadrantHeading";
+import { ToothIcon } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Teeth";
+import { ToothNumber } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/ToothNumber";
+import { useDentalExaminationStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
+import {
+  QuadrantNumber,
+  Tooth,
+  isToothWithDiagnosis,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types";
+
+export function FullDentitionOverview() {
+  return (
+    <Stack>
+      <QuadrantHeadingRow marginBottom="24px">
+        <QuadrantHeading name="Oberkiefer rechts" index={1} />
+        <QuadrantHeading name="Oberkiefer links" index={2} />
+      </QuadrantHeadingRow>
+      <Grid container>
+        <QuadrantSection quadrantNumber="Q1" />
+        <QuadrantSection quadrantNumber="Q2" />
+      </Grid>
+      <Grid container>
+        <QuadrantSection quadrantNumber="Q4" />
+        <QuadrantSection quadrantNumber="Q3" />
+      </Grid>
+      <QuadrantHeadingRow>
+        <QuadrantHeading name="Unterkiefer rechts" index={4} />
+        <QuadrantHeading name="Unterkiefer links" index={3} />
+      </QuadrantHeadingRow>
+    </Stack>
+  );
+}
+
+interface QuadrantSectionProps {
+  quadrantNumber: QuadrantNumber;
+}
+
+function QuadrantSection({ quadrantNumber }: QuadrantSectionProps) {
+  const styles: SxProps = {
+    padding:
+      quadrantNumber === "Q1" || quadrantNumber === "Q4"
+        ? "20px 20px 20px 0"
+        : "20px 0 20px 20px",
+    borderTop:
+      quadrantNumber === "Q3" || quadrantNumber === "Q4"
+        ? "0.5px solid black"
+        : "none",
+    borderRight:
+      quadrantNumber === "Q1" || quadrantNumber === "Q4"
+        ? "0.5px solid black"
+        : "none",
+    borderBottom:
+      quadrantNumber === "Q1" || quadrantNumber === "Q2"
+        ? "0.5px solid black"
+        : "none",
+    borderLeft:
+      quadrantNumber === "Q2" || quadrantNumber === "Q3"
+        ? "0.5px solid black"
+        : "none",
+  };
+
+  const setFocus = useDentalExaminationStore((state) => state.setFocus);
+  return (
+    <Grid xxs={6} sx={styles}>
+      <Quadrant quadrantNumber={quadrantNumber} gap={0}>
+        {(tooth, index) => (
+          <Button
+            key={tooth.toothNumber}
+            variant="plain"
+            sx={{
+              padding: "4px",
+              display: "flex",
+              flexDirection: "column",
+              alignItems: "center",
+              justifyContent: "flex-start",
+              gap: 2,
+              backgroundColor: "none",
+            }}
+            onClick={() =>
+              setFocus({
+                toothContext: {
+                  quadrantNumber,
+                  toothIndex: index,
+                },
+                field: "main",
+              })
+            }
+          >
+            <ToothNumber tooth={tooth} />
+            <ToothIcon tooth={tooth} />
+            <ExaminationResult tooth={tooth} />
+          </Button>
+        )}
+      </Quadrant>
+    </Grid>
+  );
+}
+
+function ExaminationResult({ tooth }: { tooth: Tooth }) {
+  if (!isToothWithDiagnosis(tooth)) {
+    return undefined;
+  }
+  const mainResult = tooth.mainResult;
+  const secondaryResult1 = tooth.secondaryResult1;
+  const secondaryResult2 = tooth.secondaryResult2;
+  return (
+    <Stack sx={{ alignItems: "center" }}>
+      <Typography>{mainResult?.value ? mainResult.value : "-"}</Typography>
+      <Typography>
+        {secondaryResult1?.value ? secondaryResult1.value : undefined}
+      </Typography>
+      <Typography>
+        {secondaryResult2?.value ? secondaryResult2.value : undefined}
+      </Typography>
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/GeneralJawForm.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/GeneralJawForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..62657d112890bc2c0737a893ee34610f4e748e3b
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/GeneralJawForm.tsx
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiMainResult } from "@eshg/dental-api";
+import { isEmptyString } from "@eshg/lib-portal/helpers/guards";
+import { Stack, Typography } from "@mui/joy";
+
+import { AddToothButton } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/AddToothButton";
+import { Quadrant } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Quadrant";
+import { ToothIcon } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Teeth";
+import { ToothNumber } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/ToothNumber";
+import { useDentalExaminationStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
+import {
+  QuadrantNumber,
+  ToothWithDiagnosis,
+  isAddableTooth,
+  isToothWithDiagnosis,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types";
+
+import { ResultInputField } from "./ResultInputField";
+
+export function GeneralJawForm(props: { quadrantNumber: QuadrantNumber }) {
+  const setMainResult = useDentalExaminationStore(
+    (state) => state.setMainResult,
+  );
+  const setSecondaryResult1 = useDentalExaminationStore(
+    (state) => state.setSecondaryResult1,
+  );
+  const setSecondaryResult2 = useDentalExaminationStore(
+    (state) => state.setSecondaryResult2,
+  );
+
+  return (
+    <Quadrant quadrantNumber={props.quadrantNumber}>
+      {(tooth, index) => (
+        <Stack key={tooth.toothNumber} sx={{ gap: 2, alignItems: "center" }}>
+          {isToothWithDiagnosis(tooth) && (
+            <>
+              <ToothNumber tooth={tooth} />
+              <ToothIcon tooth={tooth} />
+              <ResultInputField
+                result={tooth.mainResult}
+                index={index}
+                quadrantNumber={props.quadrantNumber}
+                setResultAction={setMainResult}
+                field="main"
+                variant={
+                  isEmptyString(tooth.mainResult.value) ? "soft" : "outlined"
+                }
+              />
+              <ResultInputField
+                result={tooth.secondaryResult1}
+                index={index}
+                quadrantNumber={props.quadrantNumber}
+                setResultAction={setSecondaryResult1}
+                field="secondary1"
+              />
+              <ResultInputField
+                result={tooth.secondaryResult2}
+                index={index}
+                quadrantNumber={props.quadrantNumber}
+                setResultAction={setSecondaryResult2}
+                field="secondary2"
+              />
+              {hasPreviousExaminationResult(tooth) && (
+                <Typography color="danger">
+                  {tooth.previousResults.join(",")}
+                </Typography>
+              )}
+            </>
+          )}
+          {isAddableTooth(tooth) && (
+            <AddToothButton
+              index={index}
+              quadrantNumber={props.quadrantNumber}
+            />
+          )}
+        </Stack>
+      )}
+    </Quadrant>
+  );
+}
+
+export function hasPreviousExaminationResult(
+  tooth: ToothWithDiagnosis,
+): boolean {
+  return (
+    tooth.previousResults.length > 0 &&
+    tooth.previousResults[0] !== ApiMainResult.S
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/JawWithHeading.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/JawWithHeading.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4991dae5e0aac867c232dedb091e0fc4001a43ba
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/JawWithHeading.tsx
@@ -0,0 +1,39 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Grid, Stack } from "@mui/joy";
+import { ReactNode } from "react";
+
+interface JawFormWithHeadingProps {
+  heading: ReactNode;
+  left: ReactNode;
+  right: ReactNode;
+}
+
+export function JawWithHeading(props: JawFormWithHeadingProps) {
+  return (
+    <Stack>
+      {props.heading}
+      <Grid container sx={{ flexWrap: "nowrap" }}>
+        <Grid
+          sx={{
+            borderRight: "0.5px solid black",
+            padding: "24px 24px 24px 4px",
+          }}
+        >
+          {props.left}
+        </Grid>
+        <Grid
+          sx={{
+            borderLeft: "0.5px solid black",
+            padding: "24px 4px 24px 24px",
+          }}
+        >
+          {props.right}
+        </Grid>
+      </Grid>
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Legend.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Legend.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..ad524cd84b5352915d2770ccbd63455163116e35
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Legend.tsx
@@ -0,0 +1,138 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import CircleIcon from "@mui/icons-material/Circle";
+import CircleOutlinedIcon from "@mui/icons-material/CircleOutlined";
+import ErrorIcon from "@mui/icons-material/Error";
+import { Button, Stack, Typography } from "@mui/joy";
+import { ReactNode } from "react";
+
+import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
+import { DrawerProps } from "@/lib/shared/components/drawer/drawerContext";
+import { useSidebar } from "@/lib/shared/components/drawer/useSidebar";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+
+export function Legend() {
+  const findingsOverviewSidebar = useSidebar({
+    component: FindingsOverviewSidebar,
+  });
+  return (
+    <Stack direction="row" sx={{ justifyContent: "space-between" }}>
+      <Stack direction="row" gap={3}>
+        <LegendItem
+          icon={<ErrorIcon color="danger" />}
+          helpText="Vorbefund vorhanden"
+        />
+        <LegendItem
+          icon={<CircleIcon color="neutral" />}
+          helpText="Bleibender Zahn"
+        />
+        <LegendItem
+          icon={<CircleOutlinedIcon color="neutral" />}
+          helpText="Milchzahn"
+        />
+      </Stack>
+      <Button variant="plain" onClick={findingsOverviewSidebar.open}>
+        <Typography component="u" color="primary">
+          Befundwerte?
+        </Typography>
+      </Button>
+    </Stack>
+  );
+}
+
+interface LegendItemProps {
+  icon: ReactNode;
+  helpText: string;
+}
+
+function LegendItem({ icon, helpText }: LegendItemProps) {
+  return (
+    <Stack direction="row" gap={0.5} alignItems="center">
+      {icon}
+      <Typography>= {helpText}</Typography>
+    </Stack>
+  );
+}
+
+function FindingsOverviewSidebar({ onClose }: DrawerProps) {
+  return (
+    <>
+      <SidebarContent title="Mögliche Befundwerte">
+        <Stack>
+          {Object.entries(POSSIBLE_DIAGNOSES).map(([abbr, expl]) => (
+            <Diagnosis
+              key={abbr}
+              abbreviation={abbr as Abbreviation}
+              explanation={expl}
+            />
+          ))}
+        </Stack>
+      </SidebarContent>
+      <SidebarActions>
+        <ButtonBar
+          right={[
+            <Button
+              color="neutral"
+              variant="soft"
+              key="close"
+              onClick={() => onClose()}
+            >
+              Schließen
+            </Button>,
+          ]}
+        />
+      </SidebarActions>
+    </>
+  );
+}
+
+type Abbreviation = keyof typeof POSSIBLE_DIAGNOSES;
+type Explanation = (typeof POSSIBLE_DIAGNOSES)[keyof typeof POSSIBLE_DIAGNOSES];
+
+const POSSIBLE_DIAGNOSES = {
+  S: "Kariesfrei",
+  I: "Initialkaries",
+  D: "Kariös",
+  F: "gefüllt",
+  E: "Extrahiert",
+  Y: "KFO-Extr.",
+  X: "Nichtanlage",
+  Z: "Zerstört",
+  T: "Trauma",
+  H: "Hypoplasie",
+  O: "Trep/Fistel",
+  V: "versiegelt",
+  N: "Nicht beurteilbar",
+  P: "Platzhalter",
+  da: "Doppelte Anlage",
+  fa: "Formanomalie",
+  fis: "Fistel",
+  id: "Im Durchbruch",
+  ins: "insuffizie",
+  K: "Krone",
+  lü: "Lückenschluss",
+  ret: "retinierter Zahn",
+  tr: "trepaniert",
+  wr: "Wurzelrest",
+  za: "Zapfenzahn",
+};
+
+interface DiagnosisProp {
+  abbreviation: Abbreviation;
+  explanation: Explanation;
+}
+
+function Diagnosis({ abbreviation, explanation }: DiagnosisProp) {
+  return (
+    <Stack direction="row" gap={2}>
+      <Typography sx={{ fontWeight: 600, width: 24 }}>
+        {abbreviation}
+      </Typography>
+      <Typography>= {explanation}</Typography>
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/LowerJawForm.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/LowerJawForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..947c229ba3617295bd80bd033f58332f6ed552bf
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/LowerJawForm.tsx
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { GeneralJawForm } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/GeneralJawForm";
+import { JawWithHeading } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/JawWithHeading";
+import {
+  QuadrantHeading,
+  QuadrantHeadingRow,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/QuadrantHeading";
+
+export function LowerJawForm() {
+  return (
+    <JawWithHeading
+      heading={
+        <QuadrantHeadingRow marginBottom="24px">
+          <QuadrantHeading name="Unterkiefer rechts" index={4} />
+          <QuadrantHeading name="Unterkiefer links" index={3} />
+        </QuadrantHeadingRow>
+      }
+      left={<GeneralJawForm quadrantNumber="Q4" />}
+      right={<GeneralJawForm quadrantNumber="Q3" />}
+    />
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Quadrant.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Quadrant.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..d8510a2a3a83c3b4ca51f329e8946c239dd23444
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Quadrant.tsx
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Stack } from "@mui/joy";
+import { Property } from "csstype";
+import { ReactNode } from "react";
+
+import { useDentalExaminationStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
+import {
+  QuadrantNumber,
+  Tooth,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types";
+
+interface QuadrantProps {
+  quadrantNumber: QuadrantNumber;
+  children: (tooth: Tooth, index: number) => ReactNode;
+  gap?: Property.Gap;
+}
+
+export function Quadrant(props: QuadrantProps) {
+  const dentition = useDentalExaminationStore((state) => state.dentition);
+  return (
+    <Stack gap={props.gap ?? 1} direction="row">
+      {dentition[props.quadrantNumber].teeth.map((tooth, index) =>
+        props.children(tooth, index),
+      )}
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/QuadrantHeading.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/QuadrantHeading.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..73f26ea9e6920a391c795b3ba134759e60a9c035
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/QuadrantHeading.tsx
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { RequiresChildren } from "@eshg/lib-portal/types/react";
+import { Stack, Typography } from "@mui/joy";
+import { Property } from "csstype";
+
+import { theme } from "@/lib/baseModule/theme/theme";
+
+interface QuadrantHeadingRowProps extends RequiresChildren {
+  marginTop?: Property.MarginTop;
+  marginBottom?: Property.MarginBottom;
+}
+
+export function QuadrantHeadingRow(props: QuadrantHeadingRowProps) {
+  return (
+    <Stack
+      direction="row"
+      sx={{
+        justifyContent: "space-between",
+        marginTop: props.marginTop,
+        marginBottom: props.marginBottom,
+      }}
+    >
+      {props.children}
+    </Stack>
+  );
+}
+
+export function QuadrantHeading(props: { name: string; index: number }) {
+  return (
+    <Typography component="h3">
+      <Typography
+        component="span"
+        sx={{
+          fontSize: theme.fontSize.md,
+          fontWeight: theme.fontWeight.lg,
+        }}
+      >
+        {props.name}
+      </Typography>{" "}
+      - Quadrant {props.index}
+    </Typography>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/ResultInputField.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/ResultInputField.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..aff3bf8b7b3c44f4ee870b9fd2d9511f32739288
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/ResultInputField.tsx
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Input, VariantProp } from "@mui/joy";
+import { useEffect, useRef } from "react";
+
+import { useDentalExaminationStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
+import { SetToothResultAction } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/dentalExaminationStore";
+import {
+  FieldVariant,
+  QuadrantNumber,
+  ToothResult,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types";
+
+interface ResultInputFieldProps {
+  quadrantNumber: QuadrantNumber;
+  index: number;
+  setResultAction: SetToothResultAction;
+  field: FieldVariant;
+  result: ToothResult;
+  variant?: VariantProp;
+}
+
+export function ResultInputField(props: ResultInputFieldProps) {
+  const focus = useDentalExaminationStore((state) => state.focus);
+  const setFocus = useDentalExaminationStore((state) => state.setFocus);
+  const input = useRef<HTMLInputElement>(null);
+
+  const { quadrantNumber, toothIndex } = focus.toothContext;
+  const focusReferencesThisInput =
+    quadrantNumber === props.quadrantNumber &&
+    toothIndex === props.index &&
+    focus.field === props.field;
+
+  useEffect(() => {
+    if (focusReferencesThisInput) {
+      input?.current?.focus();
+    }
+  }, [input, focusReferencesThisInput]);
+
+  function handleOnFocus() {
+    if (!focusReferencesThisInput) {
+      setFocus({
+        toothContext: {
+          quadrantNumber: props.quadrantNumber,
+          toothIndex: props.index,
+        },
+        field: props.field,
+      });
+    }
+  }
+
+  return (
+    <Input
+      slotProps={{ input: { ref: input } }}
+      value={props.result.value}
+      sx={{ width: 60 }}
+      color={props.result.isInvalid ? "danger" : "primary"}
+      type="text"
+      variant={props.variant}
+      onFocus={handleOnFocus}
+      onChange={(event) => {
+        props.setResultAction(
+          {
+            quadrantNumber: props.quadrantNumber,
+            toothIndex: props.index,
+          },
+          event.target.value.toUpperCase(),
+        );
+      }}
+    />
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Teeth.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Teeth.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0000aaf6e33aed8ac5fe320744f7b5864e8a1ff8
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/Teeth.tsx
@@ -0,0 +1,262 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+"use client";
+
+import ClearIcon from "@mui/icons-material/Clear";
+import { Box } from "@mui/joy";
+import SvgIcon from "@mui/joy/SvgIcon";
+import { SxProps } from "@mui/joy/styles/types";
+
+import { theme } from "@/lib/baseModule/theme/theme";
+import {
+  Tooth,
+  isInUpperJaw,
+  isToothWithDiagnosis,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types";
+
+import { hasPreviousExaminationResult } from "./GeneralJawForm";
+
+const FILL_COLOR = "#555E68";
+const ICON_SIZE: SxProps = {
+  width: 60,
+  height: 66,
+};
+
+type ToothKey = keyof typeof TOOTH_COMPONENTS;
+
+const TOOTH_COMPONENTS = {
+  1: Incisor,
+  2: Cuspid,
+  3: Cuspid,
+  4: Premolar,
+  5: Premolar,
+  6: Molar,
+  7: Molar,
+  8: Molar,
+} as const;
+
+interface ToothProps {
+  tooth: Tooth;
+}
+
+export function ToothIcon({ tooth }: ToothProps) {
+  const inUpperJaw = isInUpperJaw(tooth);
+
+  if (!isToothWithDiagnosis(tooth)) {
+    return <NoToothIcon isInUpperJaw={inUpperJaw} />;
+  }
+
+  const toothKey = getToothKey(tooth);
+  const variant = inUpperJaw ? "upperJaw" : "lowerJaw";
+  const ToothIcon = TOOTH_COMPONENTS[toothKey];
+
+  return (
+    <ToothIcon
+      variant={variant}
+      isPrimaryTooth={tooth.toothType === "PRIMARY_TOOTH"}
+      hasPreviousExaminationResult={hasPreviousExaminationResult(tooth)}
+    />
+  );
+}
+
+interface ToothIconProps {
+  hasPreviousExaminationResult?: boolean;
+  isPrimaryTooth?: boolean;
+  variant: "upperJaw" | "lowerJaw";
+}
+
+export function Incisor(props: ToothIconProps) {
+  return (
+    <SvgIcon sx={ICON_SIZE} viewBox="0 0 60 66" fill="none">
+      <g transform={props.variant === "upperJaw" ? "" : "rotate(180, 30, 33)"}>
+        <path
+          d="M30.8944 12.0249L34.6584 19.5528C34.9908 20.2177 34.5073 21 33.7639 21H26.2361C25.4927 21 25.0092 20.2177 25.3416 19.5528L29.1056 12.0249C29.4741 11.2879 30.5259 11.2879 30.8944 12.0249Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        <path
+          d="M11 34C11 30.134 14.134 27 18 27H42C45.866 27 49 30.134 49 34V58C49 61.866 45.866 65 42 65H18C14.134 65 11 61.866 11 58V34Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        {props.hasPreviousExaminationResult && (
+          <g
+            transform={
+              props.variant === "upperJaw" ? "" : "rotate(180, 30, 46)"
+            }
+          >
+            <path
+              d="M21 46C21 41.0294 25.0294 37 30 37C34.9706 37 39 41.0294 39 46C39 50.9706 34.9706 55 30 55C25.0294 55 21 50.9706 21 46Z"
+              fill={theme.palette.danger.solidBg}
+            />
+            <path
+              d="M30.616 41.66L30.46 47.48H29.32L29.164 41.66H30.616ZM29.932 50.084C29.684 50.084 29.476 50 29.308 49.832C29.14 49.664 29.056 49.456 29.056 49.208C29.056 48.96 29.14 48.752 29.308 48.584C29.476 48.416 29.684 48.332 29.932 48.332C30.172 48.332 30.376 48.416 30.544 48.584C30.712 48.752 30.796 48.96 30.796 49.208C30.796 49.456 30.712 49.664 30.544 49.832C30.376 50 30.172 50.084 29.932 50.084Z"
+              fill="white"
+            />
+          </g>
+        )}
+      </g>
+    </SvgIcon>
+  );
+}
+
+export function Premolar(props: ToothIconProps) {
+  return (
+    <SvgIcon sx={ICON_SIZE} viewBox="0 0 60 66" fill="none">
+      <g transform={props.variant === "upperJaw" ? "" : "rotate(180, 30, 33)"}>
+        <path
+          d="M22.8944 4.02492L26.6584 11.5528C26.9908 12.2177 26.5073 13 25.7639 13H18.2361C17.4927 13 17.0092 12.2177 17.3416 11.5528L21.1056 4.02492C21.4741 3.28787 22.5259 3.28787 22.8944 4.02492Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        <path
+          d="M38.8944 4.02492L42.6584 11.5528C42.9908 12.2177 42.5073 13 41.7639 13H34.2361C33.4927 13 33.0092 12.2177 33.3416 11.5528L37.1056 4.02492C37.4741 3.28787 38.5259 3.28787 38.8944 4.02492Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        <path
+          d="M7 26C7 22.134 10.134 19 14 19H46C49.866 19 53 22.134 53 26V58C53 61.866 49.866 65 46 65H14C10.134 65 7 61.866 7 58V26Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        {props.hasPreviousExaminationResult && (
+          <g
+            transform={
+              props.variant === "upperJaw" ? "" : "rotate(180, 30, 42)"
+            }
+          >
+            <path
+              d="M21 42C21 37.0294 25.0294 33 30 33C34.9706 33 39 37.0294 39 42C39 46.9706 34.9706 51 30 51C25.0294 51 21 46.9706 21 42Z"
+              fill={theme.palette.danger.solidBg}
+            />
+            <path
+              d="M30.616 37.66L30.46 43.48H29.32L29.164 37.66H30.616ZM29.932 46.084C29.684 46.084 29.476 46 29.308 45.832C29.14 45.664 29.056 45.456 29.056 45.208C29.056 44.96 29.14 44.752 29.308 44.584C29.476 44.416 29.684 44.332 29.932 44.332C30.172 44.332 30.376 44.416 30.544 44.584C30.712 44.752 30.796 44.96 30.796 45.208C30.796 45.456 30.712 45.664 30.544 45.832C30.376 46 30.172 46.084 29.932 46.084Z"
+              fill="white"
+            />
+          </g>
+        )}
+      </g>
+    </SvgIcon>
+  );
+}
+
+export function Cuspid(props: ToothIconProps) {
+  return (
+    <SvgIcon sx={ICON_SIZE} viewBox="0 0 60 66" fill="none">
+      <g transform={props.variant === "upperJaw" ? "" : "rotate(180, 30, 33)"}>
+        <path
+          d="M30.8944 4.02492L34.6584 11.5528C34.9908 12.2177 34.5073 13 33.7639 13H26.2361C25.4927 13 25.0092 12.2177 25.3416 11.5528L29.1056 4.02492C29.4741 3.28787 30.5259 3.28787 30.8944 4.02492Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        <path
+          d="M11 26C11 22.134 14.134 19 18 19H42C45.866 19 49 22.134 49 26V58C49 61.866 45.866 65 42 65H18C14.134 65 11 61.866 11 58V26Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        {props.hasPreviousExaminationResult && (
+          <g
+            transform={
+              props.variant === "upperJaw" ? "" : "rotate(180, 30, 42)"
+            }
+          >
+            <path
+              d="M21 42C21 37.0294 25.0294 33 30 33C34.9706 33 39 37.0294 39 42C39 46.9706 34.9706 51 30 51C25.0294 51 21 46.9706 21 42Z"
+              fill={theme.palette.danger.solidBg}
+            />
+            <path
+              d="M30.616 37.66L30.46 43.48H29.32L29.164 37.66H30.616ZM29.932 46.084C29.684 46.084 29.476 46 29.308 45.832C29.14 45.664 29.056 45.456 29.056 45.208C29.056 44.96 29.14 44.752 29.308 44.584C29.476 44.416 29.684 44.332 29.932 44.332C30.172 44.332 30.376 44.416 30.544 44.584C30.712 44.752 30.796 44.96 30.796 45.208C30.796 45.456 30.712 45.664 30.544 45.832C30.376 46 30.172 46.084 29.932 46.084Z"
+              fill="white"
+            />
+          </g>
+        )}
+      </g>
+    </SvgIcon>
+  );
+}
+
+export function Molar(props: ToothIconProps) {
+  return (
+    <SvgIcon sx={ICON_SIZE} viewBox="0 0 60 66" fill="none">
+      <g transform={props.variant === "upperJaw" ? "" : "rotate(180, 30, 33)"}>
+        <path
+          d="M14.8944 4.02492L18.6584 11.5528C18.9908 12.2177 18.5073 13 17.7639 13H10.2361C9.49269 13 9.00919 12.2177 9.34164 11.5528L13.1056 4.02492C13.4741 3.28787 14.5259 3.28787 14.8944 4.02492Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        <path
+          d="M30.8944 4.02492L34.6584 11.5528C34.9908 12.2177 34.5073 13 33.7639 13H26.2361C25.4927 13 25.0092 12.2177 25.3416 11.5528L29.1056 4.02492C29.4741 3.28787 30.5259 3.28787 30.8944 4.02492Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        <path
+          d="M46.8944 4.02492L50.6584 11.5528C50.9908 12.2177 50.5073 13 49.7639 13H42.2361C41.4927 13 41.0092 12.2177 41.3416 11.5528L45.1056 4.02492C45.4741 3.28787 46.5259 3.28787 46.8944 4.02492Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        <path
+          d="M1 26C1 22.134 4.13401 19 8 19H52C55.866 19 59 22.134 59 26V58C59 61.866 55.866 65 52 65H8C4.13401 65 1 61.866 1 58V26Z"
+          fill={props.isPrimaryTooth ? "white" : FILL_COLOR}
+          stroke={FILL_COLOR}
+          stroke-width="2"
+        />
+        {props.hasPreviousExaminationResult && (
+          <g
+            transform={
+              props.variant === "upperJaw" ? "" : "rotate(180, 30, 42)"
+            }
+          >
+            <path
+              d="M21 42C21 37.0294 25.0294 33 30 33C34.9706 33 39 37.0294 39 42C39 46.9706 34.9706 51 30 51C25.0294 51 21 46.9706 21 42Z"
+              fill={theme.palette.danger.solidBg}
+            />
+            <path
+              d="M30.616 37.66L30.46 43.48H29.32L29.164 37.66H30.616ZM29.932 46.084C29.684 46.084 29.476 46 29.308 45.832C29.14 45.664 29.056 45.456 29.056 45.208C29.056 44.96 29.14 44.752 29.308 44.584C29.476 44.416 29.684 44.332 29.932 44.332C30.172 44.332 30.376 44.416 30.544 44.584C30.712 44.752 30.796 44.96 30.796 45.208C30.796 45.456 30.712 45.664 30.544 45.832C30.376 46 30.172 46.084 29.932 46.084Z"
+              fill="white"
+            />
+          </g>
+        )}
+      </g>
+    </SvgIcon>
+  );
+}
+
+interface NoToothIconProps {
+  isInUpperJaw: boolean;
+}
+
+function NoToothIcon(props: NoToothIconProps) {
+  return (
+    <Box
+      sx={{
+        ...ICON_SIZE,
+        padding: props.isInUpperJaw
+          ? "32px 18px 10px 18px"
+          : "10px 18px 32px 18px",
+      }}
+    >
+      <ClearIcon color="neutral" />
+    </Box>
+  );
+}
+
+function getToothKey(tooth: Tooth): ToothKey {
+  const toothKey = parseInt(tooth.toothNumber.substring(2, 3));
+  if (toothKey < 1 || toothKey > 8) {
+    throw new Error("Invalid tooth key");
+  }
+  return toothKey as ToothKey;
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/ToothNumber.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/ToothNumber.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..16a5fa0ad68822c6a0444053d37e20dcfc961299
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/ToothNumber.tsx
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Typography } from "@mui/joy";
+
+import { theme } from "@/lib/baseModule/theme/theme";
+import { Tooth } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types";
+
+export function ToothNumber(props: { tooth: Tooth }) {
+  return (
+    <Typography
+      sx={{
+        fontSize: theme.fontSize.md,
+        borderRadius: theme.radius.sm,
+        backgroundColor: theme.palette.background.level3,
+        fontWeight: theme.fontWeight.lg,
+        width: 36,
+        height: 24,
+        textAlign: "center",
+      }}
+    >
+      {getToothNumber(props.tooth)}
+    </Typography>
+  );
+}
+
+export function getToothNumber(tooth: Tooth): number {
+  return Number.parseInt(tooth.toothNumber.substring(1));
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/UpperJawForm.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/UpperJawForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..32238f88c674dfff23b3f02dda76f5b9d100bd60
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/UpperJawForm.tsx
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { GeneralJawForm } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/GeneralJawForm";
+import { JawWithHeading } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/JawWithHeading";
+import {
+  QuadrantHeading,
+  QuadrantHeadingRow,
+} from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/QuadrantHeading";
+
+export function UpperJawForm() {
+  return (
+    <JawWithHeading
+      heading={
+        <QuadrantHeadingRow marginBottom="24px">
+          <QuadrantHeading name="Oberkiefer rechts" index={1} />
+          <QuadrantHeading name="Oberkiefer links" index={2} />
+        </QuadrantHeadingRow>
+      }
+      left={<GeneralJawForm quadrantNumber="Q1" />}
+      right={<GeneralJawForm quadrantNumber="Q2" />}
+    />
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c837c33cf5c3a1a761d4c14ab280bb064eeaca40
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider.tsx
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+"use client";
+
+import { ExaminationResult } from "@eshg/dental/api/models/ExaminationResult";
+import { RequiresChildren } from "@eshg/lib-portal/types/react";
+import { createContext, useContext, useState } from "react";
+import { useStore } from "zustand";
+
+import {
+  DentalExaminationStore,
+  createDentalExaminationStore,
+  initDentalExaminationStore,
+} from "./dentalExaminationStore";
+
+type DentalExaminationStoreApi = ReturnType<
+  typeof createDentalExaminationStore
+>;
+
+const DentalExaminationStoreContext =
+  createContext<DentalExaminationStoreApi | null>(null);
+
+interface DentalExaminationStoreProviderProps extends RequiresChildren {
+  examinationResult?: ExaminationResult;
+}
+
+export function DentalExaminationStoreProvider({
+  examinationResult,
+  children,
+}: DentalExaminationStoreProviderProps) {
+  const [store] = useState(() =>
+    createDentalExaminationStore(initDentalExaminationStore(examinationResult)),
+  );
+
+  // TODO: handle updated examinationResult
+
+  return (
+    <DentalExaminationStoreContext.Provider value={store}>
+      {children}
+    </DentalExaminationStoreContext.Provider>
+  );
+}
+
+export function useDentalExaminationStore<T>(
+  selector: (store: DentalExaminationStore) => T,
+): T {
+  const dentalExaminationStoreContext = useContext(
+    DentalExaminationStoreContext,
+  );
+
+  if (dentalExaminationStoreContext === null) {
+    throw new Error("Missing DentalExaminationStoreProvider");
+  }
+
+  return useStore(dentalExaminationStoreContext, selector);
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/actions.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/actions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..574503a4a92dd282a66baa0e83711a6effc87eed
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/actions.ts
@@ -0,0 +1,243 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiMainResult, ApiSecondaryResult } from "@eshg/dental-api";
+import { ToothDiagnoses } from "@eshg/dental/api/models/ExaminationResult";
+import { isEmptyString } from "@eshg/lib-portal/helpers/guards";
+
+import { createToothResult, createToothWithDiagnosis } from "./factories";
+import {
+  DentalExaminationView,
+  Dentition,
+  Focus,
+  ToothContext,
+  ToothResult,
+  ToothWithDiagnosis,
+  isAddableTooth,
+} from "./types";
+
+export function setMainResult(
+  toothContext: ToothContext,
+  newValue: string,
+  dentition: Dentition,
+) {
+  const tooth = getToothFromToothContext(dentition, toothContext);
+
+  const isInvalid = isEmptyString(newValue)
+    ? !isEmptyString(tooth.secondaryResult1.value) ||
+      !isEmptyString(tooth.secondaryResult2.value)
+    : !isValidMainResult(newValue);
+
+  return updateToothWithDiagnosis(toothContext, dentition, {
+    mainResult: createToothResult(newValue, isInvalid),
+  });
+}
+
+export function setSecondaryResult1(
+  toothContext: ToothContext,
+  newValue: string,
+  dentition: Dentition,
+) {
+  const tooth = getToothFromToothContext(dentition, toothContext);
+
+  const isInvalid =
+    !isEmptyString(newValue) && !isValidSecondaryResult(newValue);
+
+  const mainResult = setMainResultInvalidIfEmpty(
+    tooth.mainResult,
+    tooth.secondaryResult2,
+    newValue,
+  );
+
+  return updateToothWithDiagnosis(toothContext, dentition, {
+    mainResult,
+    secondaryResult1: createToothResult(newValue, isInvalid),
+  });
+}
+
+export function setSecondaryResult2(
+  toothContext: ToothContext,
+  newValue: string,
+  dentition: Dentition,
+) {
+  const tooth = getToothFromToothContext(dentition, toothContext);
+
+  const isInvalid =
+    !isEmptyString(newValue) && !isValidSecondaryResult(newValue);
+
+  const mainResult = setMainResultInvalidIfEmpty(
+    tooth.mainResult,
+    tooth.secondaryResult1,
+    newValue,
+  );
+
+  return updateToothWithDiagnosis(toothContext, dentition, {
+    mainResult,
+    secondaryResult2: createToothResult(newValue, isInvalid),
+  });
+}
+
+function setMainResultInvalidIfEmpty(
+  mainResult: ToothResult,
+  secondaryResult: ToothResult,
+  newValue: string,
+) {
+  if (isEmptyToothResult(mainResult)) {
+    if (isEmptyString(newValue) && isEmptyToothResult(secondaryResult)) {
+      return createToothResult(mainResult.value, false);
+    } else {
+      return createToothResult("", true);
+    }
+  }
+  return mainResult;
+}
+
+function getToothFromToothContext(
+  dentition: Dentition,
+  toothContext: ToothContext,
+) {
+  return dentition[toothContext.quadrantNumber].teeth[
+    toothContext.toothIndex
+  ] as ToothWithDiagnosis;
+}
+
+function isValidSecondaryResult(
+  newValue: string,
+): newValue is ApiSecondaryResult {
+  return Object.values(ApiSecondaryResult).includes(
+    newValue as ApiSecondaryResult,
+  );
+}
+
+function isValidMainResult(newValue: string): newValue is ApiMainResult {
+  return Object.values(ApiMainResult).includes(newValue as ApiMainResult);
+}
+
+export function addTooth(
+  toothContext: ToothContext,
+  dentition: Dentition,
+): Dentition {
+  const { quadrantNumber, toothIndex } = toothContext;
+  const targetQuadrant = dentition[quadrantNumber];
+  const tooth = targetQuadrant.teeth[toothIndex];
+
+  if (tooth === undefined) {
+    throw new Error(
+      `Tooth with index ${toothIndex} does not exist in quadrant ${quadrantNumber}`,
+    );
+  }
+
+  if (!isAddableTooth(tooth)) {
+    throw new Error("Tooth must be of type AddableTooth");
+  }
+
+  const newTooth = createToothWithDiagnosis(tooth.toothNumber);
+
+  return {
+    ...dentition,
+    [quadrantNumber]: {
+      ...targetQuadrant,
+      teeth: targetQuadrant.teeth.with(toothContext.toothIndex, newTooth),
+    },
+  };
+}
+
+function updateToothWithDiagnosis(
+  toothContext: ToothContext,
+  dentition: Dentition,
+  newTooth: Partial<ToothWithDiagnosis>,
+): Dentition {
+  const { quadrantNumber, toothIndex } = toothContext;
+  const targetQuadrant = dentition[quadrantNumber];
+  const tooth = targetQuadrant.teeth[toothIndex];
+
+  if (tooth === undefined) {
+    throw new Error(
+      `Tooth with index ${toothIndex} does not exist in quadrant ${quadrantNumber}`,
+    );
+  }
+
+  if (tooth.type !== "ToothWithDiagnosis") {
+    throw new Error("Tooth must be of type ToothWithDiagnosis");
+  }
+
+  return {
+    ...dentition,
+    [quadrantNumber]: {
+      ...targetQuadrant,
+      teeth: targetQuadrant.teeth.with(toothIndex, { ...tooth, ...newTooth }),
+    },
+  };
+}
+
+export function getToothDiagnoses(dentition: Dentition): ToothDiagnoses {
+  const toothDiagnoses: ToothDiagnoses = {};
+
+  Object.values(dentition)
+    .flatMap((quadrant) => quadrant.teeth)
+    .forEach((tooth) => {
+      if (tooth.type !== "ToothWithDiagnosis") {
+        return;
+      }
+
+      const { toothNumber, mainResult, secondaryResult1, secondaryResult2 } =
+        tooth;
+
+      assertIsValid(mainResult);
+
+      if (
+        isEmptyToothResult(mainResult) ||
+        !isValidMainResult(mainResult.value)
+      ) {
+        return;
+      }
+
+      toothDiagnoses[toothNumber] = {
+        tooth: toothNumber,
+        mainResult: mainResult.value,
+        secondaryResult1: resolveSecondaryResult(secondaryResult1),
+        secondaryResult2: resolveSecondaryResult(secondaryResult2),
+      };
+    });
+
+  return toothDiagnoses;
+}
+
+function resolveSecondaryResult(
+  toothResult: ToothResult,
+): ApiSecondaryResult | undefined {
+  assertIsValid(toothResult);
+
+  if (!isValidSecondaryResult(toothResult.value)) {
+    return undefined;
+  }
+
+  return toothResult.value;
+}
+
+function assertIsValid(toothResult: ToothResult): void {
+  if (toothResult.isInvalid) {
+    throw new Error("Invalid tooth result");
+  }
+}
+
+function isEmptyToothResult(toothResult: ToothResult): boolean {
+  return toothResult.value === "";
+}
+
+export function setFocus(focus: Focus): {
+  focus: Focus;
+  currentView: DentalExaminationView;
+} {
+  const quadrantNumber = focus.toothContext.quadrantNumber;
+  const nextView =
+    quadrantNumber === "Q1" || quadrantNumber === "Q2"
+      ? "UPPER_JAW"
+      : "LOWER_JAW";
+  return {
+    focus,
+    currentView: nextView,
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/constants.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a4f548ed9705ed762c6c0ab4a6c3651c2c399007
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/constants.ts
@@ -0,0 +1,141 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiTooth } from "@eshg/dental-api";
+
+import { ToothType } from "./types";
+
+/**
+ * Defines a mapping from milk teeth to permanent teeth and vice versa
+ */
+export const RELATED_TEETH: Partial<Record<ApiTooth, ApiTooth>> = {
+  T11: "T51",
+  T12: "T52",
+  T13: "T53",
+  T14: "T54",
+  T15: "T55",
+
+  T21: "T61",
+  T22: "T62",
+  T23: "T63",
+  T24: "T64",
+  T25: "T65",
+
+  T31: "T71",
+  T32: "T72",
+  T33: "T73",
+  T34: "T74",
+  T35: "T75",
+
+  T41: "T81",
+  T42: "T82",
+  T43: "T83",
+  T44: "T84",
+  T45: "T85",
+
+  T51: "T11",
+  T52: "T12",
+  T53: "T13",
+  T54: "T14",
+  T55: "T15",
+
+  T61: "T21",
+  T62: "T22",
+  T63: "T23",
+  T64: "T24",
+  T65: "T25",
+
+  T71: "T31",
+  T72: "T32",
+  T73: "T33",
+  T74: "T34",
+  T75: "T35",
+
+  T81: "T41",
+  T82: "T42",
+  T83: "T43",
+  T84: "T44",
+  T85: "T45",
+};
+
+export const TOOTH_TYPES: Record<ApiTooth, ToothType> = {
+  T11: "SECONDARY_TOOTH",
+  T12: "SECONDARY_TOOTH",
+  T13: "SECONDARY_TOOTH",
+  T14: "SECONDARY_TOOTH",
+  T15: "SECONDARY_TOOTH",
+  T16: "SECONDARY_TOOTH",
+  T17: "SECONDARY_TOOTH",
+  T18: "SECONDARY_TOOTH",
+
+  T21: "SECONDARY_TOOTH",
+  T22: "SECONDARY_TOOTH",
+  T23: "SECONDARY_TOOTH",
+  T24: "SECONDARY_TOOTH",
+  T25: "SECONDARY_TOOTH",
+  T26: "SECONDARY_TOOTH",
+  T27: "SECONDARY_TOOTH",
+  T28: "SECONDARY_TOOTH",
+
+  T31: "SECONDARY_TOOTH",
+  T32: "SECONDARY_TOOTH",
+  T33: "SECONDARY_TOOTH",
+  T34: "SECONDARY_TOOTH",
+  T35: "SECONDARY_TOOTH",
+  T36: "SECONDARY_TOOTH",
+  T37: "SECONDARY_TOOTH",
+
+  T38: "SECONDARY_TOOTH",
+  T41: "SECONDARY_TOOTH",
+  T42: "SECONDARY_TOOTH",
+  T43: "SECONDARY_TOOTH",
+  T44: "SECONDARY_TOOTH",
+  T45: "SECONDARY_TOOTH",
+  T46: "SECONDARY_TOOTH",
+  T47: "SECONDARY_TOOTH",
+  T48: "SECONDARY_TOOTH",
+
+  T51: "PRIMARY_TOOTH",
+  T52: "PRIMARY_TOOTH",
+  T53: "PRIMARY_TOOTH",
+  T54: "PRIMARY_TOOTH",
+  T55: "PRIMARY_TOOTH",
+
+  T61: "PRIMARY_TOOTH",
+  T62: "PRIMARY_TOOTH",
+  T63: "PRIMARY_TOOTH",
+  T64: "PRIMARY_TOOTH",
+  T65: "PRIMARY_TOOTH",
+
+  T71: "PRIMARY_TOOTH",
+  T72: "PRIMARY_TOOTH",
+  T73: "PRIMARY_TOOTH",
+  T74: "PRIMARY_TOOTH",
+  T75: "PRIMARY_TOOTH",
+
+  T81: "PRIMARY_TOOTH",
+  T82: "PRIMARY_TOOTH",
+  T83: "PRIMARY_TOOTH",
+  T84: "PRIMARY_TOOTH",
+  T85: "PRIMARY_TOOTH",
+};
+
+/**
+ * Defines teeth which can be added and removed
+ */
+export const OPTIONAL_TEETH = new Set<ApiTooth>([
+  "T16",
+  "T17",
+  "T18",
+  "T26",
+  "T27",
+  "T28",
+  "T36",
+  "T37",
+  "T38",
+  "T46",
+  "T47",
+  "T48",
+]);
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/dentalExaminationStore.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/dentalExaminationStore.ts
new file mode 100644
index 0000000000000000000000000000000000000000..08cd0e677b6225507e3a5be36d2e9898a65c8477
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/dentalExaminationStore.ts
@@ -0,0 +1,106 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+/* eslint-disable unused-imports/no-unused-vars */
+import {
+  ExaminationResult,
+  ToothDiagnoses,
+} from "@eshg/dental/api/models/ExaminationResult";
+import { createStore } from "zustand";
+
+import {
+  addTooth,
+  getToothDiagnoses,
+  setFocus,
+  setMainResult,
+  setSecondaryResult1,
+  setSecondaryResult2,
+} from "./actions";
+import { createSecondaryDentition } from "./factories";
+import { DentalExaminationView, Dentition, Focus, ToothContext } from "./types";
+
+export interface DentalExaminationState {
+  currentView: DentalExaminationView;
+  dentition: Dentition;
+  focus: Focus;
+}
+
+export interface DentalExaminationActions {
+  setView: (newView: DentalExaminationView) => void;
+
+  addTooth: ToothAction;
+  removeTooth: ToothAction;
+  toggleToothType: ToothAction;
+  setFocus: (focus: Focus) => void;
+
+  setMainResult: SetToothResultAction;
+  setSecondaryResult1: SetToothResultAction;
+  setSecondaryResult2: SetToothResultAction;
+  getToothDiagnoses: () => ToothDiagnoses;
+}
+
+export type ToothAction = (toothContext: ToothContext) => void;
+export type SetToothResultAction = (
+  toothContext: ToothContext,
+  newValue: string,
+) => void;
+
+export type DentalExaminationStore = DentalExaminationState &
+  DentalExaminationActions;
+
+export function initDentalExaminationStore(
+  examinationResult: ExaminationResult | undefined,
+): DentalExaminationState {
+  const toothDiagnoses =
+    examinationResult?.type === "screening"
+      ? examinationResult.toothDiagnoses
+      : {};
+
+  return {
+    currentView: "UPPER_JAW",
+    // TODO ISSUE-6584: distinguish between type of dentition
+    dentition: createSecondaryDentition(toothDiagnoses),
+    focus: {
+      toothContext: { quadrantNumber: "Q1", toothIndex: 0 },
+      field: "main",
+    },
+  };
+}
+
+export function createDentalExaminationStore(
+  initialState: DentalExaminationState,
+) {
+  return createStore<DentalExaminationStore>()((set, get) => ({
+    ...initialState,
+    setView: (newView: DentalExaminationView) => set({ currentView: newView }),
+    addTooth: (toothContext: ToothContext) => {
+      set((state) => ({
+        dentition: addTooth(toothContext, state.dentition),
+      }));
+    },
+    removeTooth: (toothContext: ToothContext) => {
+      throw new Error("Not yet implemented");
+    },
+    toggleToothType: (toothContext: ToothContext) => {
+      throw new Error("Not yet implemented");
+    },
+    setFocus: (focus: Focus) => {
+      set(setFocus(focus));
+    },
+    setMainResult: (toothContext: ToothContext, newValue: string) =>
+      set((state) => ({
+        dentition: setMainResult(toothContext, newValue, state.dentition),
+      })),
+    setSecondaryResult1: (toothContext: ToothContext, newValue: string) =>
+      set((state) => ({
+        dentition: setSecondaryResult1(toothContext, newValue, state.dentition),
+      })),
+    setSecondaryResult2: (toothContext: ToothContext, newValue: string) =>
+      set((state) => ({
+        dentition: setSecondaryResult2(toothContext, newValue, state.dentition),
+      })),
+    getToothDiagnoses: () => getToothDiagnoses(get().dentition),
+  }));
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/factories.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/factories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e9c7a3cf216ce3f7fe26f2fdef6cb1af2bcce88c
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/factories.ts
@@ -0,0 +1,135 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiTooth } from "@eshg/dental-api";
+import { ToothDiagnoses } from "@eshg/dental/api/models/ExaminationResult";
+import { ToothDiagnosis } from "@eshg/dental/api/models/ToothDiagnosis";
+import { isDefined } from "remeda";
+
+import { OPTIONAL_TEETH, RELATED_TEETH, TOOTH_TYPES } from "./constants";
+import {
+  AddableTooth,
+  Dentition,
+  Quadrant,
+  QuadrantNumber,
+  Tooth,
+  ToothResult,
+  ToothWithDiagnosis,
+} from "./types";
+
+export function createPrimaryDentition(
+  toothDiagnoses: ToothDiagnoses = {},
+): Dentition {
+  return createDentition(
+    ["T18", "T17", "T16", "T55", "T54", "T53", "T52", "T51"],
+    ["T61", "T62", "T63", "T64", "T65", "T26", "T27", "T28"],
+    ["T71", "T72", "T73", "T74", "T75", "T36", "T37", "T38"],
+    ["T48", "T47", "T46", "T85", "T84", "T83", "T82", "T81"],
+    toothDiagnoses,
+    true,
+  );
+}
+
+export function createSecondaryDentition(
+  toothDiagnoses: ToothDiagnoses = {},
+): Dentition {
+  return createDentition(
+    ["T18", "T17", "T16", "T15", "T14", "T13", "T12", "T11"],
+    ["T21", "T22", "T23", "T24", "T25", "T26", "T27", "T28"],
+    ["T31", "T32", "T33", "T34", "T35", "T36", "T37", "T38"],
+    ["T48", "T47", "T46", "T45", "T44", "T43", "T42", "T41"],
+    toothDiagnoses,
+    false,
+  );
+}
+
+function createDentition(
+  teethQuadrant1: ApiTooth[],
+  teethQuadrant2: ApiTooth[],
+  teethQuadrant3: ApiTooth[],
+  teethQuadrant4: ApiTooth[],
+  toothDiagnoses: ToothDiagnoses = {},
+  isPrimaryDentition: boolean,
+): Dentition {
+  function createToothWithType(
+    tooth: ApiTooth,
+  ): ToothWithDiagnosis | AddableTooth {
+    return OPTIONAL_TEETH.has(tooth) &&
+      resolveToothDiagnosis(tooth, toothDiagnoses) === undefined &&
+      isPrimaryDentition
+      ? createAddableTooth(tooth)
+      : createToothWithDiagnosis(tooth, toothDiagnoses);
+  }
+
+  function processQuadrant(teeth: ApiTooth[]) {
+    return teeth.map(createToothWithType);
+  }
+
+  return {
+    Q1: createQuadrant("Q1", processQuadrant(teethQuadrant1)),
+    Q2: createQuadrant("Q2", processQuadrant(teethQuadrant2)),
+    Q3: createQuadrant("Q3", processQuadrant(teethQuadrant3)),
+    Q4: createQuadrant("Q4", processQuadrant(teethQuadrant4)),
+  };
+}
+
+function createQuadrant(
+  quadrantNumber: QuadrantNumber,
+  teeth: Tooth[],
+): Quadrant {
+  return {
+    quadrantNumber,
+    teeth,
+  };
+}
+
+export function createToothWithDiagnosis(
+  tooth: ApiTooth,
+  toothDiagnoses: ToothDiagnoses = {},
+): ToothWithDiagnosis {
+  const diagnosis = resolveToothDiagnosis(tooth, toothDiagnoses);
+  const toothNumber = diagnosis?.tooth ?? tooth;
+
+  return {
+    type: "ToothWithDiagnosis",
+    toothNumber,
+    toothType: TOOTH_TYPES[toothNumber],
+    isRemovable: OPTIONAL_TEETH.has(toothNumber),
+    mainResult: createToothResult(diagnosis?.mainResult),
+    secondaryResult1: createToothResult(diagnosis?.secondaryResult1),
+    secondaryResult2: createToothResult(diagnosis?.secondaryResult2),
+    previousResults: [],
+  };
+}
+
+function resolveToothDiagnosis(
+  toothNumber: ApiTooth,
+  toothDiagnoses: ToothDiagnoses,
+): ToothDiagnosis | undefined {
+  if (isDefined(toothDiagnoses[toothNumber])) {
+    return toothDiagnoses[toothNumber];
+  }
+
+  const relatedTooth = RELATED_TEETH[toothNumber];
+  if (relatedTooth === undefined) {
+    return undefined;
+  }
+
+  return toothDiagnoses[relatedTooth];
+}
+
+export function createToothResult(value = "", isInvalid = false): ToothResult {
+  return {
+    value,
+    isInvalid,
+  };
+}
+
+export function createAddableTooth(tooth: ApiTooth): AddableTooth {
+  return {
+    type: "AddableTooth",
+    toothNumber: tooth,
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3e73437e5457b312ada020e87b1dc56d9a860c0d
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/types.ts
@@ -0,0 +1,79 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiMainResult, ApiSecondaryResult, ApiTooth } from "@eshg/dental-api";
+
+export type DentalExaminationView =
+  | "UPPER_JAW"
+  | "LOWER_JAW"
+  | "FULL_DENTITION";
+
+export type Dentition = Record<QuadrantNumber, Quadrant>;
+
+export interface Quadrant {
+  quadrantNumber: QuadrantNumber;
+  teeth: Tooth[];
+}
+
+export type QuadrantNumber = "Q1" | "Q2" | "Q3" | "Q4";
+
+export type Tooth = ToothWithDiagnosis | AddableTooth;
+
+export interface ToothWithDiagnosis {
+  type: "ToothWithDiagnosis";
+  toothNumber: ApiTooth;
+  toothType: ToothType;
+  isRemovable: boolean;
+  mainResult: ToothResult;
+  secondaryResult1: ToothResult;
+  secondaryResult2: ToothResult;
+  previousResults: ToothDiagnosisResult[];
+}
+
+export interface AddableTooth {
+  type: "AddableTooth";
+  toothNumber: ApiTooth;
+}
+
+export function isToothWithDiagnosis(
+  tooth: Tooth,
+): tooth is ToothWithDiagnosis {
+  return tooth.type === "ToothWithDiagnosis";
+}
+
+export function isAddableTooth(tooth: Tooth): tooth is AddableTooth {
+  return tooth.type === "AddableTooth";
+}
+
+export function isInUpperJaw(tooth: Tooth) {
+  const quadrantIdentifier = parseInt(tooth.toothNumber.substring(1, 2));
+  return (
+    quadrantIdentifier === 1 ||
+    quadrantIdentifier === 2 ||
+    quadrantIdentifier === 5 ||
+    quadrantIdentifier === 6
+  );
+}
+
+export type ToothType = "PRIMARY_TOOTH" | "SECONDARY_TOOTH";
+
+type ToothDiagnosisResult = ApiMainResult | ApiSecondaryResult;
+
+export interface ToothResult {
+  value: string;
+  isInvalid: boolean;
+}
+
+export interface ToothContext {
+  quadrantNumber: QuadrantNumber;
+  toothIndex: number;
+}
+
+export type FieldVariant = "main" | "secondary1" | "secondary2";
+
+export interface Focus {
+  toothContext: ToothContext;
+  field: FieldVariant;
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/formComponents.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/formComponents.tsx
deleted file mode 100644
index 509149c67331ffe89dc51cc1b6aea49ab9232007..0000000000000000000000000000000000000000
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/formComponents.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-
-import {
-  SoftRequiredBooleanSelectField,
-  SoftRequiredSelectField,
-} from "@eshg/lib-portal/components/form/fieldVariants";
-import { SelectFieldProps } from "@eshg/lib-portal/components/formFields/SelectField";
-import { ReactNode } from "react";
-import { isDefined } from "remeda";
-
-import { AdditionalInformationFormComponents } from "@/lib/businessModules/dental/features/examinations/AdditionalInformationFormSection";
-
-export const ADDITIONAL_INFO_FORM_COMPONENTS: AdditionalInformationFormComponents =
-  {
-    SelectField: <
-      TMultiple extends boolean,
-      TOptionLabel extends string | ReactNode = string,
-    >(
-      props: SelectFieldProps<TMultiple, TOptionLabel>,
-    ) => (
-      <SoftRequiredSelectField<TMultiple, TOptionLabel>
-        {...toSoftRequiredProps(props)}
-      />
-    ),
-    BooleanSelectField: (props) => (
-      <SoftRequiredBooleanSelectField {...toSoftRequiredProps(props)} />
-    ),
-  };
-
-function toSoftRequiredProps<TProps extends { required?: string }>({
-  required,
-  ...props
-}: TProps) {
-  return {
-    ...props,
-    softRequired: isDefined(required),
-    orientation: "vertical",
-  } as const;
-}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/useProphylaxisSessionExaminationForm.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/useProphylaxisSessionExaminationForm.ts
deleted file mode 100644
index 0992303a2f2f2d7015def7e32e037fbf75fa1226..0000000000000000000000000000000000000000
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/useProphylaxisSessionExaminationForm.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-
-import { ExaminationResult } from "@eshg/dental/api/models/ExaminationResult";
-import {
-  mapOptionalValue,
-  mapRequiredValue,
-} from "@eshg/lib-portal/helpers/form";
-import { useFormik } from "formik";
-
-import {
-  ExaminationFormValues,
-  mapToExaminationFormValues,
-} from "@/lib/businessModules/dental/features/examinations/ExaminationFormLayout";
-import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider";
-
-interface UseProphylaxisSessionExaminationFormParams {
-  examinationResult: ExaminationResult | undefined;
-  note: string | undefined;
-  onSubmit: (examinationResult: ExaminationResult) => void;
-}
-
-export function useProphylaxisSessionExaminationForm(
-  params: UseProphylaxisSessionExaminationFormParams,
-) {
-  const { examinationResult, note, onSubmit } = params;
-
-  const isScreening = useProphylaxisSessionStore((state) => state.isScreening);
-
-  const examinationForm = useFormik({
-    initialValues: mapToExaminationFormValues(
-      examinationResult,
-      note, // TODO pass actual note
-    ),
-    onSubmit: (formValues: ExaminationFormValues) => {
-      onSubmit(mapToExaminationResult(isScreening, formValues));
-    },
-    enableReinitialize: true,
-  });
-
-  return examinationForm;
-}
-
-function mapToExaminationResult(
-  screening: boolean,
-  formValues: ExaminationFormValues,
-): ExaminationResult {
-  if (screening) {
-    return {
-      type: "screening",
-      oralHygieneStatus: mapOptionalValue(formValues.oralHygieneStatus),
-      fluorideVarnishApplied:
-        mapOptionalValue(formValues.fluorideVarnishApplied) ?? false,
-    };
-  }
-
-  // TODO: Remove when fluoridation only examination is handled without form
-  return {
-    type: "fluoridation",
-    fluorideVarnishApplied: mapRequiredValue(formValues.fluorideVarnishApplied),
-  };
-}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationBottomBar.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationBottomBar.tsx
similarity index 90%
rename from employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationBottomBar.tsx
rename to employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationBottomBar.tsx
index 08a2d09594c9b770bd1558d34db3db40abe11e83..80d00a63c2315fb22e4dc2ef2fda312c6850ad24 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationBottomBar.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationBottomBar.tsx
@@ -12,14 +12,14 @@ import { isDefined } from "remeda";
 
 import { StickyBottomButtonBar } from "@/lib/shared/components/buttons/StickyBottomButtonBar";
 
-interface ProphylaxisSessionExaminationBottomBarProps {
+interface ParticipantExaminationBottomBarProps {
   onPreviousParticipantClicked?: () => void;
   onNextParticipantClicked?: () => void;
   onOverviewClicked: () => void;
 }
 
-export function ProphylaxisSessionExaminationBottomBar(
-  props: ProphylaxisSessionExaminationBottomBarProps,
+export function ParticipantExaminationBottomBar(
+  props: ParticipantExaminationBottomBarProps,
 ) {
   const {
     onPreviousParticipantClicked,
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationForm.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationForm.tsx
similarity index 84%
rename from employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationForm.tsx
rename to employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationForm.tsx
index d4e74e6b0b82700b0337a80cfb0e54f9633171ba..436a2659e9960c2e6e8a1c891719871fe1606a31 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationForm.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationForm.tsx
@@ -20,14 +20,13 @@ const FullHeightFormPlus = styled(FormPlus)({
   height: "100%",
 });
 
-export interface ProphylaxisSessionExaminationFormProps
-  extends RequiresChildren {
+export interface ParticipantExaminationFormProps extends RequiresChildren {
   form: FormikProps<ExaminationFormValues>;
   bottomBar: ReactNode;
 }
 
-export function ProphylaxisSessionExaminationForm(
-  props: ProphylaxisSessionExaminationFormProps,
+export function ParticipantExaminationForm(
+  props: ParticipantExaminationFormProps,
 ) {
   return (
     <FormikProvider value={props.form}>
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationPage.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationPage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..99ca0749691fa952bdeb512532190bd259553f82
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationPage.tsx
@@ -0,0 +1,118 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ChildExamination } from "@eshg/dental/api/models/ChildExamination";
+import { useRouter } from "next/navigation";
+import { useState } from "react";
+import { isDefined } from "remeda";
+
+import { AdditionalInformationFormSection } from "@/lib/businessModules/dental/features/examinations/AdditionalInformationFormSection";
+import { ExaminationFormLayout } from "@/lib/businessModules/dental/features/examinations/ExaminationFormLayout";
+import { NoteFormSection } from "@/lib/businessModules/dental/features/examinations/NoteFormSection";
+import { DentalExaminationFormSection } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExamination/DentalExaminationFormSection";
+import { useDentalExaminationStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/dentalExaminationStore/DentalExaminationStoreProvider";
+import { ParticipantExaminationBottomBar } from "@/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationBottomBar";
+import { ParticipantExaminationForm } from "@/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationForm";
+import { ParticipantExaminationToolbar } from "@/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationToolbar";
+import { useParticipantExaminationForm } from "@/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/useParticipantExaminationForm";
+import { useParticipantNavigation } from "@/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/useParticipantNavigation";
+import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
+import { StickyToolbarLayout } from "@/lib/shared/components/layout/StickyToolbarLayout";
+
+interface ParticipantExaminationPageProps {
+  participant: ChildExamination;
+  participantIndex: number;
+  participantsLength: number;
+}
+
+export function ParticipantExaminationPage(
+  props: ParticipantExaminationPageProps,
+) {
+  const { participant, participantIndex, participantsLength } = props;
+  const router = useRouter();
+  const prophylaxisSessionId = useProphylaxisSessionStore((state) => state.id);
+  const isScreening = useProphylaxisSessionStore((state) => state.isScreening);
+  const fluoridationVarnish = useProphylaxisSessionStore(
+    (state) => state.fluoridationVarnish,
+  );
+  const setExamination = useProphylaxisSessionStore(
+    (state) => state.setExamination,
+  );
+  const getToothDiagnoses = useDentalExaminationStore(
+    (state) => state.getToothDiagnoses,
+  );
+
+  const [nextRoute, setNextRoute] = useState<string>();
+  const examinationForm = useParticipantExaminationForm({
+    initialValues: participant,
+    onSubmit: (values) => {
+      try {
+        const toothDiagnoses = getToothDiagnoses();
+        const result =
+          values.result?.type === "screening"
+            ? { ...values.result, toothDiagnoses }
+            : values.result;
+
+        setExamination(participant.examinationId, result, values.note);
+        if (isDefined(nextRoute)) {
+          router.push(nextRoute);
+        }
+      } catch {
+        // TODO handle invalid tooth diagnoses
+      } finally {
+        setNextRoute(undefined);
+      }
+    },
+  });
+  const examinationNavigation = useParticipantNavigation({
+    participantIndex,
+    participantsLength,
+    onNavigate: (nextRoute) => {
+      setNextRoute(nextRoute);
+      void examinationForm.submitForm();
+    },
+  });
+
+  return (
+    <StickyToolbarLayout
+      toolbar={
+        <ParticipantExaminationToolbar
+          prophylaxisSessionId={prophylaxisSessionId}
+          participant={participant}
+          participantIndex={participantIndex}
+          onBackClicked={examinationNavigation.gotoOverview}
+        />
+      }
+    >
+      <ParticipantExaminationForm
+        form={examinationForm}
+        bottomBar={
+          <ParticipantExaminationBottomBar
+            onPreviousParticipantClicked={
+              examinationNavigation.gotoPreviousParticipant
+            }
+            onNextParticipantClicked={examinationNavigation.gotoNextParticipant}
+            onOverviewClicked={examinationNavigation.gotoOverview}
+          />
+        }
+      >
+        <ExaminationFormLayout
+          additionalInformation={
+            <AdditionalInformationFormSection
+              screening={isScreening}
+              fluoridation={isDefined(fluoridationVarnish)}
+              fluoridationConsentGiven={participant.fluoridationConsentGiven}
+              status={participant.status}
+            />
+          }
+          dentalExamination={
+            isScreening ? <DentalExaminationFormSection /> : undefined
+          }
+          note={<NoteFormSection />}
+        />
+      </ParticipantExaminationForm>
+    </StickyToolbarLayout>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationToolbar.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationToolbar.tsx
similarity index 87%
rename from employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationToolbar.tsx
rename to employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationToolbar.tsx
index 3e3b3cf98c5c97c276b49ab35ae8a7e632572871..c82bd24e6f8b55158ad370740e27f6b8ebe4cb2e 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/ProphylaxisSessionExaminationToolbar.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/ParticipantExaminationToolbar.tsx
@@ -15,15 +15,15 @@ import {
   TabNavigationToolbar,
 } from "@/lib/shared/components/tabNavigationToolbar/TabNavigationToolbar";
 
-interface ProphylaxisSessionExaminationToolbarProps {
+interface ParticipantExaminationToolbarProps {
   prophylaxisSessionId: string;
   participant: ChildExamination;
   participantIndex: number;
   onBackClicked: () => void;
 }
 
-export function ProphylaxisSessionExaminationToolbar(
-  props: ProphylaxisSessionExaminationToolbarProps,
+export function ParticipantExaminationToolbar(
+  props: ParticipantExaminationToolbarProps,
 ) {
   return (
     <TabNavigationToolbar
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/useParticipantExaminationForm.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/useParticipantExaminationForm.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b6df30289d4890336871f58f6501ef1d4a889f1f
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/useParticipantExaminationForm.ts
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  ExaminationResult,
+  FluoridationExaminationResult,
+  ScreeningExaminationResult,
+  isEmptyExaminationResult,
+} from "@eshg/dental/api/models/ExaminationResult";
+import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
+import { useFormik } from "formik";
+
+import {
+  ExaminationFormValues,
+  mapToExaminationFormValues,
+} from "@/lib/businessModules/dental/features/examinations/ExaminationFormLayout";
+import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
+
+interface ExaminationInputValues {
+  result?: ExaminationResult;
+  note?: string;
+}
+
+interface ExaminationOutputValues {
+  result?: ExaminationResult;
+  note?: string;
+}
+
+interface UseParticipantExaminationFormParams {
+  initialValues: ExaminationInputValues;
+  onSubmit: (values: ExaminationOutputValues) => void;
+}
+
+export function useParticipantExaminationForm(
+  params: UseParticipantExaminationFormParams,
+) {
+  const { initialValues, onSubmit } = params;
+
+  const isScreening = useProphylaxisSessionStore((state) => state.isScreening);
+
+  return useFormik({
+    initialValues: mapToExaminationFormValues(
+      initialValues.result,
+      initialValues.note,
+    ),
+    onSubmit: (formValues: ExaminationFormValues) => {
+      onSubmit(mapToExaminationValues(isScreening, formValues));
+    },
+    enableReinitialize: true,
+  });
+}
+
+function mapToExaminationValues(
+  screening: boolean,
+  formValues: ExaminationFormValues,
+): ExaminationOutputValues {
+  return {
+    result: mapToExaminationResult(screening, formValues),
+    note: mapOptionalValue(formValues.note),
+  };
+}
+
+function mapToExaminationResult(
+  screening: boolean,
+  formValues: ExaminationFormValues,
+): ExaminationResult | undefined {
+  let result: FluoridationExaminationResult | ScreeningExaminationResult;
+  if (screening) {
+    result = {
+      type: "screening",
+      oralHygieneStatus: mapOptionalValue(formValues.oralHygieneStatus),
+      fluorideVarnishApplied: mapOptionalValue(
+        formValues.fluorideVarnishApplied,
+      ),
+      toothDiagnoses: {},
+    };
+  } else {
+    // TODO: Remove when fluoridation only examination is handled without form
+    result = {
+      type: "fluoridation",
+      fluorideVarnishApplied: mapOptionalValue(
+        formValues.fluorideVarnishApplied,
+      ),
+    };
+  }
+
+  if (isEmptyExaminationResult(result)) {
+    return undefined;
+  }
+  return result;
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/useProphylaxisSessionExaminationNavigation.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/useParticipantNavigation.ts
similarity index 91%
rename from employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/useProphylaxisSessionExaminationNavigation.ts
rename to employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/useParticipantNavigation.ts
index b73b28500a1127c278b433182c1ba3705bf309df..f4b36528a3fa3f89d46cfb82989e195fd86c66ea 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/examination/useProphylaxisSessionExaminationNavigation.ts
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/participantExamination/useParticipantNavigation.ts
@@ -5,7 +5,7 @@
 
 import { routes } from "@eshg/dental/shared/routes";
 
-import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider";
+import { useProphylaxisSessionStore } from "@/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider";
 
 interface UseParticipantNavigationResult {
   gotoPreviousParticipant?: () => void;
@@ -19,7 +19,7 @@ interface UseParticipantNavigationParams {
   onNavigate: (route: string) => void;
 }
 
-export function useProphylaxisSessionExaminationNavigation(
+export function useParticipantNavigation(
   params: UseParticipantNavigationParams,
 ): UseParticipantNavigationResult {
   const { participantIndex, participantsLength, onNavigate } = params;
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider.tsx b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider.tsx
similarity index 89%
rename from employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider.tsx
rename to employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider.tsx
index d616915a897d393299cb2955a7adc976cdc0398a..bf135bed992eba06aadcd89049dd128b3ad532c2 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/ProphylaxisSessionStoreProvider.tsx
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/ProphylaxisSessionStoreProvider.tsx
@@ -8,7 +8,7 @@
 import { ChildExamination } from "@eshg/dental/api/models/ChildExamination";
 import { ProphylaxisSessionDetails } from "@eshg/dental/api/models/ProphylaxisSessionDetails";
 import { RequiresChildren } from "@eshg/lib-portal/types/react";
-import { createContext, useContext, useEffect, useState } from "react";
+import { createContext, useContext, useState } from "react";
 import { useStore } from "zustand";
 import { useShallow } from "zustand/react/shallow";
 
@@ -19,6 +19,7 @@ import {
   createProphylaxisSessionStore,
   initProphylaxisSessionStore,
 } from "./prophylaxisSessionStore";
+import { useSyncIncomingProphylaxisSessionChanges } from "./useSyncIncomingProphylaxisSessionChanges";
 
 type ProphylaxisSessionStoreApi = ReturnType<
   typeof createProphylaxisSessionStore
@@ -41,10 +42,7 @@ export function ProphylaxisSessionStoreProvider({
     ),
   );
 
-  const { setState } = store;
-  useEffect(() => {
-    setState(prophylaxisSession);
-  }, [prophylaxisSession, setState]);
+  useSyncIncomingProphylaxisSessionChanges(store, prophylaxisSession);
 
   return (
     <ProphylaxisSessionStoreContext.Provider value={store}>
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/actions.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/actions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6e7baef74870029c0ea699e08def612ed8863287
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/actions.ts
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ExaminationResult } from "@eshg/dental/api/models/ExaminationResult";
+
+import { ParticipantFilters } from "./participantFilters";
+import { ProphylaxisSessionState } from "./prophylaxisSessionStore";
+
+type SetParticipantFiltersState = Pick<
+  ProphylaxisSessionState,
+  "participantFilters"
+>;
+
+export function setParticipantFilters(
+  filters: Partial<ParticipantFilters>,
+  state: SetParticipantFiltersState,
+): SetParticipantFiltersState {
+  return {
+    participantFilters: {
+      ...state.participantFilters,
+      ...filters,
+    },
+  };
+}
+
+type SetExaminationState = Pick<
+  ProphylaxisSessionState,
+  "participants" | "changedExaminationsById"
+>;
+
+export function setExamination(
+  examinationId: string,
+  result: ExaminationResult | undefined,
+  note: string | undefined,
+  state: SetExaminationState,
+): SetExaminationState {
+  const updatedParticipants = state.participants.map((participant) => {
+    if (participant.examinationId !== examinationId) {
+      return participant;
+    }
+
+    return {
+      ...participant,
+      result,
+      note,
+    };
+  });
+
+  return {
+    participants: updatedParticipants,
+    changedExaminationsById: new Set(state.changedExaminationsById).add(
+      examinationId,
+    ),
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/participantFilters.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/participantFilters.ts
similarity index 100%
rename from employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/participantFilters.ts
rename to employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/participantFilters.ts
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/participantSorting.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/participantSorting.ts
similarity index 97%
rename from employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/participantSorting.ts
rename to employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/participantSorting.ts
index ab190f2bdb6b2aff51e9a8d0b8bccfb0e98f7e05..0e8ad45086e7706606b4d7c9c5430dd28cb992e2 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/participantSorting.ts
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/participantSorting.ts
@@ -17,7 +17,7 @@ export interface ParticipantSorting {
 
 export type ParticipantSortKey = keyof Omit<
   ChildExamination,
-  "childId" | "result" | "note"
+  "childId" | "result" | "note" | "examinationId" | "examinationVersion"
 >;
 export type ParticipantSortDirection = "asc" | "desc";
 
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/prophylaxisSessionStore.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/prophylaxisSessionStore.ts
similarity index 63%
rename from employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/prophylaxisSessionStore.ts
rename to employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/prophylaxisSessionStore.ts
index 907ad84fb16cf7da94066875f2fc2a17d9d4a66d..d68f9ef0cccc3743474d3038616a731b1670acbe 100644
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/prophylaxisSessionStore.ts
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/prophylaxisSessionStore.ts
@@ -7,22 +7,30 @@ import { ExaminationResult } from "@eshg/dental/api/models/ExaminationResult";
 import { ProphylaxisSessionDetails } from "@eshg/dental/api/models/ProphylaxisSessionDetails";
 import { createStore } from "zustand";
 
+import { setExamination, setParticipantFilters } from "./actions";
 import { ParticipantFilters } from "./participantFilters";
 import { ParticipantSorting } from "./participantSorting";
-import { replaceExaminationResult } from "./replaceExaminationResult";
 
 export interface ProphylaxisSessionState extends ProphylaxisSessionDetails {
   participantFilters: ParticipantFilters;
   participantSorting: ParticipantSorting;
+
+  changedExaminationsById: Set<string>;
 }
 
 export interface ProphylaxisSessionActions {
   setParticipantFilters: (filtersChange: Partial<ParticipantFilters>) => void;
   setParticipantSorting: (sorting: ParticipantSorting) => void;
-  setExaminationResult: (
-    participantId: string,
-    examinationResult: ExaminationResult,
+  setProphylaxisSession: (
+    prophylaxisSession: ProphylaxisSessionDetails,
+  ) => void;
+  setExamination: (
+    examinationId: string,
+    result: ExaminationResult | undefined,
+    note: string | undefined,
   ) => void;
+
+  markAsSynchronized: () => void;
 }
 
 export type ProphylaxisSessionStore = ProphylaxisSessionState &
@@ -45,6 +53,8 @@ export function initProphylaxisSessionStore(
     ...prophylaxisSession,
     participantFilters: initialFilters,
     participantSorting: initialSorting,
+
+    changedExaminationsById: new Set(),
   };
 }
 
@@ -54,27 +64,16 @@ export function createProphylaxisSessionStore(
   return createStore<ProphylaxisSessionStore>()((set) => ({
     ...initialState,
     setParticipantFilters: (filters) => {
-      set((state) => ({
-        participantFilters: {
-          ...state.participantFilters,
-          ...filters,
-        },
-      }));
+      set((state) => setParticipantFilters(filters, state));
     },
-    setParticipantSorting: (participantSorting) =>
-      set({
-        participantSorting,
-      }),
-    setExaminationResult: (
-      participantId: string,
-      examinationResult: ExaminationResult,
-    ) =>
-      set((state) => ({
-        participants: replaceExaminationResult(
-          participantId,
-          examinationResult,
-          state.participants,
-        ),
-      })),
+    setParticipantSorting: (participantSorting) => set({ participantSorting }),
+    setProphylaxisSession: (prophylaxisSession) => set(prophylaxisSession),
+    setExamination: (
+      examinationId: string,
+      result: ExaminationResult | undefined,
+      note: string | undefined,
+    ) => set((state) => setExamination(examinationId, result, note, state)),
+
+    markAsSynchronized: () => set({ changedExaminationsById: new Set() }),
   }));
 }
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/useSyncIncomingProphylaxisSessionChanges.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/useSyncIncomingProphylaxisSessionChanges.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c039a6781618958dd06fae73dd2e79ce4b5b5f3a
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/useSyncIncomingProphylaxisSessionChanges.ts
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ProphylaxisSessionDetails } from "@eshg/dental/api/models/ProphylaxisSessionDetails";
+import { useEffect } from "react";
+import { StoreApi, useStore } from "zustand";
+
+import { type ProphylaxisSessionStore } from "./prophylaxisSessionStore";
+
+export function useSyncIncomingProphylaxisSessionChanges(
+  store: StoreApi<ProphylaxisSessionStore>,
+  prophylaxisSession: ProphylaxisSessionDetails,
+) {
+  const changedExaminationsById = useStore(
+    store,
+    (state) => state.changedExaminationsById,
+  );
+  const setProphylaxisSession = useStore(
+    store,
+    (state) => state.setProphylaxisSession,
+  );
+
+  const canUpdate = changedExaminationsById.size === 0;
+  useEffect(() => {
+    if (canUpdate) {
+      setProphylaxisSession(prophylaxisSession);
+    }
+  }, [prophylaxisSession, canUpdate, setProphylaxisSession]);
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/useSyncOutgoingProphylaxisSessionChanges.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/useSyncOutgoingProphylaxisSessionChanges.ts
new file mode 100644
index 0000000000000000000000000000000000000000..256452a443220ad29e1e5d51d656b6a6b44376df
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/prophylaxisSessionStore/useSyncOutgoingProphylaxisSessionChanges.ts
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  ApiExaminationResult,
+  ApiUpdateExaminationsInBulkRequest,
+} from "@eshg/dental-api";
+import { ChildExamination } from "@eshg/dental/api/models/ChildExamination";
+import {
+  AbsenceExaminationResult,
+  ExaminationResult,
+  FluoridationExaminationResult,
+  ScreeningExaminationResult,
+} from "@eshg/dental/api/models/ExaminationResult";
+import { useUpdateProphylaxisSessionExaminations } from "@eshg/dental/api/mutations/prophylaxisSessionApi";
+import { useEffect, useRef } from "react";
+
+import { useProphylaxisSessionStore } from "./ProphylaxisSessionStoreProvider";
+
+export function useSyncOutgoingProphylaxisSessionChanges() {
+  const lastSynchronizedChanges = useRef<Set<string> | null>(null);
+  const prophylaxisSessionId = useProphylaxisSessionStore((state) => state.id);
+  const participants = useProphylaxisSessionStore(
+    (state) => state.participants,
+  );
+  const changedExaminationsById = useProphylaxisSessionStore(
+    (state) => state.changedExaminationsById,
+  );
+  const markAsSynchronized = useProphylaxisSessionStore(
+    (state) => state.markAsSynchronized,
+  );
+  const { mutate: updateProphylaxisSessionExaminations } =
+    useUpdateProphylaxisSessionExaminations(prophylaxisSessionId, {
+      /**
+       * pass success handler as hook option to ensure execution
+       * @see https://tkdodo.eu/blog/mastering-mutations-in-react-query#some-callbacks-might-not-fire
+       */
+      onSuccess: markAsSynchronized,
+    });
+
+  useEffect(() => {
+    if (
+      changedExaminationsById.size > 0 &&
+      changedExaminationsById !== lastSynchronizedChanges.current
+    ) {
+      lastSynchronizedChanges.current = changedExaminationsById;
+      const changedExaminations = participants.filter((participant) =>
+        changedExaminationsById.has(participant.examinationId),
+      );
+      updateProphylaxisSessionExaminations(
+        changedExaminations.map(mapExaminationToRequest),
+      );
+    }
+  }, [
+    changedExaminationsById,
+    participants,
+    updateProphylaxisSessionExaminations,
+    markAsSynchronized,
+  ]);
+}
+
+function mapExaminationToRequest(
+  examination: ChildExamination,
+): ApiUpdateExaminationsInBulkRequest {
+  return {
+    id: examination.examinationId,
+    version: examination.examinationVersion,
+    result: mapExaminationResultToRequest(examination.result),
+    note: examination.note,
+  };
+}
+
+function mapExaminationResultToRequest(
+  examinationResult: ExaminationResult | undefined,
+): ApiExaminationResult | undefined {
+  switch (examinationResult?.type) {
+    case "screening":
+      return mapScreeningResult(examinationResult);
+    case "fluoridation":
+      return mapFluoridationResult(examinationResult);
+    case "absence":
+      return mapAbsenceResult(examinationResult);
+    case undefined:
+      return undefined;
+  }
+}
+
+function mapScreeningResult(
+  screeningResult: ScreeningExaminationResult,
+): ApiExaminationResult {
+  return {
+    type: "ScreeningExaminationResult",
+    fluorideVarnishApplied: screeningResult.fluorideVarnishApplied,
+    oralHygieneStatus: screeningResult.oralHygieneStatus,
+    toothDiagnoses: Object.values(screeningResult.toothDiagnoses),
+  };
+}
+
+function mapFluoridationResult(
+  fluoridationResult: FluoridationExaminationResult,
+): ApiExaminationResult {
+  return {
+    type: "FluoridationExaminationResult",
+    fluorideVarnishApplied: fluoridationResult.fluorideVarnishApplied,
+  };
+}
+
+function mapAbsenceResult(
+  absenceResult: AbsenceExaminationResult,
+): ApiExaminationResult {
+  return {
+    type: "AbsenceExaminationResult",
+    reasonForAbsence: absenceResult.reasonForAbsence,
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/staff.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/staff.ts
new file mode 100644
index 0000000000000000000000000000000000000000..427ddd822f9d59f1c0756008b641b3fd10902b91
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/staff.ts
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  getAllDentalAssistantsQuery,
+  getAllDentistsQuery,
+} from "@eshg/dental/api/queries/staffApi";
+import { useSuspenseQueries } from "@tanstack/react-query";
+
+import { useUserApi } from "@/lib/baseModule/api/clients";
+
+export function useGetStaff() {
+  const userApi = useUserApi();
+  const [{ data: allDentists }, { data: allDentalAssistants }] =
+    useSuspenseQueries({
+      queries: [
+        getAllDentistsQuery(userApi),
+        getAllDentalAssistantsQuery(userApi),
+      ],
+    });
+
+  return { allDentists, allDentalAssistants };
+}
diff --git a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/replaceExaminationResult.ts b/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/replaceExaminationResult.ts
deleted file mode 100644
index bbd050919c15db6617381a25e5830ad5b42ae88c..0000000000000000000000000000000000000000
--- a/employee-portal/src/lib/businessModules/dental/features/prophylaxisSessions/store/replaceExaminationResult.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-
-import { ChildExamination } from "@eshg/dental/api/models/ChildExamination";
-import { ExaminationResult } from "@eshg/dental/api/models/ExaminationResult";
-
-export function replaceExaminationResult(
-  participantId: string,
-  examinationResult: ExaminationResult,
-  participants: ChildExamination[],
-): ChildExamination[] {
-  return participants.map((participant) => {
-    if (participant.childId !== participantId) {
-      return participant;
-    }
-
-    return {
-      ...participant,
-      result: examinationResult,
-    };
-  });
-}
diff --git a/employee-portal/src/lib/businessModules/dental/import/ImportChildrenSidebar.tsx b/employee-portal/src/lib/businessModules/dental/import/ImportChildrenSidebar.tsx
index f7ccc912349ed29b77d9be8c3da2cc45538ce1da..2a6aaabfa1638da6f0311331a42dccf851e155db 100644
--- a/employee-portal/src/lib/businessModules/dental/import/ImportChildrenSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/dental/import/ImportChildrenSidebar.tsx
@@ -78,6 +78,7 @@ function ImportChildrenSidebar(props: SidebarWithFormRefProps) {
               name="institution"
               label="Einrichtung"
               categories={SCHOOL_OR_DAYCARE}
+              placeholder="Schule/Kita suchen"
               required="Bitte eine Schule/Kita angeben."
               getOptionLabel={getInstitutionOptionLabel}
             />
diff --git a/employee-portal/src/lib/businessModules/inspection/api/clients.ts b/employee-portal/src/lib/businessModules/inspection/api/clients.ts
index 8d814fbb34febad962eff10d932082fe5670a9f7..95c2137b82cc4086dfb4dcb70ae3bbccd5c9afce 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/clients.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/clients.ts
@@ -28,7 +28,7 @@ import {
   TaskApi,
   TextBlockApi,
   WebSearchApi,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
 
 export function useConfiguration() {
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/checklist.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/checklist.ts
index c4635a1684184c208b09203e4fc4dd8ecaa43945..9b132f4b253eb53bbb93ba0b1d230261e33fa713 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/checklist.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/checklist.ts
@@ -7,7 +7,7 @@ import {
   ApiUpdateChecklistElementsInner,
   ChecklistDeleteFileRequest,
   UpdateChecklistRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/checklistDefinition.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/checklistDefinition.ts
index 3d7637df8920baefb2a0fe1b770142bc3ec30c2d..c3546279f4b370b583a5a2167ae2ec187ee29584 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/checklistDefinition.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/checklistDefinition.ts
@@ -12,7 +12,7 @@ import {
   ApiCreateNewChecklistDefinitionRequest,
   DeleteChecklistDefinitionFromCentralRepoRequest,
   UpdateChecklistDefinitionToCentralRepoRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/facility.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/facility.ts
index 060dc724d7f989da134ef1dc78c4ab6874ac4b5c..c998b63694c6455a9d30a4f77201274b1744dbb8 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/facility.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/facility.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspLinkBaseFacilityRequest } from "@eshg/employee-portal-api/inspection";
+import { ApiInspLinkBaseFacilityRequest } from "@eshg/inspection-api";
 import { downloadFileAndOpen } from "@eshg/lib-portal/api/files/download";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/incidents.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/incidents.ts
index 9bd704e6ff303f445573840135bf912d6452961e..373630a5ee554d2311698e05544fee685227f2a4 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/incidents.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/incidents.ts
@@ -7,7 +7,7 @@ import {
   CreateIncidentRequest,
   DeleteIncidentRequest,
   UpdateIncidentRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/inspection.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/inspection.ts
index a72e01f72f046a48d5bd83053e05d63190cf70c1..b89137432eb5ef221d4fa08ed9d3638de8e3188d 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/inspection.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/inspection.ts
@@ -10,7 +10,7 @@ import {
   ResolveInspectionDuplicateRequest,
   StartInspectionRequest,
   UpdateInspectionRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/inventory.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/inventory.ts
index f25660533e9f72ffaf7eaaa6ae33d257790e794a..5f68b71061129deb61702b9608a9bdaf7be14ff5 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/inventory.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/inventory.ts
@@ -4,7 +4,7 @@
  */
 
 import { ApiErrorCode } from "@eshg/base-api";
-import { ModifyInventoryRequest } from "@eshg/employee-portal-api/inspection";
+import { ModifyInventoryRequest } from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/objectTypes.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/objectTypes.ts
index 4461fafb316eeab8e3678eff2d0fc6b182d88d49..c0d157fe8557a0d1ee5c8aebdaf9ea06f45a6927 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/objectTypes.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/objectTypes.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUpdateObjectTypeRequest } from "@eshg/employee-portal-api/inspection";
+import { ApiUpdateObjectTypeRequest } from "@eshg/inspection-api";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/packlist.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/packlist.ts
index 51a6bb4ba05744aaeb56acf2126fa29595a78d8c..77bcd2bec076e9a02909fbb5c73dc74d0797b676 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/packlist.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/packlist.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { CheckPacklistElementRequest } from "@eshg/employee-portal-api/inspection";
+import { CheckPacklistElementRequest } from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/packlistDefinition.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/packlistDefinition.ts
index 6ceab5ef0ca54e6559981d169ace2739fcf55593..629f085fdba45f83fc7c5d8353b544391fe6ef1b 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/packlistDefinition.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/packlistDefinition.ts
@@ -7,7 +7,7 @@ import {
   ApiAddPacklistDefinitionRevisionRequest,
   ApiCreateNewPacklistDefinitionRequest,
   ApiPacklistDefinitionElement,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 
 import { usePacklistDefinitionApi } from "@/lib/businessModules/inspection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/processImport.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/processImport.ts
index db55b928caff5ebf9dae16f220e27c5a845b4836..6397a0bfc45c040e1da0db1e2b05435867d7b41b 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/processImport.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/processImport.ts
@@ -8,7 +8,7 @@ import {
   ApiImportStatisticsFromJSON,
   ApiResponse,
   ImportProcessesRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 
 import { useImportApi } from "@/lib/businessModules/inspection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/resources.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/resources.ts
index 8016467f1744e532d7a567d40a887238b6fe84c1..fc33315703af94c9f97d96d4c2606d4dc6498535 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/resources.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/resources.ts
@@ -6,7 +6,7 @@
 import {
   AddResourceRequest,
   DeleteResourceRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/textblocks.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/textblocks.ts
index c95b013876142d3f0f9e2380d3f34189e304908f..45c850e924f1a14f2f039b83228947c3d05570e4 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/textblocks.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/textblocks.ts
@@ -6,7 +6,7 @@
 import {
   ApiTextBlockRequest,
   UpdateTextBlockRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 
 import { useTextBlockApi } from "@/lib/businessModules/inspection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/mutations/webSearch.ts b/employee-portal/src/lib/businessModules/inspection/api/mutations/webSearch.ts
index cac7cbdaabd027e7b333a53b6c19da864c3d9ab0..d639720fe9b75bc288e34074261224bada446b25 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/mutations/webSearch.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/mutations/webSearch.ts
@@ -9,7 +9,7 @@ import {
   SaveQueryRequest,
   UpdateWebSearchByIdRequest,
   UpdateWebSearchEntryRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/archiving.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/archiving.ts
index 6af542a46e240218ee81abc9cf30bbeacd778b34..a6fc41ac818f44f025b80beff16082cdd0ac086b 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/archiving.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/archiving.ts
@@ -6,7 +6,7 @@
 import {
   GetArchivableProceduresRequest,
   GetRelevantArchivableProceduresRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 
 import { useArchivingApi } from "@/lib/businessModules/inspection/api/clients";
 import { archivingApiQueryKey } from "@/lib/businessModules/inspection/api/queries/apiQueryKeys";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/checklist.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/checklist.ts
index 4f1e6653b0346bcd89fa7a4aa4b6b7775df7c6aa..26d3801562ddbef8ceadbe5514534746a7045947 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/checklist.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/checklist.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ChecklistApi } from "@eshg/employee-portal-api/inspection";
+import { ChecklistApi } from "@eshg/inspection-api";
 import { queryOptions } from "@tanstack/react-query";
 
 import { checklistApiQueryKey } from "@/lib/businessModules/inspection/api/queries/apiQueryKeys";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/checklistDefinition.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/checklistDefinition.ts
index 46cabb9d94d234a3308b24086730678177d2ade3..974b820ed44160f798a52dafbc29538ec0d89c8f 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/checklistDefinition.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/checklistDefinition.ts
@@ -6,7 +6,7 @@
 import {
   ChecklistDefinitionApi,
   ChecklistDefinitionCentralRepoApi,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import {
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/facility.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/facility.ts
index 6149b37d568d8af0f0157d9d8782501ec2d9689b..7813d8656b0f239e9d2e32941d38e865f3404906 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/facility.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/facility.ts
@@ -3,10 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  FacilityApi,
-  GetPendingFacilitiesRequest,
-} from "@eshg/employee-portal-api/inspection";
+import { FacilityApi, GetPendingFacilitiesRequest } from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/feature.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/feature.ts
index c4d9df1609437b68577fdd82df4fc79e043a0526..8ff98872a3a39bb2e515d9418a7e852899313b32 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/feature.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/feature.ts
@@ -6,7 +6,7 @@
 import {
   ApiGetInspectionFeatureTogglesResponse,
   ApiInspectionFeature,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import {
   FeatureToggleQueryOptions,
   selectDisabledOldFeature,
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/geo.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/geo.ts
index 04e54c370986f91924a257c2863562e4e6381c64..eb4a1cedf427d7174e8a3467e555e8a2f275b453 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/geo.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/geo.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { InspectionGeoApi } from "@eshg/employee-portal-api/inspection";
+import { InspectionGeoApi } from "@eshg/inspection-api";
 import { QueryClient } from "@tanstack/react-query";
 
 import { inspectionGeoApiQueryKey } from "@/lib/businessModules/inspection/api/queries/apiQueryKeys";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/incidents.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/incidents.ts
index 0a02ba5cb7eebe5d5807132667f0c8d4eb444d19..451c6e78462dd4adb1e4a7a5ec056471d00ddc0b 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/incidents.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/incidents.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { InspectionIncidentApi } from "@eshg/employee-portal-api/inspection";
+import { InspectionIncidentApi } from "@eshg/inspection-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import { useIncidentApi } from "@/lib/businessModules/inspection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/inspection.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/inspection.ts
index 5c4838b5d35401b1aaf9ea73e963db5c194d5fc2..d57f40a37313c480ea939b9f635b6373fb397938 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/inspection.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/inspection.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { InspectionApi } from "@eshg/employee-portal-api/inspection";
+import { InspectionApi } from "@eshg/inspection-api";
 import {
   queryOptions,
   useQueryClient,
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/inspectionReport.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/inspectionReport.ts
index 5d0daeb650c11fe2952091b282c57de5b3cf68d0..bc9f6093ee5d8ccfe35be1d33c6479b0d20e9243 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/inspectionReport.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/inspectionReport.ts
@@ -9,7 +9,7 @@ import {
   EditorApi,
   InspectionApi,
   TextBlockApi,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import {
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/objectTypes.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/objectTypes.ts
index 60550f063d17565c56d7e539c65c954f8e13f45a..42802d1352a0623a52cbd334e30fb5a535aaab99 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/objectTypes.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/objectTypes.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ObjectTypeApi } from "@eshg/employee-portal-api/inspection";
+import { ObjectTypeApi } from "@eshg/inspection-api";
 import { STATIC_QUERY_OPTIONS } from "@eshg/lib-portal/api/queryOptions";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/packlistDefinition.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/packlistDefinition.ts
index e996bfdf77cd50a7dda1f2627bedca0ff618c4f9..3e0b823886265c099d962d55d2e81242aa5635de 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/packlistDefinition.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/packlistDefinition.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { PacklistDefinitionApi } from "@eshg/employee-portal-api/inspection";
+import { PacklistDefinitionApi } from "@eshg/inspection-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import { usePacklistDefinitionApi } from "@/lib/businessModules/inspection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/textblocks.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/textblocks.ts
index bf85dab6e4f913a61e5e4deb4c6bc2767a26910f..f249e74bac60ba2d44aba4de59e677b504f2aed8 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/textblocks.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/textblocks.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { GetTextBlocksRequest } from "@eshg/employee-portal-api/inspection";
+import { GetTextBlocksRequest } from "@eshg/inspection-api";
 import { useSuspenseQuery } from "@tanstack/react-query";
 
 import { useTextBlockApi } from "@/lib/businessModules/inspection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/inspection/api/queries/webSearch.ts b/employee-portal/src/lib/businessModules/inspection/api/queries/webSearch.ts
index d1147640882386b6eb403e215d312a343c070102..5ebf7e05f94ba6e1e581c40a851086662e447e4b 100644
--- a/employee-portal/src/lib/businessModules/inspection/api/queries/webSearch.ts
+++ b/employee-portal/src/lib/businessModules/inspection/api/queries/webSearch.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { SearchRequest } from "@eshg/employee-portal-api/inspection";
+import { SearchRequest } from "@eshg/inspection-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useSuspenseQuery } from "@tanstack/react-query";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/EditChecklistDefinition.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/EditChecklistDefinition.tsx
index 360324e0178cb6183bf15151a45a02e95c98bace..0c3c0c463a211ca3a63f3aa44bd60867391140be 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/EditChecklistDefinition.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/EditChecklistDefinition.tsx
@@ -8,7 +8,7 @@
 import {
   ApiChecklistDefinitionVersion,
   ApiObjectType,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { InternalLinkButton } from "@eshg/lib-portal/components/navigation/InternalLinkButton";
 import { InfoOutlined } from "@mui/icons-material";
@@ -109,6 +109,7 @@ export function EditChecklistDefinition({
       initialValues={formData}
       onSubmit={sendToBackend}
       enableReinitialize
+      validateOnChange={false}
     >
       {({ isSubmitting }) => (
         <FormPlus>
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElement.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElement.tsx
index 06ae3f6bb0a10dc05c0e803acc6971e8fd5b7f8b..2482b056647e33e8ebcf667ad23e32c01384c699 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElement.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElement.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLSectionContextElementsInner } from "@eshg/employee-portal-api/inspection";
+import { ApiCLSectionContextElementsInner } from "@eshg/inspection-api";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { DraggableProvidedDragHandleProps } from "@hello-pangea/dnd";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElementsList.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElementsList.tsx
index 2a84816acb565f96c3a27a906ac90675abb1269f..5c9173aaba3df20a0dcb4971590db7ba8e3d2c69 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElementsList.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElementsList.tsx
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { ApiCLSectionContextElementsInner } from "@eshg/inspection-api";
 import { useNonce } from "@eshg/lib-portal/components/NonceProvider";
 import {
   DragDropContext,
@@ -13,6 +14,7 @@ import {
 } from "@hello-pangea/dnd";
 import { Box, Stack } from "@mui/joy";
 import { FieldArray, useFormikContext } from "formik";
+import { memo } from "react";
 
 import { FormChecklistDefinitionVersion } from "@/lib/businessModules/inspection/api/mutations/checklistDefinition";
 import { ChecklistDefinitionElement } from "@/lib/businessModules/inspection/components/checklistDefinition/editor/elements/ChecklistDefinitionElement";
@@ -50,35 +52,15 @@ export function ChecklistDefinitionElementsList({
                 >
                   {values.context.sections[sectionIndex]?.elements.map(
                     (element, elementIndex) => (
-                      <Draggable
+                      <MemoizedDraggableChecklistDefinitionElement
                         key={element.id}
-                        draggableId={element.id}
-                        index={elementIndex}
-                      >
-                        {(provided, snapshot) => (
-                          <Box
-                            ref={provided.innerRef}
-                            {...provided.draggableProps}
-                            sx={getItemStyle(
-                              snapshot.isDragging,
-                              provided.draggableProps.style,
-                            )}
-                          >
-                            <ChecklistDefinitionElement
-                              dragHandleProps={provided.dragHandleProps}
-                              key={element.id}
-                              element={element}
-                              setElement={(element) =>
-                                replace(elementIndex, element)
-                              }
-                              deleteElement={() => remove(elementIndex)}
-                              addElement={(element) => push(element)}
-                              sectionIndex={sectionIndex}
-                              elementIndex={elementIndex}
-                            />
-                          </Box>
-                        )}
-                      </Draggable>
+                        element={element}
+                        elementIndex={elementIndex}
+                        sectionIndex={sectionIndex}
+                        push={push}
+                        remove={remove}
+                        replace={replace}
+                      />
                     ),
                   )}
                   {provided.placeholder}
@@ -92,6 +74,53 @@ export function ChecklistDefinitionElementsList({
   );
 }
 
+const MemoizedDraggableChecklistDefinitionElement = memo(
+  function DraggableChecklistDefinitionElement({
+    element,
+    elementIndex,
+    sectionIndex,
+    push,
+    remove,
+    replace,
+  }: {
+    element: ApiCLSectionContextElementsInner;
+    elementIndex: number;
+    sectionIndex: number;
+    push: (element: ApiCLSectionContextElementsInner) => void;
+    remove: (elementIndex: number) => void;
+    replace: (
+      elementIndex: number,
+      element: ApiCLSectionContextElementsInner,
+    ) => void;
+  }) {
+    return (
+      <Draggable draggableId={element.id} index={elementIndex}>
+        {(provided, snapshot) => (
+          <Box
+            ref={provided.innerRef}
+            {...provided.draggableProps}
+            sx={getItemStyle(
+              snapshot.isDragging,
+              provided.draggableProps.style,
+            )}
+          >
+            <ChecklistDefinitionElement
+              dragHandleProps={provided.dragHandleProps}
+              key={element.id}
+              element={element}
+              setElement={(element) => replace(elementIndex, element)}
+              deleteElement={() => remove(elementIndex)}
+              addElement={(element) => push(element)}
+              sectionIndex={sectionIndex}
+              elementIndex={elementIndex}
+            />
+          </Box>
+        )}
+      </Draggable>
+    );
+  },
+);
+
 function getItemStyle(
   isDragging: boolean,
   draggableStyle: DraggingStyle | NotDraggingStyle | undefined,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/NoteAndHelpTextInput.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/NoteAndHelpTextInput.tsx
index fe5e26824c419f32adaebb0fe3e7a8bb3bd5179d..68df56026c660130e07e856f3b38e0acad422585 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/NoteAndHelpTextInput.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/NoteAndHelpTextInput.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLSectionContextElementsInner } from "@eshg/employee-portal-api/inspection";
+import { ApiCLSectionContextElementsInner } from "@eshg/inspection-api";
 import { Box } from "@mui/joy";
 
 import { OptionalInputField } from "@/lib/businessModules/inspection/components/checklistDefinition/helpers/OptionalInputField";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionAnswerItem.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionAnswerItem.tsx
index 4661d02a9926de25ebb341ebea1407d27b1928c1..f37f977c616f0659f10304ce6885142cc2ec0ea4 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionAnswerItem.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionAnswerItem.tsx
@@ -3,12 +3,15 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLFieldOptionContext } from "@eshg/employee-portal-api/inspection";
+import {
+  ApiCLFieldOptionContext,
+  ApiCLSectionContextElementsInner,
+} from "@eshg/inspection-api";
 import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
 import { SubdirectoryArrowRight } from "@mui/icons-material";
 import { Stack } from "@mui/joy";
 import { useFormikContext } from "formik";
-import { useState } from "react";
+import { memo, useState } from "react";
 
 import { FormChecklistDefinitionVersion } from "@/lib/businessModules/inspection/api/mutations/checklistDefinition";
 import { FlexInputField } from "@/lib/businessModules/inspection/components/checklistDefinition/helpers/FlexInputField";
@@ -21,81 +24,101 @@ interface ChecklistDefinitionAnswerItemProps {
   elementIndex: number;
   itemIndex: number;
   item: ApiCLFieldOptionContext;
-  setItem: (item: ApiCLFieldOptionContext) => void;
   onDelete: () => void;
   hideDeleteButton?: boolean;
 }
 
-export function ChecklistDefinitionAnswerItem({
-  sectionIndex,
-  elementIndex,
-  itemIndex,
-  item,
-  onDelete,
-  hideDeleteButton = false,
-}: Readonly<ChecklistDefinitionAnswerItemProps>) {
+export function ChecklistDefinitionAnswerItem(
+  props: Readonly<ChecklistDefinitionAnswerItemProps>,
+) {
   const { values } = useFormikContext<FormChecklistDefinitionVersion>();
-  const [showTextModules, setShowTextModules] = useState(false);
-  function validateMultipleAnswers(value: OptionalFieldValue<string>) {
-    if (value === "") {
-      return undefined;
-    }
+  return (
+    <MemoizedChecklistDefinitionAnswerItem
+      {...props}
+      element={
+        values.context.sections[props.sectionIndex]?.elements[
+          props.elementIndex
+        ]
+      }
+    />
+  );
+}
+
+interface InnerChecklistDefinitionAnswerItemProps
+  extends ChecklistDefinitionAnswerItemProps {
+  element?: ApiCLSectionContextElementsInner;
+}
 
-    switch (
-      values.context.sections[sectionIndex]?.elements[elementIndex]?.type
-    ) {
-      case "MULTI_SELECT":
-      case "CLMultiSelectContext":
-      case "SINGLE_SELECT":
-      case "CLSingleSelectContext": {
-        const occurances = values.context.sections[sectionIndex]?.elements[
-          elementIndex
-        ].items!.filter((answer) => answer.text === value);
-        if (occurances.length > 1) {
-          return "Bitte unterschiedliche Werte eingeben.";
-        } else {
-          return undefined;
+const MemoizedChecklistDefinitionAnswerItem = memo(
+  function InnerChecklistDefinitionAnswerItem({
+    sectionIndex,
+    elementIndex,
+    itemIndex,
+    item,
+    onDelete,
+    hideDeleteButton = false,
+    element,
+  }: Readonly<InnerChecklistDefinitionAnswerItemProps>) {
+    const [showTextModules, setShowTextModules] = useState(false);
+    function validateMultipleAnswers(value: OptionalFieldValue<string>) {
+      if (value === "") {
+        return undefined;
+      }
+
+      switch (element?.type) {
+        case "MULTI_SELECT":
+        case "CLMultiSelectContext":
+        case "SINGLE_SELECT":
+        case "CLSingleSelectContext": {
+          const occurances = element.items!.filter(
+            (answer) => answer.text === value,
+          );
+          if (occurances.length > 1) {
+            return "Bitte unterschiedliche Werte eingeben.";
+          } else {
+            return undefined;
+          }
         }
       }
     }
-  }
 
-  return (
-    <Stack spacing={2}>
-      <InputWithDeleteButton
-        name={`context.sections.${sectionIndex}.elements.${elementIndex}.items.${itemIndex}.text`}
-        label={`Antwort ${itemIndex + 1}`}
-        placeholder="Antwort eingeben"
-        onDelete={onDelete}
-        validate={validateMultipleAnswers}
-        required="Bitte geben Sie eine Antwort ein."
-        hideDeleteButton={hideDeleteButton}
-        endDecorator={
-          <TextModuleToggle
-            checked={showTextModules}
-            onToggle={(show) => setShowTextModules(show)}
-            count={countTextModules(item)}
-          />
-        }
-      />
-      {showTextModules && (
-        <>
-          <FlexInputField
-            name={`context.sections.${sectionIndex}.elements.${elementIndex}.items.${itemIndex}.textModuleTrue`}
-            multiline
-            label={`Textbaustein für Antwort ${itemIndex + 1} (ausgewählt)`}
-            placeholder="Textbaustein eingeben"
-            startDecorator={<SubdirectoryArrowRight />}
-          />
-          <FlexInputField
-            name={`context.sections.${sectionIndex}.elements.${elementIndex}.items.${itemIndex}.textModuleFalse`}
-            multiline
-            label={`Textbaustein für Antwort ${itemIndex + 1} (nicht ausgewählt)`}
-            placeholder="Textbaustein eingeben"
-            startDecorator={<SubdirectoryArrowRight />}
-          />
-        </>
-      )}
-    </Stack>
-  );
-}
+    return (
+      <Stack spacing={2}>
+        <InputWithDeleteButton
+          name={`context.sections.${sectionIndex}.elements.${elementIndex}.items.${itemIndex}.text`}
+          label={`Antwort ${itemIndex + 1}`}
+          placeholder="Antwort eingeben"
+          onDelete={onDelete}
+          validate={validateMultipleAnswers}
+          required="Bitte geben Sie eine Antwort ein."
+          hideDeleteButton={hideDeleteButton}
+          endDecorator={
+            <TextModuleToggle
+              checked={showTextModules}
+              onToggle={(show) => setShowTextModules(show)}
+              count={countTextModules(item)}
+            />
+          }
+        />
+        {showTextModules && (
+          <>
+            <FlexInputField
+              name={`context.sections.${sectionIndex}.elements.${elementIndex}.items.${itemIndex}.textModuleTrue`}
+              multiline
+              label={`Textbaustein für Antwort ${itemIndex + 1} (ausgewählt)`}
+              placeholder="Textbaustein eingeben"
+              startDecorator={<SubdirectoryArrowRight />}
+            />
+            <FlexInputField
+              name={`context.sections.${sectionIndex}.elements.${elementIndex}.items.${itemIndex}.textModuleFalse`}
+              multiline
+              label={`Textbaustein für Antwort ${itemIndex + 1} (nicht ausgewählt)`}
+              placeholder="Textbaustein eingeben"
+              startDecorator={<SubdirectoryArrowRight />}
+            />
+          </>
+        )}
+      </Stack>
+    );
+  },
+);
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementCheckboxInner.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementCheckboxInner.tsx
index bb056b08531bb8486ed328c94aae9d530a52aaf2..dba410c0284bd07719c09740537cdca9635be0d6 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementCheckboxInner.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementCheckboxInner.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLCheckboxContext } from "@eshg/employee-portal-api/inspection";
+import { ApiCLCheckboxContext } from "@eshg/inspection-api";
 import { SubdirectoryArrowRight } from "@mui/icons-material";
 import { Radio, Stack } from "@mui/joy";
 import { useState } from "react";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementInner.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementInner.tsx
index 88e433165f541e24ac61e0a93cf6206373c33e78..2f92d0d6cf3f1478d45ea0f8e145dc35d5607d54 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementInner.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementInner.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLSectionContextElementsInner } from "@eshg/employee-portal-api/inspection";
+import { ApiCLSectionContextElementsInner } from "@eshg/inspection-api";
 import type { FC } from "react";
 
 import { ChecklistDefinitionElementCheckboxInner } from "@/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementCheckboxInner";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementMultiInner.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementMultiInner.tsx
index 1c179d1b81953687a61de287f4bf6d774e03b941..f07ec65d2ccb37096bae886e5536f896a01418da 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementMultiInner.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/elements/inner/ChecklistDefinitionElementMultiInner.tsx
@@ -7,7 +7,7 @@ import {
   ApiCLFieldOptionContext,
   type ApiCLMultiSelectContext,
   ApiCLSectionContextElementsInner,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { Add } from "@mui/icons-material";
 import { Button, Stack } from "@mui/joy";
 import { v4 as uuidv4 } from "uuid";
@@ -53,13 +53,6 @@ export function ChecklistDefinitionElementMultiInner({
     });
   }
 
-  function setItem(index: number, item: ApiCLFieldOptionContext) {
-    items[index] = item;
-    updateElement({
-      items: [...items],
-    });
-  }
-
   return (
     <Stack spacing={2}>
       {items.map((item, index) => {
@@ -73,7 +66,6 @@ export function ChecklistDefinitionElementMultiInner({
             elementIndex={elementIndex}
             itemIndex={index}
             item={item}
-            setItem={(item) => setItem(index, item)}
             onDelete={() => deleteItem(index)}
             hideDeleteButton={hideDeleteButton}
           />
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/header/ChecklistDefinitionHeaderCard.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/header/ChecklistDefinitionHeaderCard.tsx
index 6e6a5f43a0b289853e425e91390e7a66ff73b128..e3076326f865616ee428f7c0d41b310b8ca0cb6a 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/header/ChecklistDefinitionHeaderCard.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/header/ChecklistDefinitionHeaderCard.tsx
@@ -4,7 +4,7 @@
  */
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiObjectType } from "@eshg/employee-portal-api/inspection";
+import { ApiObjectType } from "@eshg/inspection-api";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { Stack } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/header/ChecklistDefinitionHeaderRow.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/header/ChecklistDefinitionHeaderRow.tsx
index 346bcffdfd9656171b1e74444c4b584ffe927db7..1281d82afe3e95cdbc07065ee111542c1d9e2866 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/header/ChecklistDefinitionHeaderRow.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/header/ChecklistDefinitionHeaderRow.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUser } from "@eshg/employee-portal-api/inspection";
+import { ApiUser } from "@eshg/inspection-api";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { Stack, Typography } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/sections/ChecklistDefinitionSection.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/sections/ChecklistDefinitionSection.tsx
index 4815c0a2c2c3559e7ce2189e9a3aa0505ba93a07..b182ec94976786d2e3177a35085ad5c8d1af833a 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/sections/ChecklistDefinitionSection.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/editor/sections/ChecklistDefinitionSection.tsx
@@ -8,7 +8,7 @@
 import {
   ApiCLSectionContext,
   ApiCLSectionContextElementsInner,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { DraggableProvidedDragHandleProps } from "@hello-pangea/dnd";
 import { Add } from "@mui/icons-material";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/helpers/OptionalInputField.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/helpers/OptionalInputField.tsx
index 725eb65157a30866d0fe00e044611e801683930a..c247f75d0348e3f7373b725820ef23ace8225682 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/helpers/OptionalInputField.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/helpers/OptionalInputField.tsx
@@ -3,10 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useBaseField } from "@eshg/lib-portal/components/formFields/BaseField";
 import { Add } from "@mui/icons-material";
 import { Button } from "@mui/joy";
-import { useFormikContext } from "formik";
-import { useEffect, useState } from "react";
+import { FormikErrors } from "formik";
+import { memo, useState } from "react";
 
 import { FlexInputFieldProps } from "@/lib/businessModules/inspection/components/checklistDefinition/helpers/FlexInputField";
 import { InputWithDeleteButton } from "@/lib/businessModules/inspection/components/checklistDefinition/helpers/InputWithDeleteButton";
@@ -15,23 +16,37 @@ export interface OptionalInputFieldProps extends FlexInputFieldProps {
   addButtonLabel: string;
 }
 
-export function OptionalInputField({
+export function OptionalInputField(props: Readonly<OptionalInputFieldProps>) {
+  const { meta, helpers } = useBaseField(props);
+
+  return (
+    <MemoizedOptionalInputField
+      {...props}
+      setValue={helpers.setValue}
+      hasInitialValue={!!meta.initialValue}
+    />
+  );
+}
+
+interface InnerOptionalInputFieldProps extends OptionalInputFieldProps {
+  setValue: (
+    value: string,
+    shouldValidate?: boolean,
+  ) => Promise<void | FormikErrors<string>>;
+  hasInitialValue: boolean;
+}
+
+const MemoizedOptionalInputField = memo(function InnerOptionalInputField({
   addButtonLabel,
+  hasInitialValue,
+  setValue,
   ...props
-}: Readonly<OptionalInputFieldProps>) {
-  const { getFieldProps, setFieldValue } = useFormikContext();
-  const [showInput, setShowInput] = useState(false);
-
-  // show input if it has an initial value
-  useEffect(() => {
-    const { value } = getFieldProps<string>(props.name);
-    setShowInput(!!value);
-    // eslint-disable-next-line react-hooks/exhaustive-deps -- only run on mount
-  }, [props.name]);
+}: Readonly<InnerOptionalInputFieldProps>) {
+  const [showInput, setShowInput] = useState(hasInitialValue);
 
   function handleDelete() {
     setShowInput(false);
-    void setFieldValue(props.name, "");
+    void setValue("");
   }
 
   if (showInput) {
@@ -49,4 +64,4 @@ export function OptionalInputField({
       {addButtonLabel}
     </Button>
   );
-}
+});
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/helpers/helpers.ts b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/helpers/helpers.ts
index bef9e97aabf1199a2bd5c63206a88fe421b33802..fb7169e54dd9617803fcb41d29ece253fd2c1b76 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/helpers/helpers.ts
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/helpers/helpers.ts
@@ -14,7 +14,7 @@ import {
   ApiCLSingleSelectContext,
   type ApiCLTextElementContext,
   ApiChecklistDefinitionVersion,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { ConfirmationDialogProps } from "@eshg/lib-portal/components/confirmationDialog/BaseConfirmationDialog";
 import { v4 as uuidv4 } from "uuid";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/overview/ChecklistDefinitionOverviewTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/overview/ChecklistDefinitionOverviewTable.tsx
index ae73692a5ee92ddd5a3b7a741db0f9f6481da25d..011ed4054924417230ae7a857583454860bac381 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/overview/ChecklistDefinitionOverviewTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/overview/ChecklistDefinitionOverviewTable.tsx
@@ -6,7 +6,7 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiChecklistDefinition } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklistDefinition } from "@eshg/inspection-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { Row } from "@tanstack/react-table";
 import { useRouter } from "next/navigation";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/overview/columns.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/overview/columns.tsx
index 6e76b3c0feaabeb25d4400abeef460dacfb3c2ec..26bb38226bd7014aeb46e19687d13c9ae8ad27fc 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/overview/columns.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/overview/columns.tsx
@@ -6,7 +6,7 @@
 import {
   ApiChecklistDefinition,
   ApiChecklistDefinitionVersion,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { ConfirmationDialogProps } from "@eshg/lib-portal/components/confirmationDialog/BaseConfirmationDialog";
 import { Snackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/CLDInfoCard.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/CLDInfoCard.tsx
index 7022e431ce948019ab8bd744fd3f223603b6c18d..c7aaa99c886e504b49c7fb36f56d5eaf2e49cfaa 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/CLDInfoCard.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/CLDInfoCard.tsx
@@ -4,7 +4,7 @@
  */
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiChecklistDefinitionVersion } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklistDefinitionVersion } from "@eshg/inspection-api";
 import { InternalLinkButton } from "@eshg/lib-portal/components/navigation/InternalLinkButton";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import { CopyAllOutlined, InfoOutlined } from "@mui/icons-material";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDContent.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDContent.tsx
index d6855f2dbf75bf7dae584a1b8a02c8e8cc7c450a..c7019b65375b5b0311949c3f6c446efb49fd79e0 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDContent.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDContent.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiChecklistDefinitionVersion } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklistDefinitionVersion } from "@eshg/inspection-api";
 import { Sheet, Stack } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDPage.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDPage.tsx
index 1182b75f39dee7703aba44087d8cd76a45d8af9a..be420a422031766eddba87ddf4b099492d062de8 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDPage.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDPage.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiChecklistDefinitionVersion } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklistDefinitionVersion } from "@eshg/inspection-api";
 import { InfoOutlined } from "@mui/icons-material";
 import { Alert, Box } from "@mui/joy";
 import { ReactNode } from "react";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDSection.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDSection.tsx
index 717be100c26809b69d8d7639520088a1ce732c22..b2f8c293d248646d478b80a6a9bbb701358802ae 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDSection.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/ReadOnlyCLDSection.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLSectionContext } from "@eshg/employee-portal-api/inspection";
+import { ApiCLSectionContext } from "@eshg/inspection-api";
 import { Stack, Typography } from "@mui/joy";
 
 import { ReadOnlyCLDElement } from "@/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/ReadOnlyCLDElement";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/ReadOnlyCLDElement.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/ReadOnlyCLDElement.tsx
index a9afcd8a42138e13f9e754d1223e8bf499dc1c3c..4a6ac2252266ac972bc57ae89b2b999c70dbd066 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/ReadOnlyCLDElement.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/ReadOnlyCLDElement.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLSectionContextElementsInner } from "@eshg/employee-portal-api/inspection";
+import { ApiCLSectionContextElementsInner } from "@eshg/inspection-api";
 import { Divider } from "@mui/joy";
 
 import { ReadOnlyCLDElementCheckbox } from "@/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementCheckbox";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementCheckbox.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementCheckbox.tsx
index 677e56affe17ab559fc1e83a1d2a2b958008cf5e..92d278cde9d530d17dc30d0b17492e016f021e97 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementCheckbox.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementCheckbox.tsx
@@ -6,7 +6,7 @@
 import {
   ApiCLCheckboxContext,
   ApiCLMultiSelectContext,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { ReadOnlyCLDElementProps } from "@/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/ReadOnlyCLDElement";
 import { ReadOnlyCLDElementMultiSelect } from "@/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementMultiSelect";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementFile.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementFile.tsx
index 4a9af66440d2c853a404baaa42e2c8be2ab062f3..ef5b149b656c7910ee16299a4755f03178eac37d 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementFile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementFile.tsx
@@ -3,10 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiCLAudioContext,
-  ApiCLImageContext,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiCLAudioContext, ApiCLImageContext } from "@eshg/inspection-api";
 import { UploadFileOutlined } from "@mui/icons-material";
 import { Button } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementMultiSelect.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementMultiSelect.tsx
index 704ef1ed76355b3550a676f521268a1fe26410e7..62b91678f8f5be62287d377aa917e1c1dabd2226 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementMultiSelect.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementMultiSelect.tsx
@@ -6,7 +6,7 @@
 import {
   ApiCLFieldOptionContext,
   ApiCLMultiSelectContext,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { Box, List, ListItem, Typography, styled } from "@mui/joy";
 
 import { ReadOnlyCLDElementProps } from "@/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/ReadOnlyCLDElement";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementText.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementText.tsx
index 46c13bf6eb42e5d8159029c116bdbd4301b99e2a..c60872839f0190d23e7eb350e72dfd51f0b925d7 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementText.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/inner/ReadOnlyCLDElementText.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLTextElementContext } from "@eshg/employee-portal-api/inspection";
+import { ApiCLTextElementContext } from "@eshg/inspection-api";
 import { Card } from "@mui/joy";
 
 import { ReadOnlyCLDElementProps } from "@/lib/businessModules/inspection/components/checklistDefinition/readOnly/elements/ReadOnlyCLDElement";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/UploadChecklistToRepoSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/UploadChecklistToRepoSidebar.tsx
index c4365d7069e8a7a4c12e4400482a39944fd13445..8d112b3be79207863f0181312f2a24df997c5373 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/UploadChecklistToRepoSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/UploadChecklistToRepoSidebar.tsx
@@ -6,7 +6,7 @@
 import {
   ApiChecklistDefinition,
   ApiChecklistDefinitionCentralRepoRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { formatPersonName } from "@eshg/lib-portal/formatters/person";
 import { Stack } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/history/ChecklistVersionsSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/history/ChecklistVersionsSidebar.tsx
index 63cff01cd3c5782a90c03b8a4bad997fa1fb99d9..ce4f052b6db5ec5d6dc7bc7a27b06631439a0bba 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/history/ChecklistVersionsSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/history/ChecklistVersionsSidebar.tsx
@@ -9,7 +9,7 @@ import { ApiUserRole } from "@eshg/base-api";
 import {
   ApiChecklistDefinition,
   ApiChecklistDefinitionVersion,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import { Stack, Typography } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/history/VersionSheet.tsx b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/history/VersionSheet.tsx
index 825276f2ca0cd85b94f23450b99292fe023fd7d1..d03f82ea2bcdebd90e555b5cf52e2d7679902f01 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/history/VersionSheet.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/checklistDefinition/sidebars/history/VersionSheet.tsx
@@ -7,7 +7,7 @@ import { ApiUserRole } from "@eshg/base-api";
 import {
   ApiChecklistDefinition,
   ApiChecklistDefinitionVersion,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import { ConfirmationDialogProps } from "@eshg/lib-portal/components/confirmationDialog/BaseConfirmationDialog";
 import {
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/FacilityDuplicateTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/FacilityDuplicateTile.tsx
index 227cb6726dd1af3dda2ec1f4172b1ab3ee4e80ad..d8ad5e2a8d996c3424d9efeb2099568d1264484f 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/FacilityDuplicateTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/FacilityDuplicateTile.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiFacilityForDuplicateReview } from "@eshg/employee-portal-api/inspection";
+import { ApiFacilityForDuplicateReview } from "@eshg/inspection-api";
 import { Radio, Sheet, Stack, Typography } from "@mui/joy";
 
 import { DuplicateTileLine } from "@/lib/businessModules/inspection/components/facility/pending/DuplicateTileLine";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/InspectionDuplicateTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/InspectionDuplicateTile.tsx
index f6476a1bd1e9c1635c8bf37f56a78a85894e4339..a19cc6899e929d72dd06b47c55238e20d6103a8c 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/InspectionDuplicateTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/InspectionDuplicateTile.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionForDuplicateReview } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionForDuplicateReview } from "@eshg/inspection-api";
 import { formatDate, formatTime } from "@eshg/lib-portal/formatters/dateTime";
 import { Sheet, Stack, Typography } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/NewFacilityButton.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/NewFacilityButton.tsx
index ec2eac3dda7330f2fd91eb849c93251f3c7132bf..977ffdbfa66563a95aef965e1dcb2e55c0c43446 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/NewFacilityButton.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/NewFacilityButton.tsx
@@ -9,7 +9,7 @@ import { ApiGetReferenceFacilityResponse } from "@eshg/base-api";
 import {
   type ApiInspAddFacilityResponse,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { Add } from "@mui/icons-material";
 import { Button } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/PendingFacilitiesIncidentsSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/PendingFacilitiesIncidentsSidebar.tsx
index e460c227a662d9322db0a6a0af5303d9bcf3d713..85b9b1d24a536e87c2bd0a8470253b9c021a448c 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/PendingFacilitiesIncidentsSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/PendingFacilitiesIncidentsSidebar.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionIncident } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionIncident } from "@eshg/inspection-api";
 import { Sheet, Stack, Typography } from "@mui/joy";
 
 import { useGetIncidents } from "@/lib/businessModules/inspection/api/queries/incidents";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/PendingFacilitiesTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/PendingFacilitiesTable.tsx
index e59f75a28e0995a198defe48ea5758dd2a58e9c8..caeec01150994a3ad35df70a7c1353a1fb06f51a 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/PendingFacilitiesTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/PendingFacilitiesTable.tsx
@@ -5,9 +5,9 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
-import { ApiObjectType } from "@eshg/employee-portal-api/inspection";
+import { ApiObjectType } from "@eshg/inspection-api";
 import { optionsFromRecord } from "@eshg/lib-portal/components/formFields/SelectOptions";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { addDays, formatISO } from "date-fns";
 import { useMemo, useState } from "react";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/columns.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/columns.tsx
index 3a558839b155669f0567b8c57137abd3967de86d..7e3bfcd5207474378a7f11e140c9dc447d8369a9 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/pending/columns.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/pending/columns.tsx
@@ -6,7 +6,7 @@
 import {
   type ApiInspPendingFacility,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { ButtonLink } from "@eshg/lib-portal/components/buttons/ButtonLink";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import { IconButton, Stack } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/search/FacilityWebSearchImportSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/search/FacilityWebSearchImportSidebar.tsx
index 0a1213b5be8fb2a54e356bbc41e1fa3fb6cef500..3c9704c77b59e799925c972a0e70a1df2c8b8223 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/search/FacilityWebSearchImportSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/search/FacilityWebSearchImportSidebar.tsx
@@ -8,7 +8,7 @@ import {
   ApiInspAddFacilityResponse,
   ApiProcedureStatus,
   ApiWebSearchEntry,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { Card, Chip, Typography } from "@mui/joy";
 import { useRouter } from "next/navigation";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/search/FacilityWebSearchTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/search/FacilityWebSearchTable.tsx
index 7f7cfba6e8ab2f25185c8d9ac1689d7ea7eeb19b..e56113b4fdc0028bd8b48407e56cf92ccafcc0c1 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/search/FacilityWebSearchTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/search/FacilityWebSearchTable.tsx
@@ -8,7 +8,7 @@
 import {
   type ApiWebSearchOverviewEntry,
   type ApiWebSearchStatus,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import { DeleteOutlined, Edit, PlayArrow } from "@mui/icons-material";
 import { ColorPaletteProp } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/search/results/FacilityWebSearchResultsTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/search/results/FacilityWebSearchResultsTable.tsx
index 99ce013af6515298fba36e60da1776645b46d442..48286530fdfb8794b5f2ec1c44dfe25fe879fa9b 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/search/results/FacilityWebSearchResultsTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/search/results/FacilityWebSearchResultsTable.tsx
@@ -10,7 +10,7 @@ import {
   ApiWebSearchEntriesResponse,
   ApiWebSearchEntry,
   ApiWebSearchQuery,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { optionsFromRecord } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import AddIcon from "@mui/icons-material/Add";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/facility/search/results/columns.tsx b/employee-portal/src/lib/businessModules/inspection/components/facility/search/results/columns.tsx
index 1fdd607a9464921ad598bf7225f8a4abec927cdc..ec90f2fb4cf6a337f6ae988772da84e727db26fd 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/facility/search/results/columns.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/facility/search/results/columns.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiWebSearchEntry } from "@eshg/employee-portal-api/inspection";
+import { ApiWebSearchEntry } from "@eshg/inspection-api";
 import { Add } from "@mui/icons-material";
 import { Checkbox, Chip, CircularProgress, Stack } from "@mui/joy";
 import { Cell, ColumnHelper, createColumnHelper } from "@tanstack/react-table";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inbox/InspectionInboxProcedureCreateSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inbox/InspectionInboxProcedureCreateSidebar.tsx
index f461f74cc5effaeaa3191b42c600dc11b4ef5c58..9834c75cadb8d6ec3af2fa65b280e307c88f54fb 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inbox/InspectionInboxProcedureCreateSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inbox/InspectionInboxProcedureCreateSidebar.tsx
@@ -8,7 +8,7 @@ import {
   ApiGetReferenceFacilityResponse,
   ApiInboxProcedure,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { assertNever } from "@eshg/lib-portal/helpers/assertions";
 import { useRouter } from "next/navigation";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/EditFacilitySidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/EditFacilitySidebar.tsx
index d98c5c3c04656f2d511e5c9a769b5a0fcede207b..50e49bb97068e652674b5f25d8619787727e6fdb 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/EditFacilitySidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/EditFacilitySidebar.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGetFacilityFileStateResponse } from "@eshg/employee-portal-api/inspection";
+import { ApiGetFacilityFileStateResponse } from "@eshg/inspection-api";
 
 import {
   DefaultFacilityFormValues,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionLockInfo.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionLockInfo.tsx
index fc13c1db6d9f0ca3515b1e01da5353d86ff6a8e9..ae47e4aa6e48b63c91522f8fd4dcf9745ad851ed 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionLockInfo.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionLockInfo.tsx
@@ -4,7 +4,7 @@
  */
 
 import { ApiUserRole } from "@eshg/base-api";
-import { type ApiInspection } from "@eshg/employee-portal-api/inspection";
+import { type ApiInspection } from "@eshg/inspection-api";
 import { Clear } from "@mui/icons-material";
 import { Box, IconButton, Typography } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionPhaseSelect.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionPhaseSelect.tsx
index 9df78c100912f606a3897771c21a6c822bc99d08..f00a63edb7227a7ddef951a82750220bfe809daa 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionPhaseSelect.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionPhaseSelect.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspection } from "@eshg/employee-portal-api/inspection";
+import { ApiInspection } from "@eshg/inspection-api";
 import { Typography } from "@mui/joy";
 
 import { translateInspectionPhase } from "@/lib/businessModules/inspection/shared/enums";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionTabHeader.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionTabHeader.tsx
index be274d01259fe047d95141c7ffac8ce4d0745f41..5a8403eb54fa586f44504dde038b3531aa274f15 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionTabHeader.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/InspectionTabHeader.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { type ApiInspection } from "@eshg/employee-portal-api/inspection";
+import { type ApiInspection } from "@eshg/inspection-api";
 
 import { InspectionLockInfo } from "@/lib/businessModules/inspection/components/inspection/InspectionLockInfo";
 import { InspectionPhaseSelect } from "@/lib/businessModules/inspection/components/inspection/InspectionPhaseSelect";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/OfflineSwitch.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/OfflineSwitch.tsx
index 819f268c2bd30ac635f1a6a790431567716fc7dc..634f53c787f7075942fa9d7135a99e458c7c2b02 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/OfflineSwitch.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/OfflineSwitch.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionPhase } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionPhase } from "@eshg/inspection-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { getErrorDescription } from "@eshg/lib-portal/errorHandling/errorMappers";
 import { resolveError } from "@eshg/lib-portal/errorHandling/errorResolvers";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/InspectionTabBasedata.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/InspectionTabBasedata.tsx
index 3ec36bda76b06dad78395dfb867c066a2dea9e62..132d5bbe276c3a37932f44ea1ed17ddafe32c7b6 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/InspectionTabBasedata.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/InspectionTabBasedata.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionPhase } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionPhase } from "@eshg/inspection-api";
 import { Grid } from "@mui/joy";
 import { useSuspenseQueries } from "@tanstack/react-query";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/InspectionTypeCard.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/InspectionTypeCard.tsx
index ad2482a29a654d4fd3ea4ac5e23b0b2478eca986..0bf5ba8f596eacb326215cad57d6b1ca78cc7696 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/InspectionTypeCard.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/InspectionTypeCard.tsx
@@ -6,7 +6,7 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiInspection } from "@eshg/employee-portal-api/inspection";
+import { ApiInspection } from "@eshg/inspection-api";
 import { formatPersonName } from "@eshg/lib-portal/formatters/person";
 import { SetFieldValueHelper } from "@eshg/lib-portal/types/form";
 import { Divider, Grid, Stack } from "@mui/joy";
@@ -23,11 +23,11 @@ import {
 import { InspectionAssigneeSelection } from "@/lib/businessModules/inspection/components/inspection/assignee/InspectionAssigneeSelection";
 import { translateInspectionType } from "@/lib/businessModules/inspection/shared/enums";
 import { OverlayBoundary } from "@/lib/shared/components/boundaries/OverlayBoundary";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import {
   DetailsSection,
   SimplifiedModalProps,
 } from "@/lib/shared/components/detailsSection/DetailsSection";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
 import {
   SidebarForm,
@@ -66,18 +66,15 @@ export function InspectionTypeCard({
         }
       >
         <Grid container direction="column" gap={2}>
-          <DetailsCell
-            name="type"
+          <DetailsItem
             label="Art"
             value={translateInspectionType(inspection.type)}
           />
-          <DetailsCell
-            name="challenging"
+          <DetailsItem
             label="Besonderheiten"
             value={inspection.challenging ? "Schwierige Gegebenheit" : "keine"}
           />
-          <DetailsCell
-            name="assignee"
+          <DetailsItem
             label="Zugewiesene:r Bearbeiter:in"
             value={formatPersonName({
               firstName: inspection.assignee?.firstName,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/contactperson/ContactPersonTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/contactperson/ContactPersonTile.tsx
index ff3ac95ee20543fdab205011c593ce474227980b..6783df60376a88868b582ef4e6bccd6741d04e67 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/contactperson/ContactPersonTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/basedata/contactperson/ContactPersonTile.tsx
@@ -13,7 +13,7 @@ import { isNonNullish } from "remeda";
 import { EmailSection } from "@/lib/businessModules/inspection/components/inspection/common/EmailSection";
 import { PhoneNumberSection } from "@/lib/businessModules/inspection/components/inspection/common/PhoneNumberSection";
 import { TileDivider } from "@/lib/businessModules/inspection/components/inspection/common/TileDivider";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 import { InfoTileAddButton } from "@/lib/shared/components/infoTile/InfoTileAddButton";
 
@@ -45,41 +45,24 @@ export function ContactPersonTile({
             <Grid container direction="row" sx={{ gap: 3 }}>
               {isNonNullish(contactPerson?.salutation) &&
                 contactPerson.salutation !== "NOT_SPECIFIED" && (
-                  <DetailsCell
-                    name="salutation"
+                  <DetailsItem
                     label="Anrede"
                     value={SALUTATION_VALUES[contactPerson.salutation]}
                   />
                 )}
               {isNonNullish(contactPerson?.title) &&
                 contactPerson.title !== "Keine Angabe" && (
-                  <DetailsCell
-                    name="title"
-                    label="Titel"
-                    value={contactPerson.title}
-                  />
+                  <DetailsItem label="Titel" value={contactPerson.title} />
                 )}
             </Grid>
             {isNonNullish(contactPerson?.role) && (
-              <DetailsCell
-                name="role"
-                label="Role"
-                value={contactPerson.role}
-              />
+              <DetailsItem label="Role" value={contactPerson.role} />
             )}
             {isNonNullish(contactPerson?.firstName) && (
-              <DetailsCell
-                name="name"
-                label="Vorname"
-                value={contactPerson.firstName}
-              />
+              <DetailsItem label="Vorname" value={contactPerson.firstName} />
             )}
             {isNonNullish(contactPerson?.lastName) && (
-              <DetailsCell
-                name="surname"
-                label="Nachname"
-                value={contactPerson.lastName}
-              />
+              <DetailsItem label="Nachname" value={contactPerson.lastName} />
             )}
           </Grid>
         </Grid>
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/common/appointment/AppointmentSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/common/appointment/AppointmentSidebar.tsx
index 92e7ad81c46c23950727c118af0004ab0b80d6d0..8f315e81e9be1fe47dbc777e1ad13ecd945195c5 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/common/appointment/AppointmentSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/common/appointment/AppointmentSidebar.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspectionAppointment } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionAppointment } from "@eshg/inspection-api";
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { toDateString } from "@eshg/lib-portal/helpers/dateTime";
 import { Grid } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/common/appointment/appointmentUtils.ts b/employee-portal/src/lib/businessModules/inspection/components/inspection/common/appointment/appointmentUtils.ts
index 5277068728b29fa8aa0afb97ab9d0f184f29895c..4ea01767669cf068d8222f44fb37d602fb07ba0f 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/common/appointment/appointmentUtils.ts
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/common/appointment/appointmentUtils.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspectionAppointment } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionAppointment } from "@eshg/inspection-api";
 import { formatDate, formatTime } from "@eshg/lib-portal/formatters/dateTime";
 import { isNonNullish } from "remeda";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/common/facility/FacilityTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/common/facility/FacilityTile.tsx
index 7d5910bd2e13a888e43d7507c9d446d6e32a6c47..01869b232ca7836c98c9c8ad2bdd869e0d63660b 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/common/facility/FacilityTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/common/facility/FacilityTile.tsx
@@ -3,10 +3,10 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspFacility } from "@eshg/employee-portal-api/inspection";
+import { ApiInspFacility } from "@eshg/inspection-api";
 
 import { CentralFileFacilityDetails } from "@/lib/shared/components/centralFile/display/CentralFileFacilityDetails";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 
 interface FacilityTileProps {
@@ -27,11 +27,7 @@ export function FacilityTile({
       onEdit={!readonly ? onEdit : undefined}
     >
       <CentralFileFacilityDetails facility={facility.baseFacility}>
-        <DetailsCell
-          name="Objekttyp"
-          label="Objekttyp"
-          value={facility.objectType?.name}
-        />
+        <DetailsItem label="Objekttyp" value={facility.objectType?.name} />
       </CentralFileFacilityDetails>
     </InfoTile>
   );
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/ExecutionSidePanel.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/ExecutionSidePanel.tsx
index 9df913809c69c1be9caeb5b9bbef32246d28fd4c..e334509d11303bd484fa13db7041c3788a9e46e4 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/ExecutionSidePanel.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/ExecutionSidePanel.tsx
@@ -9,11 +9,11 @@ import {
   ApiChecklist,
   ApiInspection,
   ApiInspectionPhase,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { scrollToFirstFormError } from "@eshg/lib-portal/components/form/FormPlus";
 import AddIcon from "@mui/icons-material/Add";
 import EditIcon from "@mui/icons-material/EditOutlined";
-import { Button, Divider, IconButton, Stack } from "@mui/joy";
+import { Button, Divider, Grid, IconButton, Stack, Typography } from "@mui/joy";
 import { useState } from "react";
 
 import { AppointmentSidebar } from "@/lib/businessModules/inspection/components/inspection/common/appointment/AppointmentSidebar";
@@ -26,7 +26,7 @@ import {
   SidePanelNavigationTab,
 } from "@/lib/businessModules/inspection/components/inspection/execution/SidePanelNavigation";
 import { useChecklistValidateContext } from "@/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistValidateContext";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { SidePanel } from "@/lib/shared/components/sidePanel/SidePanel";
 import { SidePanelTitle } from "@/lib/shared/components/sidePanel/SidePanelTitle";
 import { UserLink } from "@/lib/shared/components/users/UserLink";
@@ -159,38 +159,55 @@ export function ExecutionSidePanel({
 
       <Divider sx={{ marginY: 1 }} />
 
-      <DetailsCell
-        name="user"
+      <DetailsItem
         label={"Durchführung durch"}
         value={
-          inspection?.executedAppointment?.assignedTo && (
+          (inspection?.executedAppointment?.assignedTo && (
             <UserLink user={inspection?.executedAppointment?.assignedTo} />
+          )) ?? (
+            <Typography
+              data-testid={`user.value`}
+              component="i"
+              color="neutral"
+              level="title-md"
+            >
+              Keine Angaben
+            </Typography>
           )
         }
-        showIfEmpty
       />
 
-      <DetailsCell
-        name="date"
-        label="Geplanter Termin"
-        value={plannedDateAndTime}
-      />
-      <DetailsCell
-        name="date"
+      <DetailsItem label="Geplanter Termin" value={plannedDateAndTime} />
+      <DetailsItem
         label="Tatsächlicher Begehungstermin"
-        value={executedDateAndTime}
-      >
-        {!readOnly && (
-          <IconButton
-            aria-label={`Termin ändern`}
-            color="primary"
-            onClick={() => setApprovalSidebarOpen(true)}
-            sx={{ p: 0, ml: 1, minHeight: 0 }}
-          >
-            <EditIcon />
-          </IconButton>
-        )}
-      </DetailsCell>
+        value={
+          <Grid container alignItems="center">
+            <Typography
+              role={"paragraph"}
+              component={"p"}
+              data-testid={`date.value`}
+              level="title-md"
+              sx={{
+                width: undefined,
+                textWrap: "pretty",
+                hyphens: "auto",
+              }}
+            >
+              {executedDateAndTime}
+            </Typography>
+            {!readOnly && (
+              <IconButton
+                aria-label={`Termin ändern`}
+                color="primary"
+                onClick={() => setApprovalSidebarOpen(true)}
+                sx={{ p: 0, ml: 1, minHeight: 0 }}
+              >
+                <EditIcon />
+              </IconButton>
+            )}
+          </Grid>
+        }
+      ></DetailsItem>
 
       {!readOnly && (
         <>
@@ -202,8 +219,7 @@ export function ExecutionSidePanel({
       {inspection.phase === ApiInspectionPhase.Executed && (
         <>
           <Divider sx={{ mb: 1, mt: 1 }} />
-          <DetailsCell
-            name="phase-executed"
+          <DetailsItem
             label="Begehung abgeschlossen"
             value="Die Begehung ist abgeschlossen. Sie sind noch offline. Die eingegebenen Daten wurden gespeichert und werden übertragen, sobald Sie wieder online sind."
           />
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/FinalizeInspectionModalContent.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/FinalizeInspectionModalContent.tsx
index 3b376906403b7361f6ac6ddfe59053c7eb2c2446..b39e07fde8bad7e53fa83a8b88fca13ca54633bd 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/FinalizeInspectionModalContent.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/FinalizeInspectionModalContent.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionPhase } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionPhase } from "@eshg/inspection-api";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import {
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/InspectionTabExecution.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/InspectionTabExecution.tsx
index 16955318d977a3d0b1727e4bf8f1c92e09aec36b..3f05d65e6a06ff0fead92109d20aff1c04c97214 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/InspectionTabExecution.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/InspectionTabExecution.tsx
@@ -10,7 +10,7 @@ import {
   ApiInspection,
   ApiInspectionPhase,
   ApiUpdateInspectionRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import {
   AutorenewOutlined,
   Checklist as ChecklistIcon,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/Checklist.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/Checklist.tsx
index 1bf4a1b6924abfa4a6f0244dc19c307a57879d28..9395c9ab9010c993086b7100d29bc73aee31423a 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/Checklist.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/Checklist.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiChecklist } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklist } from "@eshg/inspection-api";
 import { Box, Stack, Typography } from "@mui/joy";
 import { Fragment } from "react";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistSection.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistSection.tsx
index 6bfe8c95ae7dbd282c6457b6f2587f20912b741c..68f49daa9d448bb40dbd46f61d45380113114a31 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistSection.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistSection.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCLSection } from "@eshg/employee-portal-api/inspection";
+import { ApiCLSection } from "@eshg/inspection-api";
 import { Divider, Stack, Typography } from "@mui/joy";
 import { Fragment } from "react";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistValidateContext.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistValidateContext.tsx
index 819423bf15c1db12860d6e833152fd494dc148a3..897b2492f7971b5626a49bb5966312645e933a9e 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistValidateContext.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/ChecklistValidateContext.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiChecklist } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklist } from "@eshg/inspection-api";
 import { FormikErrors } from "formik";
 import {
   ReactNode,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/ChecklistFileElement.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/ChecklistFileElement.tsx
index 839376ab7561a30f81e794465f7ad135b524df56..b783f63fc0c4dba609e8992dc60d16182873e305 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/ChecklistFileElement.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/ChecklistFileElement.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiFileType } from "@eshg/employee-portal-api/inspection";
+import { ApiFileType } from "@eshg/inspection-api";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { FileType } from "@eshg/lib-portal/components/formFields/file/FileType";
 import { FileLike } from "@eshg/lib-portal/components/formFields/file/validators";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/ChecklistSectionElement.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/ChecklistSectionElement.tsx
index 67e9c6bf37b583651229da6eefea7da7bc5581f4..1e53a4255d576f4f194b9cabd44592e9e36e4374 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/ChecklistSectionElement.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/ChecklistSectionElement.tsx
@@ -8,7 +8,7 @@
 import {
   ApiUpdateChecklistElementsInner,
   ApiUpdateChecklistRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { Stack } from "@mui/joy";
 import { useQueryClient } from "@tanstack/react-query";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/helpers.ts b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/helpers.ts
index bb1e096320688e660c56914508684a168f1820b1..1b9943820a74c0a92aec5619ae3d8149801e996d 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/helpers.ts
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/checklist/form/helpers.ts
@@ -10,7 +10,7 @@ import {
   ApiCLSectionElementsInner,
   ApiChecklist,
   ApiUpdateChecklistElementsInner,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { isDefined } from "remeda";
 
 export type FormCheckboxField = Omit<ApiCLCheckboxField, "checked"> & {
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentSidebar.tsx
index c3cdf803d3a0369165e92643bcb3dc6d6f820122..437a2d14621dabaafadbaadaa37f72a70d77c755 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentSidebar.tsx
@@ -6,9 +6,9 @@
 import {
   ApiCreateInspectionIncidentRequest,
   ApiInspectionIncident,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
-import { Grid } from "@mui/joy";
+import { Grid, Typography } from "@mui/joy";
 import { Formik } from "formik";
 import { isEmpty, isNonNullish, isNullish } from "remeda";
 import { v4 as uuidv4 } from "uuid";
@@ -18,7 +18,7 @@ import {
   useUpdateIncident,
 } from "@/lib/businessModules/inspection/api/mutations/incidents";
 import { OverlayBoundary } from "@/lib/shared/components/boundaries/OverlayBoundary";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
 import { SidebarForm } from "@/lib/shared/components/form/SidebarForm";
 import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
@@ -99,11 +99,20 @@ function IncidentSidebarInner({
                     />
                   )}
                   {isChecklistIncident && (
-                    <DetailsCell
-                      name="title"
+                    <DetailsItem
                       label="Titel"
-                      value={incident.title}
-                      showIfEmpty
+                      value={
+                        incident.title ?? (
+                          <Typography
+                            data-testid={`title.value`}
+                            component="i"
+                            color="neutral"
+                            level="title-md"
+                          >
+                            Keine Angaben
+                          </Typography>
+                        )
+                      }
                     />
                   )}
                 </Grid>
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentsPanel.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentsPanel.tsx
index b7d63b628655b9d80b9b6c75b85b6037c9cb10a4..9d02ac36923082f83e495aaaa958b44cd64caf8a 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentsPanel.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentsPanel.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspectionIncident } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionIncident } from "@eshg/inspection-api";
 import { Box, Stack, Typography } from "@mui/joy";
 import { useState } from "react";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentsTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentsTable.tsx
index e70225152baf8720c815e0d5974fdffebe456d75..3af7e299bbbf8d8f5f215cf24a3ea48e91ccf00e 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentsTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/execution/incident/IncidentsTable.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspectionIncident } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionIncident } from "@eshg/inspection-api";
 import { DeleteOutlined, Edit } from "@mui/icons-material";
 import { ColorPaletteProp } from "@mui/joy";
 import { ColumnHelper, createColumnHelper } from "@tanstack/react-table";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/history/InspectionHistoryTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/history/InspectionHistoryTable.tsx
index 991f050c89ce0e1e6470331c06976a54844c2618..cb54efeab578e33458664f6c9f04894dc65a9d37 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/history/InspectionHistoryTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/history/InspectionHistoryTable.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspPendingFacility } from "@eshg/employee-portal-api/inspection";
+import { ApiInspPendingFacility } from "@eshg/inspection-api";
 import { Row } from "@tanstack/react-table";
 import { useRouter } from "next/navigation";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/history/columns.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/history/columns.tsx
index e72becc7b349a8aebac06ea8828db0cc72fcc51d..f0f2ed1c4648a4281a9cc9fc385b45f3b0acc74c 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/history/columns.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/history/columns.tsx
@@ -6,7 +6,7 @@
 import {
   type ApiInspPendingFacility,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { OpenInNewOutlined } from "@mui/icons-material";
 import { Chip, IconButton, Stack, Typography } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/new/AddInspectionTiles.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/new/AddInspectionTiles.tsx
index f3ec84a7360384455ebcbd2209a8858e40df17e8..bc08efcaab75e7793ce2a5ebeed48c6119462929 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/new/AddInspectionTiles.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/new/AddInspectionTiles.tsx
@@ -6,10 +6,7 @@
 "use client";
 
 import { ApiUser } from "@eshg/base-api";
-import {
-  ApiInspection,
-  ApiObjectType,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiInspection, ApiObjectType } from "@eshg/inspection-api";
 import { Grid } from "@mui/joy";
 
 import { useUpdateInspectionFacility } from "@/lib/businessModules/inspection/api/mutations/facility";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/new/AdditionalInfoTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/new/AdditionalInfoTile.tsx
index 15c964d8ef295ceee50f4029883a87392712eada..d92314ef8fcaebf456661a1c81651d3a0c9ef6d5 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/new/AdditionalInfoTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/new/AdditionalInfoTile.tsx
@@ -11,7 +11,7 @@ import {
   ApiInspection,
   ApiInspectionType,
   ApiObjectType,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/InspectionTabPlanning.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/InspectionTabPlanning.tsx
index 2760ad7910420d5ad95e8a775278e7ecc6a7c33f..73659201d68d6714d5366150392a560d771e0a0a 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/InspectionTabPlanning.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/InspectionTabPlanning.tsx
@@ -7,7 +7,7 @@ import {
   ApiInspection,
   ApiInspectionAvailableCLDVersionsResponse,
   ApiInspectionPhase,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useWindowDimensions } from "@eshg/lib-portal/hooks/useWindowDimension";
 import { Box, useTheme } from "@mui/joy";
 import { useSuspenseQueries } from "@tanstack/react-query";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementSidebar.tsx
index 11d02144649f1ebb6c3552f73c79f5a276e66ba1..c3b20d13432b4d0c7840791446424088d892210d 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementSidebar.tsx
@@ -6,7 +6,7 @@
 import {
   ApiInspectionAnnouncement,
   ApiInspectionAnnouncementType,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { toDateString, toUtcDate } from "@eshg/lib-portal/helpers/dateTime";
 import { Grid } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementTile.tsx
index 3c30660f78daad7c6d9a4ae9db81bdfad8ef76fe..38081f1ae852de7a712b34b974da5cfe3c94cfdb 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementTile.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionAnnouncement } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionAnnouncement } from "@eshg/inspection-api";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { Typography } from "@mui/joy";
 import { useState } from "react";
@@ -13,7 +13,7 @@ import { isNonNullish, isNullish } from "remeda";
 
 import { AnnouncementSidebar } from "@/lib/businessModules/inspection/components/inspection/planning/announcement/AnnouncementSidebar";
 import { translateInspectionAnnouncement } from "@/lib/businessModules/inspection/shared/enums";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 import { InfoTileAddButton } from "@/lib/shared/components/infoTile/InfoTileAddButton";
 
@@ -70,9 +70,8 @@ export function AnnouncementTile({
         </>
       }
     >
-      <DetailsCell name="date" label="Datum" value={date} />
-      <DetailsCell
-        name="type"
+      <DetailsItem label="Datum" value={date} />
+      <DetailsItem
         label="Kommunikationsmittel"
         value={
           isNonNullish(announcement?.type)
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/appointment/AppointmentTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/appointment/AppointmentTile.tsx
index 16d827bde17abf9f0dc1fe8e0ad89a4b38582c19..35bcee9463c0e898e65619e38e6e506bc4c7ebe7 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/appointment/AppointmentTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/appointment/AppointmentTile.tsx
@@ -5,17 +5,14 @@
 
 "use client";
 
-import {
-  ApiInspection,
-  ApiInspectionAppointment,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiInspection, ApiInspectionAppointment } from "@eshg/inspection-api";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import { useState } from "react";
 import { isNonNullish, isNullish } from "remeda";
 
 import { AppointmentSidebar } from "@/lib/businessModules/inspection/components/inspection/common/appointment/AppointmentSidebar";
 import { getFormattedAppointmentParts } from "@/lib/businessModules/inspection/components/inspection/common/appointment/appointmentUtils";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 import { InfoTileAddButton } from "@/lib/shared/components/infoTile/InfoTileAddButton";
 
@@ -79,8 +76,8 @@ export function AppointmentTile({
           message="Termin muss ausgewählt sein, um eine Begehung durchzuführen."
         />
       )}
-      <DetailsCell name="date" label="Datum" value={date} />
-      <DetailsCell name="timeFrame" label="Zeitraum" value={fromTo} />
+      <DetailsItem label="Datum" value={date} />
+      <DetailsItem label="Zeitraum" value={fromTo} />
     </InfoTile>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistSelectSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistSelectSidebar.tsx
index 0808570df3673f799f84dfb6e57ef670ec2dc9c9..f3f4dfd3ecf8e4cdf4078b7efa70e1569b014510 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistSelectSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistSelectSidebar.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspectionCLDVersion } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionCLDVersion } from "@eshg/inspection-api";
 import { InfoOutlined } from "@mui/icons-material";
 import { Stack, Typography } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistSelectSidebarForm.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistSelectSidebarForm.tsx
index 4c593daf8421fbb8bb6166743b895d96156de2ad..b1b4cf33288dd7b8f88b6f2a2f52ae62bea30d8f 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistSelectSidebarForm.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistSelectSidebarForm.tsx
@@ -6,7 +6,7 @@
 import {
   ApiInspectionAvailableCLDVersionsResponse,
   ApiInspectionCLDVersion,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import { NestedFormProps } from "@eshg/lib-portal/types/form";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistTile.tsx
index 8308f63c0a94ba21e7dae2875b537cc1dfc560d8..9fdd0adfe9afae750b77c972c1d381310345a11f 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/checklist/ChecklistTile.tsx
@@ -10,7 +10,7 @@ import {
   ApiInspection,
   ApiInspectionAvailableCLDVersionsResponse,
   ApiInspectionCLDVersion,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import { DeleteOutlined } from "@mui/icons-material";
 import { Chip, IconButton, Stack, Typography } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventorySidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventorySidebar.tsx
index 4724fa9a2b6c332e63ff08739d8256584fc48773..9db99134006ada40fbd31fa0781f205181db9815 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventorySidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventorySidebar.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiUpdateInspectionModifyInventoryRequest } from "@eshg/employee-portal-api/inspection";
+import { ApiUpdateInspectionModifyInventoryRequest } from "@eshg/inspection-api";
 import { NumberField } from "@eshg/lib-portal/components/formFields/NumberField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { validateRange } from "@eshg/lib-portal/helpers/validators";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventoryTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventoryTable.tsx
index 5edc302c77617f047e7d97f0f858f020a1fbee6e..4bbf6c29239505b62245ddbff16adfad10c10a79 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventoryTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventoryTable.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspectionInventory } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionInventory } from "@eshg/inspection-api";
 import { DeleteOutlined } from "@mui/icons-material";
 import { Chip, IconButton } from "@mui/joy";
 import { createColumnHelper } from "@tanstack/react-table";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventoryTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventoryTile.tsx
index 0d38cf35672af53e28758e3d9babf27dfaab9dbb..77f8f6c5d16f26d9ba53507ca8ec95da438d152f 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventoryTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/inventory/InventoryTile.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiInspectionInventory } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionInventory } from "@eshg/inspection-api";
 import { useState } from "react";
 
 import { InventorySidebar } from "@/lib/businessModules/inspection/components/inspection/planning/inventory/InventorySidebar";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/Packlist.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/Packlist.tsx
index 77f47f4599b1dbcad506f60512f8043767c7c31c..3adf48911a25da592e5b9d712445e8af25f95432 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/Packlist.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/Packlist.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiPacklist } from "@eshg/employee-portal-api/inspection";
+import { ApiPacklist } from "@eshg/inspection-api";
 import { DeleteOutlined } from "@mui/icons-material";
 import {
   Accordion,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistSelectSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistSelectSidebar.tsx
index 101863040667ac6b07fff1498c6f7b1e39158022..df7b080e2661fe6f841923cc06a5cba4cd4d3cc7 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistSelectSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistSelectSidebar.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspectionPLDRevision } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionPLDRevision } from "@eshg/inspection-api";
 import { InfoOutlined } from "@mui/icons-material";
 import { Stack, Typography } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistSelectSidebarForm.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistSelectSidebarForm.tsx
index ad8f5550f90c023490cf886873e8576e6f074596..c29740062f4b1f5d4c4d430d16a41783e3727003 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistSelectSidebarForm.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistSelectSidebarForm.tsx
@@ -6,7 +6,7 @@
 import {
   ApiInspectionAvailablePLDRevisionsResponse,
   ApiInspectionPLDRevision,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import { NestedFormProps } from "@eshg/lib-portal/types/form";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistTile.tsx
index 8f9a669aa1595106a46822b035659f47eda5230b..414f3f3dc3bbdc2c162395ba6c05f4e6c918fccf 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/packlist/PacklistTile.tsx
@@ -5,10 +5,7 @@
 
 "use client";
 
-import {
-  ApiInspection,
-  ApiPacklist,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiInspection, ApiPacklist } from "@eshg/inspection-api";
 import { Stack, Textarea, Typography } from "@mui/joy";
 import { useQueryClient } from "@tanstack/react-query";
 import { useState } from "react";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourceSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourceSidebar.tsx
index 5ca0520e1ced5488548aa0dfcea87ea2ed86f61e..0f33e242a3f128adb6db8e5a5e28642f665e7549 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourceSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourceSidebar.tsx
@@ -10,7 +10,7 @@ import {
   ApiResourceType,
   ApiResourceTypeFromJSON,
 } from "@eshg/base-api";
-import type { ApiInspectionTravelTime } from "@eshg/employee-portal-api/inspection";
+import type { ApiInspectionTravelTime } from "@eshg/inspection-api";
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { optionsFromRecord } from "@eshg/lib-portal/components/formFields/SelectOptions";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourceTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourceTile.tsx
index 07aa0815e5c4fb28ff3a5eab356b3f49ee59a8ce..18a62b36fdc445e74b9a86e10740e182e6f2b4f5 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourceTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourceTile.tsx
@@ -9,7 +9,7 @@ import type {
   ApiInspectionAppointment,
   ApiInspectionResource,
   ApiInspectionTravelTime,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useState } from "react";
 
 import { ResourceSidebar } from "@/lib/businessModules/inspection/components/inspection/planning/resource/ResourceSidebar";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourcesTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourcesTable.tsx
index 4495f3440c5d0f07a57565e61ff0aedab6f6af81..f069b078286c2b325e9d439fc753e282928cb618 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourcesTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/resource/ResourcesTable.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import type { ApiInspectionResource } from "@eshg/employee-portal-api/inspection";
-import { ApiResourceType } from "@eshg/employee-portal-api/inspection";
+import type { ApiInspectionResource } from "@eshg/inspection-api";
+import { ApiResourceType } from "@eshg/inspection-api";
 import {
   CameraAltOutlined,
   DeleteOutlined,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeSidebar.tsx
index 9a2fcaeadcb0a3afaa5bd96d5f698d44a7be70a2..1018a25cd1818f61c85d036733b66022021481ed 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeSidebar.tsx
@@ -7,7 +7,7 @@ import type {
   ApiInspectionAppointment,
   ApiInspectionTravelTime,
   ApiObjectType,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { NumberField } from "@eshg/lib-portal/components/formFields/NumberField";
 import { toDateTimeString } from "@eshg/lib-portal/helpers/dateTime";
 import { isEmptyString } from "@eshg/lib-portal/helpers/guards";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeTile.tsx
index 455a75188f8994347b47608da365b5f3c3795fa7..3ca648d4c322c4a5f162dec316916415287a8c3c 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeTile.tsx
@@ -10,7 +10,7 @@ import type {
   ApiDomesticAddress,
   ApiInspection,
   ApiInspectionTravelTime,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
@@ -24,7 +24,7 @@ import { useInspectionGeoApi } from "@/lib/businessModules/inspection/api/client
 import { useGetDepartment } from "@/lib/businessModules/inspection/api/queries/department";
 import { getReverseGeoCode } from "@/lib/businessModules/inspection/api/queries/geo";
 import { TravelTimeSidebar } from "@/lib/businessModules/inspection/components/inspection/planning/traveltime/TravelTimeSidebar";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 import { useCopy } from "@/lib/shared/hooks/useCopy";
 import { useIsOffline } from "@/lib/shared/hooks/useIsOffline";
@@ -169,38 +169,22 @@ export function TravelTimeTile({
       <Grid container columnSpacing={2} rowSpacing={3}>
         {showTravelStart && (
           <Grid xs={6}>
-            <DetailsCell
-              name="startBuffer"
-              label="Anfahrtszeit in Minuten"
-              value={startBuffer}
-            />
+            <DetailsItem label="Anfahrtszeit in Minuten" value={startBuffer} />
           </Grid>
         )}
         {showTravelStart && (
           <Grid xs={6}>
-            <DetailsCell
-              name="startTime"
-              label="Zeitpunkt der Abfahrt"
-              value={startTime}
-            />
+            <DetailsItem label="Zeitpunkt der Abfahrt" value={startTime} />
           </Grid>
         )}
         {showTravelEnd && (
           <Grid xs={6}>
-            <DetailsCell
-              name="endBuffer"
-              label="Rückfahrzeit in Minuten"
-              value={endBuffer}
-            />
+            <DetailsItem label="Rückfahrzeit in Minuten" value={endBuffer} />
           </Grid>
         )}
         {showTravelEnd && (
           <Grid xs={6}>
-            <DetailsCell
-              name="endTime"
-              label="Zeitpunkt der Rückkehr"
-              value={endTime}
-            />
+            <DetailsItem label="Zeitpunkt der Rückkehr" value={endTime} />
           </Grid>
         )}
       </Grid>
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/InspectionResultSidePanel.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/InspectionResultSidePanel.tsx
index e375d10b8154f0a671a27af050d6df8dd8ab665f..9203416e3c87571eeff6a16a61e7dbd2ca8ec9f5 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/InspectionResultSidePanel.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/InspectionResultSidePanel.tsx
@@ -3,10 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiInspection,
-  ApiInspectionPhase,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiInspection, ApiInspectionPhase } from "@eshg/inspection-api";
 import { InternalLink } from "@eshg/lib-portal/components/navigation/InternalLink";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import ChevronRight from "@mui/icons-material/ChevronRight";
@@ -22,7 +19,7 @@ import {
   translateInspectionResult,
 } from "@/lib/businessModules/inspection/shared/enums";
 import { routes } from "@/lib/businessModules/inspection/shared/routes";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 import { useIsOffline } from "@/lib/shared/hooks/useIsOffline";
 
@@ -59,28 +56,24 @@ export function InspectionResultSidePanel({
     >
       {hasResult && (
         <>
-          <DetailsCell
-            name="resultName"
+          <DetailsItem
             label="Ergebnis"
             value={translateInspectionResult(inspection.result)}
           />
           {followupInfo?.followupType && (
             <>
-              <DetailsCell
-                name="followupType"
+              <DetailsItem
                 label="Folgebegehung"
                 value={translateFollowupType(followupInfo.followupType)}
               />
               {followupInfo.followupDate && (
-                <DetailsCell
-                  name="followupDate"
+                <DetailsItem
                   label="Datum der Nachprüfung"
                   value={formatDate(followupInfo.followupDate)}
                 />
               )}
               {followupInfo.followupId && (
-                <DetailsCell
-                  name="followupId"
+                <DetailsItem
                   label=""
                   value={
                     <InternalLink
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/InspectionResultSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/InspectionResultSidebar.tsx
index 7312e0a33039bfd75d24d97b69ebd729462742c9..b86a679ff6c395d8bde4e8f77903ca6c7df2bcd6 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/InspectionResultSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/InspectionResultSidebar.tsx
@@ -7,7 +7,7 @@ import {
   ApiFollowupType,
   ApiInspectionFollowupInfo,
   ApiInspectionResult,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { optionsFromRecord } from "@eshg/lib-portal/components/formFields/SelectOptions";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/ReportApprovalButtons.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/ReportApprovalButtons.tsx
index 75389c9dcdffb39af66288a230ef054b168fae49..c0f88c5b5674bc0ea6538ee037c91c10b1d5494b 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/ReportApprovalButtons.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/ReportApprovalButtons.tsx
@@ -5,10 +5,7 @@
 
 "use client";
 
-import {
-  ApiInspection,
-  ApiInspectionPhase,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiInspection, ApiInspectionPhase } from "@eshg/inspection-api";
 import { InternalLinkButton } from "@eshg/lib-portal/components/navigation/InternalLinkButton";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { CheckOutlined, EditRoadOutlined } from "@mui/icons-material";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/editor/InspectionReportEditor.tsx b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/editor/InspectionReportEditor.tsx
index e3124eb2a04cce34fd2b2b746409f7e29c2c9c60..ea069b652a6b2398835867a23b103890b73ee420 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/editor/InspectionReportEditor.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/editor/InspectionReportEditor.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiEditorBodyElementsInner } from "@eshg/employee-portal-api/inspection";
+import { ApiEditorBodyElementsInner } from "@eshg/inspection-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { v4 as uuidv4 } from "uuid";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/reportutils.ts b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/reportutils.ts
index 7a5bfc3e54e8cb0e2775fa295145db580281f7cf..f414e1501cf5167a25c823ece5d65705bcb105f5 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/reportutils.ts
+++ b/employee-portal/src/lib/businessModules/inspection/components/inspection/reportresult/reportutils.ts
@@ -3,10 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiInspection,
-  ApiInspectionResult,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiInspection, ApiInspectionResult } from "@eshg/inspection-api";
 import { isNonNullish } from "remeda";
 
 export function inspectionHasResult(inspection: ApiInspection) {
diff --git a/employee-portal/src/lib/businessModules/inspection/components/objectType/EditObjectTypeSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/objectType/EditObjectTypeSidebar.tsx
index 37e213cc9234fe8296d6708be067c8eb30b9f5e9..733f51defbdb9ca073e659d09846f09e204435f2 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/objectType/EditObjectTypeSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/objectType/EditObjectTypeSidebar.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiObjectType } from "@eshg/employee-portal-api/inspection";
+import { ApiObjectType } from "@eshg/inspection-api";
 import { NumberField } from "@eshg/lib-portal/components/formFields/NumberField";
 import {
   validateIntegerAnd,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/objectType/ObjectTypesTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/objectType/ObjectTypesTable.tsx
index 9f557c77d6d44743918eaf708c6aff8238560aaa..a78e3d1600171bbae5bdbbfa73912507511b210b 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/objectType/ObjectTypesTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/objectType/ObjectTypesTable.tsx
@@ -6,7 +6,7 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiObjectType } from "@eshg/employee-portal-api/inspection";
+import { ApiObjectType } from "@eshg/inspection-api";
 import { ColumnHelper, createColumnHelper } from "@tanstack/react-table";
 
 import { useGetObjectTypes } from "@/lib/businessModules/inspection/api/queries/objectTypes";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/CreateOrEditPacklistDefinitionSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/CreateOrEditPacklistDefinitionSidebar.tsx
index 079f6319a3c4799b669004a19a472b2241066c78..bf30a7255c9c80a57c58950078f54293d2c50d11 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/CreateOrEditPacklistDefinitionSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/CreateOrEditPacklistDefinitionSidebar.tsx
@@ -8,7 +8,7 @@
 import {
   ApiObjectType,
   ApiPacklistDefinitionRevision,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { Stack } from "@mui/joy";
 import { Formik } from "formik";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/PacklistDefinitionOverviewTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/PacklistDefinitionOverviewTable.tsx
index 4bea82918b0ef5fa50aa4252c5bfb3dae9825f45..ff14feb44efff7865d9ed822804cc041e311bdd3 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/PacklistDefinitionOverviewTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/PacklistDefinitionOverviewTable.tsx
@@ -8,7 +8,7 @@
 import {
   ApiPacklistDefinition,
   ApiPacklistDefinitionRevision,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { ButtonLink } from "@eshg/lib-portal/components/buttons/ButtonLink";
 import { Add, Edit, History } from "@mui/icons-material";
 import { Button, Stack } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/elements/PacklistDefinitionElement.tsx b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/elements/PacklistDefinitionElement.tsx
index 84ef86e01bf195920a5ef63d54c6e341fbe41774..42d400e62976393c54092f4282bbb8506b0d55ee 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/elements/PacklistDefinitionElement.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/elements/PacklistDefinitionElement.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiPacklistDefinitionElement } from "@eshg/employee-portal-api/inspection";
+import { ApiPacklistDefinitionElement } from "@eshg/inspection-api";
 import { DraggableProvidedDragHandleProps } from "@hello-pangea/dnd";
 import { DeleteOutlined, DragIndicatorOutlined } from "@mui/icons-material";
 import { Box, IconButton, Input, Stack } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/header/PacklistDefinitionHeaderCard.tsx b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/header/PacklistDefinitionHeaderCard.tsx
index e8c1fab8425fc1e1bb45defd0cec5d038fb20e88..4fe5a33e187acc6274f2b34c12dbb8f53166660d 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/header/PacklistDefinitionHeaderCard.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/header/PacklistDefinitionHeaderCard.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiObjectType } from "@eshg/employee-portal-api/inspection";
+import { ApiObjectType } from "@eshg/inspection-api";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { Stack } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/header/PacklistDefinitionHeaderRow.tsx b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/header/PacklistDefinitionHeaderRow.tsx
index ee8f863e3787c45ab7ff739e7b4f6341e895de3e..4c1609a976df3c18b3223ea95e5d14d408c1e768 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/header/PacklistDefinitionHeaderRow.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/header/PacklistDefinitionHeaderRow.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUser } from "@eshg/employee-portal-api/inspection";
+import { ApiUser } from "@eshg/inspection-api";
 import { ButtonLink } from "@eshg/lib-portal/components/buttons/ButtonLink";
 import AddIcon from "@mui/icons-material/Add";
 import { Stack, Typography } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/sidebars/PacklistDefinitionRevisionTile.tsx b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/sidebars/PacklistDefinitionRevisionTile.tsx
index 17a746b089f1b8a2e9b13edc505c650de8362e20..052f37eb3f8288600ee0ab50c8f3c81c35052b53 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/sidebars/PacklistDefinitionRevisionTile.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/packlistDefinition/sidebars/PacklistDefinitionRevisionTile.tsx
@@ -6,7 +6,7 @@
 "use client";
 
 import { ApiUser } from "@eshg/base-api";
-import { ApiPacklistDefinitionRevision } from "@eshg/employee-portal-api/inspection";
+import { ApiPacklistDefinitionRevision } from "@eshg/inspection-api";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import { FactCheckOutlined } from "@mui/icons-material";
 import CropFree from "@mui/icons-material/CropFree";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/repository/ChecklistDefinitionRepoOverviewTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/repository/ChecklistDefinitionRepoOverviewTable.tsx
index 066e1e0525d0d1a1b2fee26d7ea65e92da478e8f..01f9cfc5cfbe6fabb2af9112a0d001cec6d7cc1b 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/repository/ChecklistDefinitionRepoOverviewTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/repository/ChecklistDefinitionRepoOverviewTable.tsx
@@ -6,7 +6,7 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiChecklistDefinitionCentralRepoMetadata } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklistDefinitionCentralRepoMetadata } from "@eshg/inspection-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 
 import {
diff --git a/employee-portal/src/lib/businessModules/inspection/components/repository/MetadataDetailsSidebar.tsx b/employee-portal/src/lib/businessModules/inspection/components/repository/MetadataDetailsSidebar.tsx
index 743d7ba34eaf0abf98d4cb08f02b3caee8d520ad..581cd6ee34a008e7067ffae3964e9e27cf2f7395 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/repository/MetadataDetailsSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/repository/MetadataDetailsSidebar.tsx
@@ -3,12 +3,12 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiChecklistDefinitionCentralRepoMetadata } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklistDefinitionCentralRepoMetadata } from "@eshg/inspection-api";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import { Grid } from "@mui/joy";
 import { isNonNullish } from "remeda";
 
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { DrawerProps } from "@/lib/shared/components/drawer/drawerContext";
 import { useSidebar } from "@/lib/shared/components/drawer/useSidebar";
 import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
@@ -33,26 +33,10 @@ export function MetadataDetailsSidebar({
   return (
     <SidebarContent title="Details">
       <Grid container direction="column" gap={2}>
-        <DetailsCell
-          name={"description"}
-          label={"Beschreibung"}
-          value={metadata?.description}
-        />
-        <DetailsCell
-          name={"changeLog"}
-          label={"Änderungshinweis"}
-          value={metadata?.changeLog}
-        />
-        <DetailsCell
-          name={"contact"}
-          label={"Kontakt"}
-          value={metadata?.contact}
-        />
-        <DetailsCell
-          name={"createdAt"}
-          label={"Erstellt am"}
-          value={createdAt}
-        />
+        <DetailsItem label={"Beschreibung"} value={metadata?.description} />
+        <DetailsItem label={"Änderungshinweis"} value={metadata?.changeLog} />
+        <DetailsItem label={"Kontakt"} value={metadata?.contact} />
+        <DetailsItem label={"Erstellt am"} value={createdAt} />
       </Grid>
     </SidebarContent>
   );
diff --git a/employee-portal/src/lib/businessModules/inspection/components/repository/RepoCLDInfoCard.tsx b/employee-portal/src/lib/businessModules/inspection/components/repository/RepoCLDInfoCard.tsx
index bf71c0a4e67e4fbda0ff18f2256a76474fdd43f9..f45189c3070bf4e9a66f1cf93f7324c3dc41aa40 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/repository/RepoCLDInfoCard.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/repository/RepoCLDInfoCard.tsx
@@ -4,7 +4,7 @@
  */
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiChecklistDefinitionVersion } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklistDefinitionVersion } from "@eshg/inspection-api";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
diff --git a/employee-portal/src/lib/businessModules/inspection/components/repository/overviewTableColumns.tsx b/employee-portal/src/lib/businessModules/inspection/components/repository/overviewTableColumns.tsx
index 4f39f0df016bb8f7fc8c4903364bfeac929ac96a..ea33a74298a345fbfde992ef05e1c79376adf5c1 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/repository/overviewTableColumns.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/repository/overviewTableColumns.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiChecklistDefinitionCentralRepoMetadata } from "@eshg/employee-portal-api/inspection";
+import { ApiChecklistDefinitionCentralRepoMetadata } from "@eshg/inspection-api";
 import {
   Close,
   DeleteOutlined,
diff --git a/employee-portal/src/lib/businessModules/inspection/components/textBlock/TextBlocksTable.tsx b/employee-portal/src/lib/businessModules/inspection/components/textBlock/TextBlocksTable.tsx
index ea5af95b25f7f36634b09efa3ad13313c57ce681..2f5665db82598173a48a934083c56fc34b552799 100644
--- a/employee-portal/src/lib/businessModules/inspection/components/textBlock/TextBlocksTable.tsx
+++ b/employee-portal/src/lib/businessModules/inspection/components/textBlock/TextBlocksTable.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiTextBlock } from "@eshg/employee-portal-api/inspection";
+import { ApiTextBlock } from "@eshg/inspection-api";
 import { Add, DeleteOutlined, Edit } from "@mui/icons-material";
 import { Button } from "@mui/joy";
 import { createColumnHelper } from "@tanstack/react-table";
diff --git a/employee-portal/src/lib/businessModules/inspection/shared/constants.ts b/employee-portal/src/lib/businessModules/inspection/shared/constants.ts
index 5bfbe80e1cd7b6ef4ab2e27e5bdd9b47908f18ad..da80b282f7dbe90547079d49158fa662175a0df3 100644
--- a/employee-portal/src/lib/businessModules/inspection/shared/constants.ts
+++ b/employee-portal/src/lib/businessModules/inspection/shared/constants.ts
@@ -3,10 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiProcedureType,
-  ApiTaskType,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiProcedureType, ApiTaskType } from "@eshg/inspection-api";
 
 export const procedureTypes = [ApiProcedureType.Inspection];
 
diff --git a/employee-portal/src/lib/businessModules/inspection/shared/enums.ts b/employee-portal/src/lib/businessModules/inspection/shared/enums.ts
index 5471ef5f71608b73b2a05494fa046d423163f61a..0ffca329905c3447fa551a4e31ce99fa468bf305 100644
--- a/employee-portal/src/lib/businessModules/inspection/shared/enums.ts
+++ b/employee-portal/src/lib/businessModules/inspection/shared/enums.ts
@@ -11,7 +11,7 @@ import {
   ApiInspectionResult,
   ApiInspectionType,
   ApiWebSearchEntryStatus,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { ChipProps } from "@mui/joy";
 
 export const webSearchStatusNames = {
diff --git a/employee-portal/src/lib/businessModules/inspection/shared/isUnknownUser.ts b/employee-portal/src/lib/businessModules/inspection/shared/isUnknownUser.ts
index bd6b7531c794e018349317334800aecfd7cd9771..631be7e6d8f76ec2eaf6751abc6765b962bd2a8f 100644
--- a/employee-portal/src/lib/businessModules/inspection/shared/isUnknownUser.ts
+++ b/employee-portal/src/lib/businessModules/inspection/shared/isUnknownUser.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUser } from "@eshg/employee-portal-api/inspection";
+import { ApiUser } from "@eshg/inspection-api";
 
 export function isUnknownUser(user: ApiUser) {
   return (
diff --git a/employee-portal/src/lib/businessModules/inspection/shared/offline/useIsOfflineFeatureEnabled.ts b/employee-portal/src/lib/businessModules/inspection/shared/offline/useIsOfflineFeatureEnabled.ts
index 7252bd8d6396f14bbb54e9632591fdff6ad17116..0c1704be9613368261fdfa5a2daaf953d3afb5c5 100644
--- a/employee-portal/src/lib/businessModules/inspection/shared/offline/useIsOfflineFeatureEnabled.ts
+++ b/employee-portal/src/lib/businessModules/inspection/shared/offline/useIsOfflineFeatureEnabled.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspectionFeature } from "@eshg/employee-portal-api/inspection";
+import { ApiInspectionFeature } from "@eshg/inspection-api";
 
 import { useIsNewFeatureEnabledUnsuspended } from "@/lib/businessModules/inspection/api/queries/feature";
 
diff --git a/employee-portal/src/lib/businessModules/inspection/shared/offline/usePrecacheInspections.ts b/employee-portal/src/lib/businessModules/inspection/shared/offline/usePrecacheInspections.ts
index 640d92f69c2841bf05616f1a975cab3d7ad1209b..95b41e0a05261f42c21ea8dfd154f072ed6f2bcb 100644
--- a/employee-portal/src/lib/businessModules/inspection/shared/offline/usePrecacheInspections.ts
+++ b/employee-portal/src/lib/businessModules/inspection/shared/offline/usePrecacheInspections.ts
@@ -23,7 +23,7 @@ import {
   PacklistApi,
   ProcedureApi,
   ProgressEntryApi,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { queryKeyFactory } from "@eshg/lib-portal/api/queryKeyFactory";
 import { QueryClient, useQueryClient } from "@tanstack/react-query";
 import { useCallback } from "react";
diff --git a/employee-portal/src/lib/businessModules/inspection/shared/types.ts b/employee-portal/src/lib/businessModules/inspection/shared/types.ts
index a87805ded7eae48348a76c0562084e8e01129519..e5b792553181e746a794bb4dafd35b7343f47b84 100644
--- a/employee-portal/src/lib/businessModules/inspection/shared/types.ts
+++ b/employee-portal/src/lib/businessModules/inspection/shared/types.ts
@@ -6,7 +6,7 @@
 import {
   GetPendingFacilitiesRequest,
   SearchRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 export type FacilityWebSearchFilters = Partial<Omit<SearchRequest, "sort">> & {
   sortField?: string;
diff --git a/employee-portal/src/lib/businessModules/measlesProtection/api/queries/archiving.ts b/employee-portal/src/lib/businessModules/measlesProtection/api/queries/archiving.ts
index bfa5b4387a429d9121806b11703dba35a23221c9..a4fff14018edd2273cfd0b3c057b21418a76b1a0 100644
--- a/employee-portal/src/lib/businessModules/measlesProtection/api/queries/archiving.ts
+++ b/employee-portal/src/lib/businessModules/measlesProtection/api/queries/archiving.ts
@@ -6,7 +6,7 @@
 import {
   GetArchivableProceduresRequest,
   GetRelevantArchivableProceduresRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 
 import { useArchivingApi } from "@/lib/businessModules/measlesProtection/api/clients";
 import { archivingApiQueryKey } from "@/lib/businessModules/measlesProtection/api/queries/apiQueryKeys";
diff --git a/employee-portal/src/lib/businessModules/measlesProtection/components/procedures/proceduresTable/ProceduresTable.tsx b/employee-portal/src/lib/businessModules/measlesProtection/components/procedures/proceduresTable/ProceduresTable.tsx
index bcee4566ddb0816b53ee1d297ba68dacdc039c78..ca193d2bed3b1599fe7777681f6d4754f37e3627 100644
--- a/employee-portal/src/lib/businessModules/measlesProtection/components/procedures/proceduresTable/ProceduresTable.tsx
+++ b/employee-portal/src/lib/businessModules/measlesProtection/components/procedures/proceduresTable/ProceduresTable.tsx
@@ -6,9 +6,9 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
 import { Row } from "@eshg/lib-portal/components/Row";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 import { ApiGetProcedure200Response } from "@eshg/measles-protection-api";
 import { EditOutlined, Preview, ToggleOffOutlined } from "@mui/icons-material";
 import { Chip } from "@mui/joy";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/api/clients.ts b/employee-portal/src/lib/businessModules/medicalRegistry/api/clients.ts
index 306b535b1c7cf37e23c350193805dca4afc3a916..90b9518ddf685c124819f7e89f0235a76dfd7228 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/api/clients.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/api/clients.ts
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
 import {
   ApprovalRequestApi,
   ArchivingApi,
@@ -12,8 +13,7 @@ import {
   MedicalRegistryImportApi,
   ProcedureApi,
   ProgressEntryApi,
-} from "@eshg/employee-portal-api/medicalRegistry";
-import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
+} from "@eshg/medical-registry-api";
 
 function useConfiguration() {
   const configurationParameters = useApiConfiguration(
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/api/mutations/import.ts b/employee-portal/src/lib/businessModules/medicalRegistry/api/mutations/import.ts
index 85c2718486956a9ec853f5381b3a5cc38247193b..5cf5df8ad234e8330faa57f217a09efcb72b1357 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/api/mutations/import.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/api/mutations/import.ts
@@ -7,7 +7,7 @@ import { ApiResponse } from "@eshg/base-api";
 import {
   ApiImportStatistics,
   ApiImportStatisticsFromJSON,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { useMutation } from "@tanstack/react-query";
 import { useCallback, useRef } from "react";
 
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries.ts b/employee-portal/src/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries.ts
index 80b85e3f2af3ff3c971111b26e0dd639379e7b12..80563be594332e307f506178ece78e0b3fffdd50 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries.ts
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ConfirmProcedureRequest,
-  CreateProcedureRequest,
-} from "@eshg/employee-portal-api/medicalRegistry";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import {
+  ConfirmProcedureRequest,
+  CreateProcedureRequest,
+} from "@eshg/medical-registry-api";
 import { useRouter } from "next/navigation";
 
 import { useMedicalRegistryApi } from "@/lib/businessModules/medicalRegistry/api/clients";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/archiving.ts b/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/archiving.ts
index d53dc5431c4ba60cde087bce3804cb276a909bd9..1309eec95f013ba42df289d4a184d6a18189c317 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/archiving.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/archiving.ts
@@ -6,7 +6,7 @@
 import {
   GetArchivableProceduresRequest,
   GetRelevantArchivableProceduresRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 
 import { useArchivingApi } from "@/lib/businessModules/medicalRegistry/api/clients";
 import { archivingApiQueryKey } from "@/lib/businessModules/medicalRegistry/api/queries/apiQueryKeys";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/draft.ts b/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/draft.ts
index eee8189f26c89c41bdb27388b47b540d6032d51c..d095f68eed402066eaf47d38c1b79f51daf2cd97 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/draft.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/draft.ts
@@ -10,7 +10,7 @@ import {
   ApiMedicalRegistryEntrySearchResult,
   ApiMedicalRegistryEntrySearchResultFromJSON,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/medicalRegistry";
+} from "@eshg/medical-registry-api";
 import { useQuery } from "@tanstack/react-query";
 import { isDefined, mapValues } from "remeda";
 
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/medicalRegistryEntries.ts b/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/medicalRegistryEntries.ts
index 221182ecf36fcf7ef62ab1ff907a97d164b665d5..54b08c5b481c54da178ec9d06a838463e371b91a 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/medicalRegistryEntries.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/medicalRegistryEntries.ts
@@ -5,11 +5,11 @@
 
 "use client";
 
+import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import {
   GetProcedureOverviewRequest,
   MedicalRegistryApi,
-} from "@eshg/employee-portal-api/medicalRegistry";
-import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+} from "@eshg/medical-registry-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import { useMedicalRegistryApi } from "@/lib/businessModules/medicalRegistry/api/clients";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/useGetMedicalProceduresTablePage.ts b/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/useGetMedicalProceduresTablePage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..29d634e18e527fbf0d69c4bb759c6045ad408f37
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/api/queries/useGetMedicalProceduresTablePage.ts
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
+import { useQueries } from "@tanstack/react-query";
+
+import { useMedicalRegistryApi } from "@/lib/businessModules/medicalRegistry/api/clients";
+import {
+  getMedicalRegistryOverviewQuery,
+  getMedicalRegistrySearchQuery,
+} from "@/lib/businessModules/medicalRegistry/api/queries/medicalRegistryEntries";
+import { getMedicalRegistryEntryFilters } from "@/lib/businessModules/medicalRegistry/shared/hooks/useMedicalRegistryFilterSettings";
+import { useGetGdprValidationBannerQuery } from "@/lib/shared/api/queries/gdpr";
+import { FilterValue } from "@/lib/shared/components/filterSettings/models/FilterValue";
+
+export function useGetMedicalProceduresTablePage(
+  isSearchPanel: boolean,
+  pageSize: number,
+  pageNumber: number,
+  activeValues: FilterValue[],
+  searchQuery: string,
+) {
+  const medicalRegistryApi = useMedicalRegistryApi();
+
+  const gdprBannerQuery = useGetGdprValidationBannerQuery(
+    ApiBusinessModule.MedicalRegistry,
+  );
+
+  const proceduresQuery = isSearchPanel
+    ? getMedicalRegistrySearchQuery(medicalRegistryApi, searchQuery)
+    : getMedicalRegistryOverviewQuery(medicalRegistryApi, {
+        ...getMedicalRegistryEntryFilters(activeValues),
+        pageSize: pageSize,
+        pageNumber: pageNumber,
+      });
+
+  const [{ data: medicalHistoryData, isLoading }, gdprBanner] = useQueries({
+    queries: [proceduresQuery, gdprBannerQuery],
+  });
+
+  return {
+    medicalHistoryData,
+    isLoading,
+    gdprBanner,
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/MedicalRegistryProcedureChip.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/MedicalRegistryProcedureChip.tsx
index f0f165a9f3d1100331452fe4b180c18a2d4f06dc..07bb347b177a1b6951779042abefd15e05c1f260 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/MedicalRegistryProcedureChip.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/MedicalRegistryProcedureChip.tsx
@@ -8,7 +8,7 @@
 import {
   ApiProcedureStatus,
   ApiProcedureType,
-} from "@eshg/employee-portal-api/medicalRegistry";
+} from "@eshg/medical-registry-api";
 import { Chip, ChipProps } from "@mui/joy";
 
 import {
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/OccupationalInformationForm.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/OccupationalInformationForm.tsx
index 13db5a6fce38e53ec4edd58501bf33c29e871b98..44002de3325596e6c619c52c75d66c1f333c75ed 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/OccupationalInformationForm.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/OccupationalInformationForm.tsx
@@ -3,7 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiTypeOfChange } from "@eshg/employee-portal-api/medicalRegistry";
 import { professionalTitleNames } from "@eshg/lib-portal/businessModules/medicalRegistry/constants";
 import {
   MedicalRegistryCreateProcedureFormValues,
@@ -22,6 +21,7 @@ import {
   validatePastOrTodayDate,
 } from "@eshg/lib-portal/helpers/validators";
 import { NestedFormProps } from "@eshg/lib-portal/types/form";
+import { ApiTypeOfChange } from "@eshg/medical-registry-api";
 import { Grid, Typography } from "@mui/joy";
 import { useFormikContext } from "formik";
 
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/PersonalInformationForm.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/PersonalInformationForm.tsx
index 0efc847e455a47a07190181ff03ce9990ba866cc..46d11d347069405e62342957c8d40788da2f14cd 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/PersonalInformationForm.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/PersonalInformationForm.tsx
@@ -3,7 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiTypeOfChange } from "@eshg/employee-portal-api/medicalRegistry";
 import {
   MedicalRegistryCreateProcedureFormValues,
   PersonalInformationFormValues,
@@ -16,10 +15,13 @@ import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField"
 import { GENDER_OPTIONS } from "@eshg/lib-portal/components/formFields/constants";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import {
+  validateDateOfBirth,
   validateLength,
   validatePastOrTodayDate,
+  validatePipe,
 } from "@eshg/lib-portal/helpers/validators";
 import { NestedFormProps } from "@eshg/lib-portal/types/form";
+import { ApiTypeOfChange } from "@eshg/medical-registry-api";
 import { Grid, Typography } from "@mui/joy";
 import { useFormikContext } from "formik";
 
@@ -162,7 +164,7 @@ export function PersonalInformationForm(props: NestedFormProps) {
           name={fieldName("birthDate")}
           label={"Geburtsdatum"}
           required={requiredFieldMessage}
-          validate={validatePastOrTodayDate}
+          validate={validatePipe(validatePastOrTodayDate, validateDateOfBirth)}
         />
       </Grid>
       <Grid xxs={6} xxl={4}>
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/ProfessionalismInformationForm.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/ProfessionalismInformationForm.tsx
index eb7152bf10ec5304a0964fba642f04f0e9bac900..e17e3a10257e6712b9ce54658b0bbc1a7391b35b 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/ProfessionalismInformationForm.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/ProfessionalismInformationForm.tsx
@@ -3,10 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiEmploymentStatus,
-  ApiEmploymentType,
-} from "@eshg/employee-portal-api/medicalRegistry";
 import {
   employmentStatusNames,
   employmentTypeNames,
@@ -15,6 +11,10 @@ import { ProfessionalismInformationFormValues } from "@eshg/lib-portal/businessM
 import { RadioGroupField } from "@eshg/lib-portal/components/formFields/RadioGroupField";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import { NestedFormProps } from "@eshg/lib-portal/types/form";
+import {
+  ApiEmploymentStatus,
+  ApiEmploymentType,
+} from "@eshg/medical-registry-api";
 import { Grid, Radio, Typography } from "@mui/joy";
 
 import { requiredFieldMessage } from "@/lib/businessModules/medicalRegistry/components/procedures/create/MedicalRegistryCreateProcedureForm";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/RequiredDocumentsForm.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/RequiredDocumentsForm.tsx
index fbbeccc84e03997d9e370bdd954ebcf26e83bd29..48cdb4c24d4ff48f5f25abab5ba5b7411c54e7a3 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/RequiredDocumentsForm.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/create/RequiredDocumentsForm.tsx
@@ -4,7 +4,6 @@
  */
 
 import { ApiCountryCode } from "@eshg/base-api";
-import { ApiTypeOfChange } from "@eshg/employee-portal-api/medicalRegistry";
 import {
   MedicalRegistryCreateProcedureFormValues,
   RequiredDocumentsFormValues,
@@ -13,6 +12,7 @@ import { FileType } from "@eshg/lib-portal/components/formFields/file/FileType";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import { validateFile } from "@eshg/lib-portal/helpers/validators";
 import { NestedFormProps } from "@eshg/lib-portal/types/form";
+import { ApiTypeOfChange } from "@eshg/medical-registry-api";
 import { Add, DeleteOutlined } from "@mui/icons-material";
 import { Button, Grid, IconButton, Stack, Typography } from "@mui/joy";
 import { FieldArray, useFormikContext } from "formik";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/MedicalRegistryProcedureDetails.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/MedicalRegistryProcedureDetails.tsx
index a19a4e3bb94b93ce687b967d3c76b63bdb3db7f0..42951a4d62da63d1d9032635fd80c24b1dd3656b 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/MedicalRegistryProcedureDetails.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/MedicalRegistryProcedureDetails.tsx
@@ -6,12 +6,12 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
+import { useControlledAlert } from "@eshg/lib-portal/errorHandling/AlertContext";
 import {
   ApiGetProcedure200Response,
   ApiGetProcedureDraftResponse,
   ApiMedicalRegistryEntryProcedureType,
-} from "@eshg/employee-portal-api/medicalRegistry";
-import { useControlledAlert } from "@eshg/lib-portal/errorHandling/AlertContext";
+} from "@eshg/medical-registry-api";
 import { Button, Grid, Stack } from "@mui/joy";
 import { useRouter } from "next/navigation";
 
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/PracticesDetailsSection.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/PracticesDetailsSection.tsx
index 149a9fdf1e96a92028f4476433a9e02f58fb6f7d..70e122e274148530d08eb7cbf0571709efd177aa 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/PracticesDetailsSection.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/PracticesDetailsSection.tsx
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
 import {
   ApiGetProcedure200Response,
   ApiPractice,
-} from "@eshg/employee-portal-api/medicalRegistry";
-import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
+} from "@eshg/medical-registry-api";
 import { Stack } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 import { isDefined } from "remeda";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/ProfessionalDetailsSection.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/ProfessionalDetailsSection.tsx
index ba99ab39f5981ced4c29c71f05619a9e068e06e1..5fa0722649a42451f7b64aae452adc17cabd2168 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/ProfessionalDetailsSection.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/ProfessionalDetailsSection.tsx
@@ -3,7 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGetProcedure200Response } from "@eshg/employee-portal-api/medicalRegistry";
 import {
   employmentStatusNames,
   employmentTypeNames,
@@ -12,6 +11,7 @@ import {
 import { PERSON_FIELD_NAME } from "@eshg/lib-portal/components/formFields/constants";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
+import { ApiGetProcedure200Response } from "@eshg/medical-registry-api";
 import { Stack } from "@mui/joy";
 import { isDefined } from "remeda";
 
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/TypeOfChangeSection.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/TypeOfChangeSection.tsx
index 625f30c5abc61d3fdd11eb2d2c6ef97ff297a15a..181386054650ccb190a1f9a01bb999962ace53e1 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/TypeOfChangeSection.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/TypeOfChangeSection.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGetProcedureDraftResponse } from "@eshg/employee-portal-api/medicalRegistry";
 import { changeTypeNames } from "@eshg/lib-portal/businessModules/medicalRegistry/constants";
+import { ApiGetProcedureDraftResponse } from "@eshg/medical-registry-api";
 import { Typography } from "@mui/joy";
 
 import { ContentPanel } from "@/lib/shared/components/contentPanel/ContentPanel";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/WrittenConfirmationSection.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/WrittenConfirmationSection.tsx
index 1c4ce4da6c4b507da1febb4d2291067f9b1e4d63..09cd761f3b58e911bbb475ea3bdb13703b518651 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/WrittenConfirmationSection.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/details/WrittenConfirmationSection.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGetProcedure200Response } from "@eshg/employee-portal-api/medicalRegistry";
+import { ApiGetProcedure200Response } from "@eshg/medical-registry-api";
 import { SvgIcon, Typography } from "@mui/joy";
 
 import { ContentPanel } from "@/lib/shared/components/contentPanel/ContentPanel";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/FacilitySidebarContent.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/FacilitySidebarContent.tsx
index a77e0facb4af3c752de68c33957d930d801b14a2..c258a4d3ff0bca08680d03f74c7bac60f4ce39bc 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/FacilitySidebarContent.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/FacilitySidebarContent.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGetProcedureDraftResponse } from "@eshg/employee-portal-api/medicalRegistry";
 import { RadioGroupField } from "@eshg/lib-portal/components/formFields/RadioGroupField";
+import { ApiGetProcedureDraftResponse } from "@eshg/medical-registry-api";
 import { Stack, Typography } from "@mui/joy";
 import { isDefined } from "remeda";
 
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/FinalizeDraftSidebar.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/FinalizeDraftSidebar.tsx
index edaf8eef98e3248403f6136a1a4d375a3c4e53bc..3c621dc76a9813c53240f7cb25602b8057f04536 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/FinalizeDraftSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/FinalizeDraftSidebar.tsx
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGetProcedureDraftResponse } from "@eshg/employee-portal-api/medicalRegistry";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
+import { ApiGetProcedureDraftResponse } from "@eshg/medical-registry-api";
 import { Button } from "@mui/joy";
 import { Formik, FormikHelpers } from "formik";
 import { useMemo, useState } from "react";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/PartialEntryErrorSidebar.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/PartialEntryErrorSidebar.tsx
index 0d0a1fae96f75748a16dbefa2a328b72e7b975be..9c96c5f5e9d587188c0191ec2d6679b01aea678c 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/PartialEntryErrorSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/PartialEntryErrorSidebar.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGetProcedureDraftResponse } from "@eshg/employee-portal-api/medicalRegistry";
+import { ApiGetProcedureDraftResponse } from "@eshg/medical-registry-api";
 import { Button, Card, Stack, Typography } from "@mui/joy";
 import { useId } from "react";
 
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/PersonSidebarContent.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/PersonSidebarContent.tsx
index 34a13e22d17b874337f3fe5a27233facea1c4731..116cff8401fd7da718bd273804105ddad11b2c7e 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/PersonSidebarContent.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/PersonSidebarContent.tsx
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiGetProcedureDraftResponse } from "@eshg/employee-portal-api/medicalRegistry";
 import { RadioGroupField } from "@eshg/lib-portal/components/formFields/RadioGroupField";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiGetProcedureDraftResponse } from "@eshg/medical-registry-api";
 import { Stack, Typography } from "@mui/joy";
 
 import { SearchDraftReferencesResponse } from "@/lib/businessModules/medicalRegistry/api/queries/draft";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/ProcedureSidebarContent.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/ProcedureSidebarContent.tsx
index 2da8d87bdd76310a47703ddb41a1bbbd649ef3e6..acd4a7fa0a9eac2194e21f8c58cf3c5eb40a82f1 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/ProcedureSidebarContent.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/ProcedureSidebarContent.tsx
@@ -4,7 +4,6 @@
  */
 
 import { ApiGetReferencePersonResponse } from "@eshg/base-api";
-import { ApiMedicalRegistryEntrySearchResult } from "@eshg/employee-portal-api/medicalRegistry";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import { RadioGroupField } from "@eshg/lib-portal/components/formFields/RadioGroupField";
 import {
@@ -13,6 +12,7 @@ import {
 } from "@eshg/lib-portal/formatters/dateTime";
 import { formatPersonName } from "@eshg/lib-portal/formatters/person";
 import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
+import { ApiMedicalRegistryEntrySearchResult } from "@eshg/medical-registry-api";
 import { Stack, Typography } from "@mui/joy";
 
 import {
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/helper.ts b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/helper.ts
index 5023dd0b194cea04fd83fce6d7fc03c1965954bd..12565e510cdeea0b08324c7299ded00b6a2c6243 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/helper.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/helper.ts
@@ -6,7 +6,7 @@
 import {
   ApiGetProcedureDraftResponse,
   ApiTypeOfChange,
-} from "@eshg/employee-portal-api/medicalRegistry";
+} from "@eshg/medical-registry-api";
 
 export function mapToOptionalPhoneNumbers(phoneNumbers: string[]) {
   if (phoneNumbers.length === 0) {
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/useConfirmDraftDialog.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/useConfirmDraftDialog.tsx
index e57e143681546efc109880d26965cb89a231b3c9..c9a62bd9412c61c675b792dc5f0be3d5459eb9ed 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/useConfirmDraftDialog.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/finalize/useConfirmDraftDialog.tsx
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { ConfirmationDialogOptions } from "@eshg/lib-portal/components/confirmationDialog/ConfirmationDialogProvider";
 import {
   ApiGetProcedureDraftResponse,
   ApiPracticeReferenceFacility,
   ApiProcedureReference,
   ApiProfessionalReferencePerson,
-} from "@eshg/employee-portal-api/medicalRegistry";
-import { ConfirmationDialogOptions } from "@eshg/lib-portal/components/confirmationDialog/ConfirmationDialogProvider";
+} from "@eshg/medical-registry-api";
 
 import { useConfirmDraft } from "@/lib/businessModules/medicalRegistry/api/mutations/medicalRegistryEntries";
 import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/import/ImportDataFormSidebar.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/import/ImportDataFormSidebar.tsx
index 4e614d840bd7241aeb213083e34cfcf07a409c62..d778ccbc8debb7ad686d49a4855ca1b758a3897e 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/import/ImportDataFormSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/import/ImportDataFormSidebar.tsx
@@ -30,38 +30,33 @@ export function ImportDataFormSidebar({ onClose }: ImportDataFormSidebarProps) {
       <SidebarContent title="Daten importieren">
         <Stack gap={3}>
           <Alert
-            color="primary"
-            title="Hinweis"
+            color="danger"
+            title="Duplikate vermeiden"
             message={
               <List
                 marker="disc"
+                size="md"
                 sx={{
                   "&, && > *": { color: "inherit" },
                   paddingInlineStart: "2ch",
                   "--List-padding": 0,
-                  "--ListItem-minHeight": "2rem",
+                  "--ListItem-minHeight": "1.5rem",
+                  "--ListItem-paddingX": 0,
+                  "--ListItem-paddingY": 0,
                 }}
               >
+                <ListItem>Laden Sie Datensätze nicht mehrfach hoch.</ListItem>
                 <ListItem>
-                  Der Import kann nicht rückgängig gemacht werden.
-                </ListItem>
-                <ListItem>Alle Pflichtfelder müssen ausgefüllt sein.</ListItem>
-                <ListItem>Daten-Duplikate sind zu vermeiden.</ListItem>
-                <ListItem>
-                  Die Datei darf maximal 4000 Einträge enthalten.
+                  Vermeiden Sie Duplikate von Bestandsdaten sowie innerhalb der
+                  XLSX-Datei.
                 </ListItem>
               </List>
             }
           />
-          <Alert
-            color="danger"
-            title="Mehrfachupload vermeiden"
-            message="Datensätze dürfen nicht mehrfach hochgeladen werden."
-          />
           <Stack gap={2}>
             <FileField
               name="importFile"
-              label="Wählen Sie eine XLSX-Datei aus"
+              label="XLSX-Datei auswählen (Max. 4000 Einträge)"
               required="Bitte eine XLSX-Datei auswählen."
               accept={FileType.Xlsx}
             />
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/import/ImportDataSummarySidebar.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/import/ImportDataSummarySidebar.tsx
index 9b306964da1653e7918b041ec027da6e298c232f..d0c70c5442ec187a1a1dffff379d105558cc2763 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/import/ImportDataSummarySidebar.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/import/ImportDataSummarySidebar.tsx
@@ -5,9 +5,9 @@
 
 "use client";
 
-import { ApiImportStatistics } from "@eshg/employee-portal-api/medicalRegistry";
 import { downloadFileAndOpen } from "@eshg/lib-portal/api/files/download";
 import { RequiresChildren } from "@eshg/lib-portal/types/react";
+import { ApiImportStatistics } from "@eshg/medical-registry-api";
 import {
   ErrorOutlineOutlined,
   FileDownloadOutlined,
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/proceduresTable/MedicalRegistryEntryOverviewControls.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/proceduresTable/MedicalRegistryEntryOverviewControls.tsx
index dca26fca2f4813cae5f93c8a5c756fd624777e12..bf0f5df6b13d82b526f62e31dab2893467b0d1cc 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/proceduresTable/MedicalRegistryEntryOverviewControls.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/proceduresTable/MedicalRegistryEntryOverviewControls.tsx
@@ -5,65 +5,94 @@
 
 "use client";
 
+import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
+import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { NavigationLink } from "@eshg/lib-portal/components/navigation/NavigationLink";
 import { Add } from "@mui/icons-material";
+import SearchIcon from "@mui/icons-material/Search";
 import { Button } from "@mui/joy";
+import { Formik } from "formik";
 
 import { MedicalRegistryImportButton } from "@/lib/businessModules/medicalRegistry/components/procedures/import/MedicalRegistryImportButton";
 import { routes } from "@/lib/businessModules/medicalRegistry/shared/routes";
 import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
 import { FilterButton } from "@/lib/shared/components/buttons/FilterButton";
 import { UseFilterSettings } from "@/lib/shared/components/filterSettings/useFilterSettings";
-import { SearchFilter } from "@/lib/shared/components/tableFilters/SearchFilter";
-import { useTableControl } from "@/lib/shared/hooks/searchParams/useTableControl";
 
 interface MedicalRegistryEntryOverviewControlProps {
   filterSettings: UseFilterSettings;
   toggleActivePanel: (panelName: "filters" | "entrySearch") => void;
   activePanel: "filters" | "entrySearch" | undefined;
+  onNameSearch: (name: string) => void;
 }
 
 export function MedicalRegistryEntryOverviewControls(
   props: MedicalRegistryEntryOverviewControlProps,
 ) {
-  const tableControl = useTableControl({
-    serverSideSorting: true,
-    sortFieldName: "sortKey",
-  });
+  const isEntrySearch = props.activePanel === "entrySearch";
 
   return (
     <ButtonBar
       left={
-        <>
-          <FilterButton
-            {...props.filterSettings.filterButtonProps}
-            isFilterVisible={props.activePanel === "filters"}
-            onClick={() => props.toggleActivePanel("filters")}
-            activeFilters={
-              props.activePanel !== "entrySearch"
-                ? props.filterSettings.filterButtonProps.activeFilters
-                : 0
-            }
-          />
-          <Button onClick={() => props.toggleActivePanel("entrySearch")}>
-            Suche
-          </Button>
-          {props.activePanel === "entrySearch" && (
-            <SearchFilter
-              tableControl={tableControl}
-              searchParamName="name"
-              label="Suche"
-            />
-          )}
-        </>
+        <Formik
+          initialValues={{
+            name: "",
+          }}
+          onSubmit={({ name }) => props.onNameSearch(name)}
+        >
+          <FormPlus
+            sx={{
+              display: "flex",
+              direction: "row",
+              gap: 2,
+            }}
+          >
+            {isEntrySearch && (
+              <InputField
+                label={null}
+                placeholder="Suche"
+                aria-label="Suche"
+                name="name"
+                type="text"
+                startDecorator={<SearchIcon />}
+              />
+            )}
+            {!isEntrySearch && (
+              <FilterButton
+                {...props.filterSettings.filterButtonProps}
+                isFilterVisible={props.activePanel === "filters"}
+                onClick={() => props.toggleActivePanel("filters")}
+                activeFilters={
+                  props.filterSettings.filterButtonProps.activeFilters
+                }
+              />
+            )}
+            {!isEntrySearch && (
+              <Button onClick={() => props.toggleActivePanel("entrySearch")}>
+                Suche
+              </Button>
+            )}
+            {isEntrySearch && <Button type="submit">Suchen</Button>}
+            {isEntrySearch && (
+              <Button
+                variant="outlined"
+                onClick={() => props.toggleActivePanel("entrySearch")}
+              >
+                Abbrechen
+              </Button>
+            )}
+          </FormPlus>
+        </Formik>
       }
       right={
-        <>
-          <MedicalRegistryImportButton />
-          <NavigationLink href={routes.procedures.create} passHref>
-            <Button startDecorator={<Add />}>Eintrag erstellen</Button>
-          </NavigationLink>
-        </>
+        !isEntrySearch && (
+          <>
+            <MedicalRegistryImportButton />
+            <NavigationLink href={routes.procedures.create} passHref>
+              <Button startDecorator={<Add />}>Eintrag erstellen</Button>
+            </NavigationLink>
+          </>
+        )
       }
     />
   );
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/proceduresTable/MedicalRegistryProceduresTable.tsx b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/proceduresTable/MedicalRegistryProceduresTable.tsx
index d4ea118c1aebad2872725857b3966b578e791594..7b8d2b2ae2d86952ff594dad0dc882131cf3ec7a 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/proceduresTable/MedicalRegistryProceduresTable.tsx
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/components/procedures/proceduresTable/MedicalRegistryProceduresTable.tsx
@@ -5,32 +5,24 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
-import {
-  ApiApplicantAddress,
-  ApiMedicalRegistryEntry,
-} from "@eshg/employee-portal-api/medicalRegistry";
 import { professionalTitleNames } from "@eshg/lib-portal/businessModules/medicalRegistry/constants";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
-import { useSuspenseQueries } from "@tanstack/react-query";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
+import {
+  ApiApplicantAddress,
+  ApiMedicalRegistryEntry,
+} from "@eshg/medical-registry-api";
+import { Box } from "@mui/joy";
 import { createColumnHelper } from "@tanstack/react-table";
-import { useSearchParams } from "next/navigation";
-import { useReducer } from "react";
+import { useEffect, useReducer, useState } from "react";
 import { isDefined } from "remeda";
 
-import { useMedicalRegistryApi } from "@/lib/businessModules/medicalRegistry/api/clients";
-import {
-  getMedicalRegistryOverviewQuery,
-  getMedicalRegistrySearchQuery,
-} from "@/lib/businessModules/medicalRegistry/api/queries/medicalRegistryEntries";
+import { useGetMedicalProceduresTablePage } from "@/lib/businessModules/medicalRegistry/api/queries/useGetMedicalProceduresTablePage";
 import { MedicalRegistryProcedureChip } from "@/lib/businessModules/medicalRegistry/components/procedures/MedicalRegistryProcedureChip";
-import {
-  getMedicalRegistryEntryFilters,
-  useMedicalRegistryFilterSettings,
-} from "@/lib/businessModules/medicalRegistry/shared/hooks/useMedicalRegistryFilterSettings";
+import { useMedicalRegistryFilterSettings } from "@/lib/businessModules/medicalRegistry/shared/hooks/useMedicalRegistryFilterSettings";
 import { routes } from "@/lib/businessModules/medicalRegistry/shared/routes";
-import { useGetGdprValidationBannerQuery } from "@/lib/shared/api/queries/gdpr";
+import { NoSearchResults } from "@/lib/shared/components/NoSearchResult";
 import { FilterSettings } from "@/lib/shared/components/filterSettings/FilterSettings";
 import { FilterSettingsSheet } from "@/lib/shared/components/filterSettings/FilterSettingsSheet";
 import { useGdprValidationTasksAlert } from "@/lib/shared/components/gdpr/useGdprValidationTasksAlert";
@@ -38,7 +30,7 @@ import { Pagination } from "@/lib/shared/components/pagination/Pagination";
 import { DataTable } from "@/lib/shared/components/table/DataTable";
 import { TablePage } from "@/lib/shared/components/table/TablePage";
 import { TableSheet } from "@/lib/shared/components/table/TableSheet";
-import { useTableControl } from "@/lib/shared/hooks/searchParams/useTableControl";
+import { usePagination } from "@/lib/shared/hooks/table/usePagination";
 
 import { MedicalRegistryEntryOverviewControls } from "./MedicalRegistryEntryOverviewControls";
 
@@ -150,49 +142,37 @@ function getProceduresColumns() {
   ];
 }
 
+type PanelName = "filters" | "entrySearch";
+
+function reduceActivePanel(
+  state: PanelName | undefined,
+  newState: PanelName,
+): PanelName | undefined {
+  return newState === state ? undefined : newState;
+}
+
 export function MedicalRegistryProceduresTable() {
-  const tableControl = useTableControl();
+  const { resetPageNumber, page, pageSize, getPaginationProps } =
+    usePagination();
   const filterSettings = useMedicalRegistryFilterSettings();
-
+  const [searchQuery, setSearchQuery] = useState<string>("");
   const [activePanel, toggleActivePanel] = useReducer(
     reduceActivePanel,
     undefined,
   );
 
-  type PanelName = "filters" | "entrySearch";
-
-  function reduceActivePanel(
-    state: PanelName | undefined,
-    newState: PanelName,
-  ): PanelName | undefined {
-    return newState === state ? undefined : newState;
-  }
-
-  const searchParams = useSearchParams();
-  const searchQuery = searchParams.get("name") ?? "";
-
-  const medicalRegistryApi = useMedicalRegistryApi();
-
-  const proceduresQuery =
-    activePanel === "entrySearch"
-      ? getMedicalRegistrySearchQuery(medicalRegistryApi, searchQuery)
-      : getMedicalRegistryOverviewQuery(medicalRegistryApi, {
-          ...getMedicalRegistryEntryFilters(filterSettings.activeValues),
-          pageSize: tableControl.paginationProps.pageSize,
-          pageNumber: tableControl.paginationProps.pageNumber,
-        });
-
-  const gdprBannerQuery = useGetGdprValidationBannerQuery(
-    ApiBusinessModule.MedicalRegistry,
-  );
+  useEffect(() => {
+    resetPageNumber();
+  }, [activePanel, searchQuery, filterSettings.activeValues, resetPageNumber]);
 
-  const [
-    {
-      data: { medicalRegistryEntries, totalElements },
-      isLoading,
-    },
-    gdprBanner,
-  ] = useSuspenseQueries({ queries: [proceduresQuery, gdprBannerQuery] });
+  const { medicalHistoryData, isLoading, gdprBanner } =
+    useGetMedicalProceduresTablePage(
+      activePanel === "entrySearch",
+      pageSize,
+      page,
+      filterSettings.activeValues,
+      searchQuery,
+    );
 
   useGdprValidationTasksAlert({
     banner: gdprBanner.data,
@@ -202,11 +182,13 @@ export function MedicalRegistryProceduresTable() {
   return (
     <TablePage
       aria-label="Vorgänge"
+      fullHeight
       controls={
         <MedicalRegistryEntryOverviewControls
           filterSettings={filterSettings}
           activePanel={activePanel}
           toggleActivePanel={toggleActivePanel}
+          onNameSearch={setSearchQuery}
         />
       }
       filterSettings={
@@ -220,22 +202,33 @@ export function MedicalRegistryProceduresTable() {
       <TableSheet
         loading={isLoading}
         footer={
-          activePanel !== "entrySearch" && (
+          activePanel !== "entrySearch" &&
+          medicalHistoryData && (
             <Pagination
-              totalCount={totalElements}
-              {...tableControl.paginationProps}
+              {...getPaginationProps({
+                totalCount: medicalHistoryData.totalElements,
+              })}
             />
           )
         }
       >
         <DataTable
-          data={medicalRegistryEntries}
+          data={medicalHistoryData?.medicalRegistryEntries ?? []}
           columns={getProceduresColumns()}
           rowNavigation={{
             route: ({ original: { id: procedureId } }) =>
               routes.procedures.byId(procedureId).details,
             focusColumnAccessorKey: "lastName",
           }}
+          noDataComponent={
+            isLoading
+              ? undefined
+              : () => (
+                  <Box flex={1} alignContent="center">
+                    <NoSearchResults info="Keine Vorgänge vorhanden" />
+                  </Box>
+                )
+          }
         />
       </TableSheet>
     </TablePage>
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/shared/constants.ts b/employee-portal/src/lib/businessModules/medicalRegistry/shared/constants.ts
index ff59a2f00d7c9e064c530d42af27d5fca17166f6..0a82276c0d0ab208e252f8ecfa62a67c490a0607 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/shared/constants.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/shared/constants.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiProcedureType } from "@eshg/employee-portal-api/medicalRegistry";
+import { ApiProcedureType } from "@eshg/medical-registry-api";
 
 export const archivableProcedureTypes = [ApiProcedureType.MedicalRegistryEntry];
 
diff --git a/employee-portal/src/lib/businessModules/medicalRegistry/shared/hooks/useMedicalRegistryFilterSettings.ts b/employee-portal/src/lib/businessModules/medicalRegistry/shared/hooks/useMedicalRegistryFilterSettings.ts
index 22a0e162830ef53ea5ea6190b0e6135f1cd6cf6b..cddc92105b5b173a8d9e890c552e057851d2817f 100644
--- a/employee-portal/src/lib/businessModules/medicalRegistry/shared/hooks/useMedicalRegistryFilterSettings.ts
+++ b/employee-portal/src/lib/businessModules/medicalRegistry/shared/hooks/useMedicalRegistryFilterSettings.ts
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { professionalTitleNames } from "@eshg/lib-portal/businessModules/medicalRegistry/constants";
 import {
   ApiProcedureStatus,
   ApiProcedureType,
   ApiProfessionalTitle,
-} from "@eshg/employee-portal-api/medicalRegistry";
-import { GetProcedureOverviewRequest } from "@eshg/employee-portal-api/medicalRegistry/apis";
-import { professionalTitleNames } from "@eshg/lib-portal/businessModules/medicalRegistry/constants";
+  GetProcedureOverviewRequest,
+} from "@eshg/medical-registry-api";
 
 import {
   EntryStatus,
@@ -87,7 +87,6 @@ export function useMedicalRegistryFilterSettings(): UseFilterSettings {
       } else {
         localStorage.removeItem(initialProfessionalTitles);
       }
-      // active values are synced via SearchParamStateProvider
     },
     showSearch: false,
   });
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/clients.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/clients.ts
index a13a2be43ccb9a8510934b677279332349d7c99f..1d822f74556455c9f832994e9719a17dfa109e0e 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/clients.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/clients.ts
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
 import {
   AppointmentBlockApi,
   AppointmentTypeApi,
@@ -12,10 +13,12 @@ import {
   EmployeeOmsProcedureApi,
   FileApi,
   OmsAppointmentApi,
+  OmsDocumentApi,
+  OmsFileApi,
   ProcedureApi,
   ProgressEntryApi,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
+  WaitingRoomApi,
+} from "@eshg/official-medical-service-api";
 
 function useConfiguration() {
   const configurationParameters = useApiConfiguration(
@@ -63,3 +66,18 @@ export function useOmsAppointmentApi() {
   const configuration = useConfiguration();
   return new OmsAppointmentApi(configuration);
 }
+
+export function useOmsDocumentApi() {
+  const configuration = useConfiguration();
+  return new OmsDocumentApi(configuration);
+}
+
+export function useOmsFileApi() {
+  const configuration = useConfiguration();
+  return new OmsFileApi(configuration);
+}
+
+export function useWaitingRoomApi() {
+  const configuration = useConfiguration();
+  return new WaitingRoomApi(configuration);
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/models/AppointmentBlockGroup.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/models/AppointmentBlockGroup.ts
index 6b18e9e1b29e9b63112ce8d55a22e70527e2c6c9..57d26a2f6a4582b7249a99b878d5270bb27dd8c1 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/models/AppointmentBlockGroup.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/models/AppointmentBlockGroup.ts
@@ -3,16 +3,16 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiAppointmentType,
-  ApiGetAppointmentBlock,
-  ApiGetAppointmentBlockGroup,
-} from "@eshg/employee-portal-api/officialMedicalService";
 import {
   BaseEntity,
   mapBaseEntity,
 } from "@eshg/lib-employee-portal/api/models/BaseEntity";
 import { assertNonEmptyArray } from "@eshg/lib-portal/helpers/assertions";
+import {
+  ApiAppointmentType,
+  ApiGetAppointmentBlock,
+  ApiGetAppointmentBlockGroup,
+} from "@eshg/official-medical-service-api";
 import { first, last, sumBy } from "remeda";
 
 export interface AppointmentBlockGroup extends AppointmentBlock {
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/models/AppointmentTypeConfig.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/models/AppointmentTypeConfig.ts
index ffc2e53900500a33fb0f84c1b4792e36758a544b..2c846dcbf2c97b6bac9ebdbc6b195112c0653177 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/models/AppointmentTypeConfig.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/models/AppointmentTypeConfig.ts
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiAppointmentType,
-  ApiAppointmentTypeConfig,
-} from "@eshg/employee-portal-api/officialMedicalService";
 import {
   BaseEntity,
   mapBaseEntity,
 } from "@eshg/lib-employee-portal/api/models/BaseEntity";
+import {
+  ApiAppointmentType,
+  ApiAppointmentTypeConfig,
+} from "@eshg/official-medical-service-api";
 
 export interface AppointmentTypeConfig extends BaseEntity {
   appointmentTypeDto: ApiAppointmentType;
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/appointmentApi.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/appointmentApi.ts
index abd13a73a8135dc696bec5ac668bc98229d3a908..556aa95cca885669d4904774576255d91142abb8 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/appointmentApi.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/appointmentApi.ts
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiBookingInfo } from "@eshg/employee-portal-api/officialMedicalService";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { ApiBookingInfo } from "@eshg/official-medical-service-api";
 
 import { useOmsAppointmentApi } from "@/lib/businessModules/officialMedicalService/api/clients";
 
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/appointmentBlocksApi.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/appointmentBlocksApi.ts
index 52844b5669f18537a76672f76eddd5f14756a8fc..c2552098924f336e571a038b05122139943ceef5 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/appointmentBlocksApi.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/appointmentBlocksApi.ts
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCreateDailyAppointmentBlockGroupRequest } from "@eshg/employee-portal-api/officialMedicalService";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { ApiCreateDailyAppointmentBlockGroupRequest } from "@eshg/official-medical-service-api";
 
 import { useAppointmentBlockApi } from "@/lib/businessModules/officialMedicalService/api/clients";
 
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi.ts
index 7896fc11d097fabd9f2798f140d309261333e4bc..603c1bbcfef4144a9289544d436cafc404fca5ed 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi.ts
@@ -3,10 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   AbortDraftProcedureRequest,
   AcceptDraftProcedureRequest,
   ApiConcern,
+  ApiPatchEmployeeOmsProcedureEmailNotificationsRequest,
   ApiPatchEmployeeOmsProcedureFacilityRequest,
   ApiPatchEmployeeOmsProcedurePhysicianRequest,
   ApiPostEmployeeOmsProcedureRequest,
@@ -14,10 +17,11 @@ import {
   ApiSyncAffectedPersonRequest,
   ApiSyncFacilityRequest,
   CloseOpenProcedureRequest,
+  PatchMedicalOpinionStatusRequest,
+  PatchWaitingRoomRequest,
+  PostDocumentRequest,
   UpdateAffectedPersonRequest,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+} from "@eshg/official-medical-service-api";
 
 import { useEmployeeOmsProcedureApi } from "@/lib/businessModules/officialMedicalService/api/clients";
 import { DefaultFacilityFormValues } from "@/lib/shared/components/facilitySidebar/create/FacilityForm";
@@ -178,6 +182,25 @@ export function usePatchPhysician(procedureId: string) {
   });
 }
 
+export function usePatchEmailNotifications(procedureId: string) {
+  const snackbar = useSnackbar();
+  const employeeOmsProcedureApi = useEmployeeOmsProcedureApi();
+
+  return useHandledMutation({
+    mutationFn: (
+      request: ApiPatchEmployeeOmsProcedureEmailNotificationsRequest,
+    ) => {
+      return employeeOmsProcedureApi.patchEmailNotifications(
+        procedureId,
+        request,
+      );
+    },
+    onSuccess: () => {
+      snackbar.confirmation("Die E-Mail-Einstellungen wurden gespeichert.");
+    },
+  });
+}
+
 export function usePostAppointment() {
   const snackbar = useSnackbar();
   const employeeOmsProcedureApi = useEmployeeOmsProcedureApi();
@@ -193,3 +216,40 @@ export function usePostAppointment() {
     onSuccess: () => snackbar.confirmation("Der Termin wurde angelegt."),
   });
 }
+
+export function usePostDocument() {
+  const snackbar = useSnackbar();
+  const employeeOmsProcedureApi = useEmployeeOmsProcedureApi();
+
+  return useHandledMutation({
+    mutationFn: (request: PostDocumentRequest) =>
+      employeeOmsProcedureApi.postDocumentRaw(request),
+    onSuccess: () => snackbar.confirmation("Das Dokument wurde angelegt."),
+  });
+}
+
+export function usePatchMedicalOpinionStatus() {
+  const snackbar = useSnackbar();
+  const employeeOmsProcedureApi = useEmployeeOmsProcedureApi();
+
+  return useHandledMutation({
+    mutationFn: (request: PatchMedicalOpinionStatusRequest) => {
+      return employeeOmsProcedureApi.patchMedicalOpinionStatusRaw(request);
+    },
+    onSuccess: () => {
+      snackbar.confirmation("Gutachtenstatus geändert");
+    },
+  });
+}
+
+export function usePatchWaitingRoom() {
+  const snackbar = useSnackbar();
+  const employeeOmsProcedureApi = useEmployeeOmsProcedureApi();
+
+  return useHandledMutation({
+    mutationFn: (request: PatchWaitingRoomRequest) =>
+      employeeOmsProcedureApi.patchWaitingRoomRaw(request),
+    onSuccess: () =>
+      snackbar.confirmation("Das Wartezimmer wurde aktualisiert."),
+  });
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/omsDocumentApi.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/omsDocumentApi.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a1ab5fc2c9d54e54e42ce03b8dc4fa743d701bd8
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/mutations/omsDocumentApi.ts
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import {
+  PatchCompleteDocumentFileUploadRequest,
+  PatchDocumentInformationRequest,
+  PatchDocumentNoteRequest,
+  PatchDocumentReviewRequest,
+} from "@eshg/official-medical-service-api";
+
+import { useOmsDocumentApi } from "@/lib/businessModules/officialMedicalService/api/clients";
+
+export function usePatchDocumentInformation() {
+  const snackbar = useSnackbar();
+  const omsDocumentApi = useOmsDocumentApi();
+
+  return useHandledMutation({
+    mutationFn: (request: PatchDocumentInformationRequest) =>
+      omsDocumentApi.patchDocumentInformationRaw(request),
+    onSuccess: () => {
+      snackbar.confirmation("Das Dokument wurde aktualisiert.");
+    },
+  });
+}
+
+export function usePatchCompleteDocumentFileUpload() {
+  const snackbar = useSnackbar();
+  const omsDocumentApi = useOmsDocumentApi();
+
+  return useHandledMutation({
+    mutationFn: (request: PatchCompleteDocumentFileUploadRequest) =>
+      omsDocumentApi.patchCompleteDocumentFileUploadRaw(request),
+    onSuccess: () => {
+      snackbar.confirmation("Das Dokument wurde aktualisiert.");
+    },
+  });
+}
+
+export function useDeleteDocument() {
+  const snackbar = useSnackbar();
+  const omsDocumentApi = useOmsDocumentApi();
+
+  return useHandledMutation({
+    mutationFn: (documentId: string) =>
+      omsDocumentApi.deleteDocumentEmployee(documentId),
+    onSuccess: () => {
+      snackbar.confirmation("Das Dokument wurde gelöscht.");
+    },
+  });
+}
+
+export function usePatchDocumentNote() {
+  const snackbar = useSnackbar();
+  const omsDocumentApi = useOmsDocumentApi();
+
+  return useHandledMutation({
+    mutationFn: (request: PatchDocumentNoteRequest) =>
+      omsDocumentApi.patchDocumentNoteRaw(request),
+    onSuccess: () => {
+      snackbar.confirmation("Die Stichwörter wurden aktualisiert.");
+    },
+  });
+}
+
+export function useReviewDocument() {
+  const omsDocumentApi = useOmsDocumentApi();
+  return useHandledMutation({
+    mutationFn: (request: PatchDocumentReviewRequest) =>
+      omsDocumentApi.patchDocumentReviewRaw(request),
+  });
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/apiQueryKeys.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/apiQueryKeys.ts
index 0d9c060f7e2353f3514287a2c60c368e61b7aa6a..7d788c7db7d482164f361831798c1d9b760c8f7d 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/apiQueryKeys.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/apiQueryKeys.ts
@@ -30,3 +30,7 @@ export const employeeOmsProcedureApiQueryKey = queryKeyFactory(
 );
 
 export const concernApiQueryKey = queryKeyFactory(apiQueryKey(["concernApi"]));
+
+export const waitingRoomApiQueryKey = queryKeyFactory(
+  apiQueryKey(["waitingRoomApi"]),
+);
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/appointmentBlocksApi.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/appointmentBlocksApi.ts
index 0b99cee4c70c561536823761e6b62bd1f9969cd7..6d751c8fddc80987d958f59e9e170c19849c66ec 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/appointmentBlocksApi.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/appointmentBlocksApi.ts
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { mapPaginatedList } from "@eshg/lib-employee-portal/api/models/PaginatedList";
+import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import {
   ApiAppointmentType,
   ApiCreateDailyAppointmentBlockGroupRequest,
   GetAppointmentBlockGroupsRequest,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { mapPaginatedList } from "@eshg/lib-employee-portal/api/models/PaginatedList";
-import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+} from "@eshg/official-medical-service-api";
 import {
   queryOptions,
   useQuery,
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/concerns.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/concerns.ts
index f649ea10961747b3a69b57d50415b05f747a33a0..8cd382005b64805f2ee4f22ed31a4fc990cb60d7 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/concerns.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/concerns.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ConcernApi } from "@eshg/employee-portal-api/officialMedicalService";
+import { ConcernApi } from "@eshg/official-medical-service-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import { useConcernApi } from "@/lib/businessModules/officialMedicalService/api/clients";
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/employeeOmsProcedureApi.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/employeeOmsProcedureApi.ts
index 7fc4f5272daa24083cca54245bebac4b86052cea..30c8f931482516f2890bd08d84defc3c16c0b900 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/employeeOmsProcedureApi.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/employeeOmsProcedureApi.ts
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import {
   EmployeeOmsProcedureApi,
   GetAllEmployeeProceduresRequest,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+} from "@eshg/official-medical-service-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import { useEmployeeOmsProcedureApi } from "@/lib/businessModules/officialMedicalService/api/clients";
@@ -53,15 +53,6 @@ export function getProcedureHeaderQuery(
 
 export function useGetProcedureDetails(procedureId: string) {
   const employeeOmsProcedureApi = useEmployeeOmsProcedureApi();
-  return useSuspenseQuery(
-    getProcedureDetailsQuery(employeeOmsProcedureApi, procedureId),
-  );
-}
-
-export function getProcedureDetailsQuery(
-  employeeOmsProcedureApi: EmployeeOmsProcedureApi,
-  procedureId: string,
-) {
   return queryOptions({
     queryKey: employeeOmsProcedureApiQueryKey([
       "getEmployeeProcedureDetails",
@@ -71,3 +62,12 @@ export function getProcedureDetailsQuery(
       employeeOmsProcedureApi.getEmployeeProcedureDetails(procedureId),
   });
 }
+
+export function useGetAllDocuments(procedureId: string) {
+  const employeeOmsProcedureApi = useEmployeeOmsProcedureApi();
+  return queryOptions({
+    queryKey: employeeOmsProcedureApiQueryKey(["getAllDocuments", procedureId]),
+    queryFn: () => employeeOmsProcedureApi.getAllDocuments(procedureId),
+    select: (response) => response.documents,
+  });
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/waitingRoomApi.ts b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/waitingRoomApi.ts
new file mode 100644
index 0000000000000000000000000000000000000000..737bbf3d33bf18508b902f49b8d94ec76e9a367c
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/api/queries/waitingRoomApi.ts
@@ -0,0 +1,24 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+import { GetWaitingRoomProceduresRequest } from "@eshg/official-medical-service-api";
+import { useSuspenseQuery } from "@tanstack/react-query";
+
+import { useWaitingRoomApi } from "@/lib/businessModules/officialMedicalService/api/clients";
+import { waitingRoomApiQueryKey } from "@/lib/businessModules/officialMedicalService/api/queries/apiQueryKeys";
+
+export function useGetWaitingRoomProcedures(
+  request: GetWaitingRoomProceduresRequest,
+) {
+  const waitingRoomApi = useWaitingRoomApi();
+  return useSuspenseQuery({
+    queryKey: waitingRoomApiQueryKey(["getWaitingRoomProcedures", request]),
+    queryFn: () =>
+      waitingRoomApi
+        .getWaitingRoomProceduresRaw(request)
+        .then(unwrapRawResponse),
+  });
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
index 105d45591dd4faa511d2da8ca5dce7db056f0c1d..a9b92a2e9997b29fd7483865468f8c9a0b0b585a 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
@@ -23,7 +23,6 @@ import { AppointmentStaffSelection } from "@/lib/shared/components/appointmentBl
 import { validateAppointmentBlock } from "@/lib/shared/components/appointmentBlocks/validateAppointmentBlock";
 import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
 import { FormSheet } from "@/lib/shared/components/form/FormSheet";
-import { fullName } from "@/lib/shared/components/users/userFormatter";
 import { validateFieldArray } from "@/lib/shared/helpers/validators";
 
 const DEFAULT_PARALLEL_EXAMINATIONS = 1;
@@ -88,8 +87,9 @@ export function AppointmentBlockGroupForm(
 ) {
   const snackbar = useSnackbar();
   const physicianOptions = props.allPhysicians.map((option) => ({
-    value: option.userId,
-    label: fullName(option),
+    userId: option.userId,
+    firstName: option.firstName,
+    lastName: option.lastName,
   }));
   const appointmentDurations = Object.fromEntries(
     props.allAppointmentTypes.map((currentType) => [
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksGroupForm/CreateAppointmentBlockGroupForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksGroupForm/CreateAppointmentBlockGroupForm.tsx
index a0ee8bc9f2981577c85aaee48a586a5ad9437e0b..5adbc9b3fd1bc8bd264040696cc2d836459c2779 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksGroupForm/CreateAppointmentBlockGroupForm.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksGroupForm/CreateAppointmentBlockGroupForm.tsx
@@ -5,14 +5,14 @@
 
 "use client";
 
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { mapRequiredValue } from "@eshg/lib-portal/helpers/form";
+import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
 import {
   ApiAppointmentType,
   ApiCreateDailyAppointmentBlock,
   ApiCreateDailyAppointmentBlockGroupRequest,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
-import { mapRequiredValue } from "@eshg/lib-portal/helpers/form";
-import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+} from "@eshg/official-medical-service-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { useRouter } from "next/navigation";
 import { useEffect, useState } from "react";
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksTable/AppointmentBlockGroupTable.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksTable/AppointmentBlockGroupTable.tsx
index 86decc820d5cfd89cc729de1db55ebe5119b232f..1635f4679f28d944017d2e6fd5dbf50b87a5e085 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksTable/AppointmentBlockGroupTable.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/appointmentBlocksTable/AppointmentBlockGroupTable.tsx
@@ -5,11 +5,11 @@
 
 "use client";
 
+import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import {
   ApiAppointmentBlockSortKey,
   ApiAppointmentType,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+} from "@eshg/official-medical-service-api";
 import { Chip } from "@mui/joy";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { ColumnSort, createColumnHelper } from "@tanstack/react-table";
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/constants.ts b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/constants.ts
index 8ba90a24538f330ef8770d41c6e3694309c3315d..6a3e57ade656c09b27ec607c4488b5957f70eb62 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/constants.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/constants.ts
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiAppointmentType } from "@eshg/employee-portal-api/officialMedicalService";
 import { EnumMap } from "@eshg/lib-portal/types/helpers";
+import { ApiAppointmentType } from "@eshg/official-medical-service-api";
 
 export const APPOINTMENT_TYPES: EnumMap<ApiAppointmentType> = {
   [ApiAppointmentType.RegularExamination]: "Regeluntersuchung",
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/options.ts b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/options.ts
index 61be359ce8c743ee7b615f7ab69cda11133bbc14..e9a5c1b45816b606da7a465fb5a3dd45a9027836 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/options.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/appointmentBlocks/options.ts
@@ -3,10 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiAppointmentType } from "@eshg/employee-portal-api/officialMedicalService";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
+import { ApiAppointmentType } from "@eshg/official-medical-service-api";
 
 import { APPOINTMENT_TYPES } from "@/lib/businessModules/officialMedicalService/components/appointmentBlocks/constants";
+import { WAITING_STATUS_VALUES } from "@/lib/businessModules/officialMedicalService/shared/translations";
 
 const SUPPORTED_APPOINTMENT_TYPES: string[] = [
   ApiAppointmentType.OfficialMedicalService,
@@ -15,3 +16,5 @@ const SUPPORTED_APPOINTMENT_TYPES: string[] = [
 export const APPOINTMENT_TYPE_OPTIONS = buildEnumOptions(
   APPOINTMENT_TYPES,
 ).filter((option) => SUPPORTED_APPOINTMENT_TYPES.includes(option.value));
+
+export const WAITING_STATUS_OPTIONS = buildEnumOptions(WAITING_STATUS_VALUES);
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AdditionalInfoPanel.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AdditionalInfoPanel.tsx
index 1fd594057970bce1e1ffd01ebffa67f23f9cc0fe..8f60dca3628b48466039d775c8e19e4760c3c844 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AdditionalInfoPanel.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AdditionalInfoPanel.tsx
@@ -5,18 +5,19 @@
 
 "use client";
 
+import { formatPersonName } from "@eshg/lib-portal/formatters/person";
 import {
   ApiEmployeeOmsProcedureDetails,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { formatPersonName } from "@eshg/lib-portal/formatters/person";
+} from "@eshg/official-medical-service-api";
 import { InfoOutlined } from "@mui/icons-material";
 import { Alert } from "@mui/joy";
 import { isDefined } from "remeda";
 
 import { useConcernSidebar } from "@/lib/businessModules/officialMedicalService/components/procedures/details/ConcernSidebar";
+import { useEmailNotificationSidebar } from "@/lib/businessModules/officialMedicalService/components/procedures/details/EmailNotificationSidebar";
 import { usePhysicianSidebar } from "@/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianSidebar";
-import { DetailsCellInlineEdit } from "@/lib/businessModules/officialMedicalService/shared/DetailsCellInlineEdit";
+import { DetailsItemInlineEdit } from "@/lib/businessModules/officialMedicalService/shared/DetailsItemInlineEdit";
 import { isProcedureFinalized } from "@/lib/businessModules/officialMedicalService/shared/helpers";
 import { EditButton } from "@/lib/shared/components/buttons/EditButton";
 import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
@@ -29,6 +30,7 @@ export function AdditionalInfoPanel({
 }>) {
   const concernSidebar = useConcernSidebar();
   const physicianSidebar = usePhysicianSidebar();
+  const emailNotificationSidebar = useEmailNotificationSidebar();
 
   return (
     <InfoTile
@@ -70,8 +72,7 @@ export function AdditionalInfoPanel({
         </Alert>
       )}
       {procedure.concern && (
-        <DetailsCellInlineEdit
-          name="concern"
+        <DetailsItemInlineEdit
           label="Anliegen"
           value={procedure.concern.nameDe}
           renderEditButton={
@@ -86,7 +87,7 @@ export function AdditionalInfoPanel({
       )}
 
       {procedure.physician && (
-        <DetailsCellInlineEdit
+        <DetailsItemInlineEdit
           renderEditButton={
             !isProcedureFinalized(procedure) && (
               <EditButton
@@ -95,11 +96,25 @@ export function AdditionalInfoPanel({
               />
             )
           }
-          name="physician"
           label="Ärzt:In"
           value={formatPersonName(procedure.physician)}
         />
       )}
+
+      {!!procedure.affectedPerson.emailAddresses?.length && (
+        <DetailsItemInlineEdit
+          label="E-Mail-Benachrichtigungen"
+          value={procedure.sendEmailNotifications ? "Aktiviert" : "Deaktiviert"}
+          renderEditButton={
+            procedure.status === ApiProcedureStatus.Draft && (
+              <EditButton
+                aria-label="E-Mail-Benachrichtigungen bearbeiten"
+                onClick={() => emailNotificationSidebar.open({ procedure })}
+              />
+            )
+          }
+        />
+      )}
     </InfoTile>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AffectedPersonPanel.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AffectedPersonPanel.tsx
index 04113419e22c994bae1d0ba55cd3238af364ea60..6a7ddaf694870ae197482ef06008f9727a76c2a1 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AffectedPersonPanel.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AffectedPersonPanel.tsx
@@ -8,11 +8,10 @@
 import {
   ApiEmployeeOmsProcedureDetails,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { Sheet } from "@mui/joy";
+} from "@eshg/official-medical-service-api";
 import { SxProps } from "@mui/joy/styles/types";
 
-import { UpdateAffectedPersonSidebar } from "@/lib/businessModules/officialMedicalService/components/procedures/details/UpdateAffectedPersonSidebar";
+import { useUpdateAffectedPersonSidebar } from "@/lib/businessModules/officialMedicalService/components/procedures/details/UpdateAffectedPersonSidebar";
 import { routes } from "@/lib/businessModules/officialMedicalService/shared/routes";
 import { PersonDetails } from "@/lib/businessModules/schoolEntry/api/models/Person";
 import { EditButton } from "@/lib/shared/components/buttons/EditButton";
@@ -21,8 +20,7 @@ import {
   SyncBarrier,
   useSyncBarrier,
 } from "@/lib/shared/components/centralFile/sync/SyncBarrier";
-import { DetailsSection } from "@/lib/shared/components/detailsSection/DetailsSection";
-import { useToggle } from "@/lib/shared/hooks/useToggle";
+import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 
 const COLUMN_STYLE: SxProps = {
   flexGrow: 1,
@@ -34,10 +32,17 @@ export function AffectedPersonPanel({
 }: Readonly<{
   procedure: ApiEmployeeOmsProcedureDetails;
 }>) {
-  const [editing, toggleEditing] = useToggle(false);
-  const title = "Betroffene Person";
   const person = procedure.affectedPerson;
 
+  const updateAffectedPersonSidebar = useUpdateAffectedPersonSidebar();
+
+  function openSidebar() {
+    updateAffectedPersonSidebar.open({
+      affectedPerson: person,
+      procedureId: procedure.id,
+    });
+  }
+
   const syncRoute =
     person.affectedPersonSync !== undefined
       ? routes.procedures
@@ -58,35 +63,31 @@ export function AffectedPersonPanel({
     syncPersonParams as PersonDetails,
   );
 
+  if (!person) {
+    return null;
+  }
+
   return (
-    person && (
-      <Sheet data-testid="affected-person">
-        <DetailsSection
-          title={title}
-          buttons={
-            procedure.status !== ApiProcedureStatus.Closed &&
-            person.affectedPersonSync !== undefined && (
-              <SyncBarrier
-                outdated={person.affectedPersonSync.outdated}
-                syncHref={syncRoute}
-              >
-                <EditButton
-                  aria-label="Person bearbeiten"
-                  onClick={syncBarrier(toggleEditing)}
-                />
-              </SyncBarrier>
-            )
-          }
-        >
-          <CentralFilePersonDetails person={person} columnSx={COLUMN_STYLE} />
-        </DetailsSection>
-        <UpdateAffectedPersonSidebar
-          affectedPerson={person}
-          onClose={toggleEditing}
-          open={editing}
-          procedureId={procedure.id}
-        />
-      </Sheet>
-    )
+    <InfoTile
+      data-testid="affected-person"
+      name="affectedPerson"
+      title="Betroffene Person"
+      controls={
+        procedure.status !== ApiProcedureStatus.Closed &&
+        person.affectedPersonSync !== undefined && (
+          <SyncBarrier
+            outdated={person.affectedPersonSync.outdated}
+            syncHref={syncRoute}
+          >
+            <EditButton
+              aria-label="Person bearbeiten"
+              onClick={syncBarrier(openSidebar)}
+            />
+          </SyncBarrier>
+        )
+      }
+    >
+      <CentralFilePersonDetails person={person} columnSx={COLUMN_STYLE} />
+    </InfoTile>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentSidebar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentSidebar.tsx
index 7ffc1ef1cbe8f0a991930ed4186e953635f2a9a5..2b2d44ae213bf57c77543875638f98d9e8515e9c 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentSidebar.tsx
@@ -3,35 +3,40 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiAppointment,
-  ApiAppointmentType,
-  ApiBookingType,
-  ApiOmsAppointment,
-  ApiUser,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { NumberField } from "@eshg/lib-portal/components/formFields/NumberField";
+import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
+import {
+  AppointmentListForDate,
+  AppointmentListProps,
+} from "@eshg/lib-portal/components/formFields/appointmentPicker/AppointmentListForDate";
 import {
   AppointmentPickerField,
   FIELD_LABELS_DE,
 } from "@eshg/lib-portal/components/formFields/appointmentPicker/AppointmentPickerField";
-import { assertNever } from "@eshg/lib-portal/helpers/assertions";
 import { toDateTimeString } from "@eshg/lib-portal/helpers/dateTime";
 import {
   validateIntegerAnd,
   validateRange,
 } from "@eshg/lib-portal/helpers/validators";
-import { Box, Button, Sheet, Stack, Typography } from "@mui/joy";
+import {
+  ApiAppointment,
+  ApiAppointmentType,
+  ApiBookingType,
+  ApiOmsAppointment,
+  ApiUser,
+} from "@eshg/official-medical-service-api";
+import { Sheet, Stack, Typography } from "@mui/joy";
 import { addMinutes, isEqual } from "date-fns";
-import { Formik, useFormikContext } from "formik";
-import { useMemo, useState } from "react";
-import { isEmpty, prop, sortBy } from "remeda";
+import { Formik, FormikHelpers, useFormikContext } from "formik";
+import { ReactNode, useMemo, useReducer, useState } from "react";
+import { clamp, isEmpty, prop, sortBy } from "remeda";
 
 import { useBookAppointment } from "@/lib/businessModules/officialMedicalService/api/mutations/appointmentApi";
 import { usePostAppointment } from "@/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi";
 import { useGetFreeAppointmentsQuery } from "@/lib/businessModules/officialMedicalService/api/queries/appointmentBlocksApi";
-import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
+import { APPOINTMENT_TYPES } from "@/lib/businessModules/schoolEntry/features/procedures/translations";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
+import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
 import { SidebarForm } from "@/lib/shared/components/form/SidebarForm";
 import { DateTimeField } from "@/lib/shared/components/formFields/DateTimeField";
 import {
@@ -51,6 +56,7 @@ interface Appointment {
 }
 
 interface AppointmentFormValues {
+  appointmentType: ApiAppointmentType;
   bookingType: ApiBookingType | "SelfBooking";
   appointment?: Appointment;
   start: string;
@@ -69,7 +75,7 @@ export function useCreateAppointmentSidebar(
         await createAppointment({
           procedureId,
           request: {
-            appointmentType: ApiAppointmentType.OfficialMedicalService,
+            appointmentType: values.appointmentType,
             bookingInfo:
               values.bookingType === "SelfBooking"
                 ? undefined
@@ -132,6 +138,60 @@ interface AppointmentSidebarProps extends SidebarWithFormRefProps {
   physician?: ApiUser;
 }
 
+interface FieldsProps {
+  allowSelfBooking: boolean;
+  physician?: ApiUser;
+  appointments: ApiAppointment[];
+  initialValues: AppointmentFormValues;
+}
+
+interface SidebarStep {
+  title: string;
+  subTitle: string;
+  fields: (props: Readonly<FieldsProps>) => ReactNode;
+}
+
+function getAppointmentTypeOptions() {
+  return [
+    {
+      value: ApiAppointmentType.OfficialMedicalService,
+      label: APPOINTMENT_TYPES[ApiAppointmentType.OfficialMedicalService],
+    },
+  ];
+}
+
+function getSteps(editingExistingAppointment: boolean): SidebarStep[] {
+  return editingExistingAppointment
+    ? [
+        {
+          title: "Termin buchen",
+          subTitle: "",
+          fields: (props: Readonly<FieldsProps>) => <BookingForm {...props} />,
+        },
+      ]
+    : [
+        {
+          title: "Termin buchen",
+          subTitle: "Schritt 1 von 2",
+          fields: () => (
+            <>
+              <SelectField
+                name="appointmentType"
+                label="Terminart"
+                required="Bitte eine Terminart auswählen"
+                options={getAppointmentTypeOptions()}
+              />
+            </>
+          ),
+        },
+        {
+          title: "Termin buchen",
+          subTitle: "Schritt 2 von 2",
+          fields: (props: Readonly<FieldsProps>) => <BookingForm {...props} />,
+        },
+      ];
+}
+
 function EmbeddedAppointmentSidebar({
   formRef,
   onClose: handleClose,
@@ -145,9 +205,20 @@ function EmbeddedAppointmentSidebar({
     physician?.userId,
   );
 
+  const steps = getSteps(!!appointment);
+  const lastStepIndex = steps.length - 1;
+  const [stepIndex, changeToStep] = useReducer(
+    (_index: number, newIndex: number) =>
+      clamp(newIndex, { min: 0, max: lastStepIndex }),
+    0,
+  );
+  const step = steps[stepIndex]!;
+  const Fields = step.fields;
+
   async function handleSubmit(values: AppointmentFormValues) {
     if (values.bookingType === ApiBookingType.AppointmentBlock) {
       values = {
+        appointmentType: values.appointmentType,
         bookingType: ApiBookingType.AppointmentBlock,
         start: toDateTimeString(values.appointment!.start),
         duration: Math.round(
@@ -162,49 +233,39 @@ function EmbeddedAppointmentSidebar({
     handleClose(true);
   }
 
+  async function handleNext(
+    newValues: AppointmentFormValues,
+    helpers: FormikHelpers<AppointmentFormValues>,
+  ) {
+    const isOnLastStep = stepIndex === lastStepIndex;
+
+    if (isOnLastStep) {
+      await handleSubmit(newValues);
+      helpers.resetForm();
+      changeToStep(0);
+    } else {
+      changeToStep(stepIndex + 1);
+    }
+  }
+
   return (
-    <Formik initialValues={initialValues} onSubmit={handleSubmit}>
+    <Formik initialValues={initialValues} onSubmit={handleNext}>
       {({ isSubmitting }) => (
         <SidebarForm ref={formRef}>
-          <SidebarContent title="Termin buchen">
-            <AssignedPhysician physician={physician} />
-            <RadioAccordionGroupField
-              name="bookingType"
-              data-testid="booking-type-radio-control"
-            >
-              <RadioAccordionItem
-                value={ApiBookingType.AppointmentBlock}
-                label="Aus Terminblock"
-              >
-                {(isExpanded) => (
-                  <AppointmentBlockForm
-                    isExpanded={isExpanded}
-                    appointments={appointments}
-                    initialMonth={initialValues.appointment?.start}
-                  />
-                )}
-              </RadioAccordionItem>
-              <RadioAccordionItem
-                value={ApiBookingType.UserDefined}
-                label="Individueller Termin"
-              >
-                {(isExpanded) => (
-                  <AppointmentUserDefinedForm isExpanded={isExpanded} />
-                )}
-              </RadioAccordionItem>
-              {allowSelfBooking && (
-                <RadioAccordionItem
-                  sx={{ "& .MuiAccordionDetails-root": { height: 0 } }}
-                  value={"SelfBooking"}
-                  label="Selbstbuchung"
-                />
-              )}
-            </RadioAccordionGroupField>
+          <SidebarContent title={step.title} subtitle={step.subTitle}>
+            <Fields
+              allowSelfBooking={allowSelfBooking}
+              appointments={appointments}
+              initialValues={initialValues}
+              physician={physician}
+            />
           </SidebarContent>
           <AppointmentSidebarActions
             isSubmitting={isSubmitting}
             onClose={handleClose}
-            initialValues={initialValues}
+            stepIndex={stepIndex}
+            changeToStep={changeToStep}
+            lastStepIndex={lastStepIndex}
           />
         </SidebarForm>
       )}
@@ -215,61 +276,82 @@ function EmbeddedAppointmentSidebar({
 function AppointmentSidebarActions({
   isSubmitting,
   onClose,
-  initialValues,
+  stepIndex,
+  changeToStep,
+  lastStepIndex,
 }: {
   isSubmitting: boolean;
   onClose: (force?: boolean) => void;
-  initialValues: AppointmentFormValues;
+  stepIndex: number;
+  changeToStep: (newStep: number) => void;
+  lastStepIndex: number;
 }) {
-  const { values } = useFormikContext<AppointmentFormValues>();
-  const dirty = !isAppointmentFormValuesEqual(initialValues, values);
+  const { dirty } = useFormikContext<AppointmentFormValues>();
+  const isOnFirstStep = stepIndex === 0;
+  const isOnLastStep = stepIndex === lastStepIndex;
+
+  let submitLabel;
+  if (isOnLastStep) {
+    submitLabel = dirty ? "Buchen" : "Schließen";
+  } else {
+    submitLabel = "Weiter";
+  }
 
   return (
     <SidebarActions>
-      <ButtonBar
-        left={
-          dirty && (
-            <Button
-              variant="plain"
-              color="primary"
-              onClick={() => onClose(true)}
-            >
-              Abbrechen
-            </Button>
-          )
-        }
-        right={
-          dirty ? (
-            <SubmitButton submitting={isSubmitting}>Buchen</SubmitButton>
-          ) : (
-            <Button onClick={() => onClose(true)}>Schließen</Button>
-          )
-        }
+      <MultiFormButtonBar
+        submitting={isSubmitting}
+        onCancel={() => onClose(true)}
+        onBack={isOnFirstStep ? undefined : () => changeToStep(stepIndex - 1)}
+        submitLabel={submitLabel}
       />
     </SidebarActions>
   );
 }
 
-function isAppointmentFormValuesEqual(
-  v1: AppointmentFormValues,
-  v2: AppointmentFormValues,
-) {
-  if (v1.bookingType !== v2.bookingType) return false;
-  switch (v1.bookingType) {
-    case ApiBookingType.AppointmentBlock:
-      if (!v1.appointment || !v2.appointment)
-        return v1.appointment == v2.appointment;
-      return (
-        isEqual(v1.appointment.start, v2.appointment.start) &&
-        isEqual(v1.appointment.end, v2.appointment.end)
-      );
-    case ApiBookingType.UserDefined:
-      return v1.start === v2.start && v1.duration === v2.duration;
-    case "SelfBooking":
-      return true;
-    default:
-      assertNever(v1.bookingType);
-  }
+function BookingForm({
+  allowSelfBooking,
+  physician,
+  appointments,
+  initialValues,
+}: Readonly<FieldsProps>) {
+  return (
+    <>
+      <AssignedPhysician physician={physician} />
+      <RadioAccordionGroupField
+        name="bookingType"
+        data-testid="booking-type-radio-control"
+      >
+        <RadioAccordionItem
+          value={ApiBookingType.AppointmentBlock}
+          label="Aus Terminblock"
+        >
+          {(isExpanded) => (
+            <AppointmentBlockForm
+              isExpanded={isExpanded}
+              appointments={appointments}
+              initialMonth={initialValues.appointment?.start}
+            />
+          )}
+        </RadioAccordionItem>
+        <RadioAccordionItem
+          value={ApiBookingType.UserDefined}
+          label="Individueller Termin"
+        >
+          {(isExpanded) => (
+            <AppointmentUserDefinedForm isExpanded={isExpanded} />
+          )}
+        </RadioAccordionItem>
+        {allowSelfBooking && (
+          <RadioAccordionItem
+            sx={{ "& .MuiAccordionDetails-root": { height: 0 } }}
+            value={"SelfBooking"}
+            label="Selbstbuchung"
+          />
+        )}
+      </RadioAccordionGroupField>
+    </>
+  );
 }
 
 function useAppointments(
@@ -316,6 +398,7 @@ function useAppointments(
     return {
       appointments,
       initialValues: {
+        appointmentType: ApiAppointmentType.OfficialMedicalService,
         bookingType:
           appointment?.bookingType ?? ApiBookingType.AppointmentBlock,
         appointment: blockAppointment,
@@ -356,6 +439,7 @@ function AppointmentBlockForm({
           isAppointmentEqual={(apt1: ApiAppointment, apt2: ApiAppointment) =>
             isEqual(apt1.start, apt2.start) && isEqual(apt1.end, apt2.end)
           }
+          appointmentList={StyledAppointmentListForDate}
         />
       )}
     </Sheet>
@@ -365,14 +449,14 @@ function AppointmentBlockForm({
 function AssignedPhysician({ physician }: { physician?: ApiUser }) {
   return (
     physician && (
-      <Box component="dl">
-        <Typography component="dt" my={2} level="title-md">
-          Zugewiesene:r Arzt/Ärztin
-        </Typography>
-        <Typography component="dd" my={2}>
-          {physician.firstName} {physician.lastName}
-        </Typography>
-      </Box>
+      <DetailsItem
+        label="Zugewiesene:r Arzt/Ärztin"
+        value={physician.firstName + " " + physician.lastName}
+        slotProps={{
+          label: { level: "title-md" },
+          value: { level: "body-sm" },
+        }}
+      />
     )
   );
 }
@@ -398,3 +482,28 @@ function AppointmentUserDefinedForm({
     </Stack>
   );
 }
+
+// AppointmentListForDate but with equal width chips and time labels with no leading zeros
+export function StyledAppointmentListForDate<T extends Appointment>(
+  props: AppointmentListProps<T>,
+) {
+  return (
+    <AppointmentListForDate
+      {...props}
+      slotProps={{
+        chip: {
+          sx: {
+            minWidth: "4rem",
+            paddingX: 0,
+          },
+        },
+      }}
+      getLabel={(apt) =>
+        apt.start.toLocaleTimeString("de-DE", {
+          hour: "numeric",
+          minute: "2-digit",
+        })
+      }
+    />
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsPanel.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsPanel.tsx
index df47b2159efd3c5403a7cdd64d0502e1c573b75b..891d97f2cc1109b0986536c83c380ba683061af8 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsPanel.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsPanel.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiEmployeeOmsProcedureDetails } from "@eshg/employee-portal-api/officialMedicalService";
+import { ApiEmployeeOmsProcedureDetails } from "@eshg/official-medical-service-api";
 import { Button } from "@mui/joy";
 
 import { useCreateAppointmentSidebar } from "@/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentSidebar";
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsTable.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsTable.tsx
index e8ec21f5913707cec8c56b214697e497b0c96823..4bdcd78de4bd67eeb866bcbf8e8d8ed65f945c25 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsTable.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsTable.tsx
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+import { EnumMap } from "@eshg/lib-portal/types/helpers";
 import {
   ApiAppointmentState,
   ApiBookingState,
   ApiEmployeeOmsProcedureDetails,
   ApiOmsAppointment,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
-import { EnumMap } from "@eshg/lib-portal/types/helpers";
+} from "@eshg/official-medical-service-api";
 import {
   CheckCircle,
   Delete,
@@ -71,13 +71,11 @@ function createAppointmentColumns({
   openCancelAppointmentDialog,
   openCloseAppointmentDialog,
   openWithdrawAppointmentDialog,
-  closeAppointment,
 }: {
   openBookingSidebar?: (appointment: ApiOmsAppointment) => void;
   openCancelAppointmentDialog?: (appointment: ApiOmsAppointment) => void;
   openCloseAppointmentDialog?: (appointment: ApiOmsAppointment) => void;
   openWithdrawAppointmentDialog?: (appointment: ApiOmsAppointment) => void;
-  closeAppointment?: (appointment: ApiOmsAppointment) => Promise<void>;
 }) {
   return [
     columnHelper.accessor("appointmentType", {
@@ -189,12 +187,12 @@ function createAppointmentColumns({
         if (
           bookingState === ApiBookingState.Cancelled &&
           appointmentState === ApiAppointmentState.Open &&
-          closeAppointment
+          openCloseAppointmentDialog
         ) {
           items.push({
             label: "Als abgeschlossen markieren",
             startDecorator: <CheckCircle />,
-            onClick: () => closeAppointment(ctx.row.original),
+            onClick: () => openCloseAppointmentDialog(ctx.row.original),
           });
         }
 
@@ -234,7 +232,7 @@ export function AppointmentsTable({
     openConfirmationDialog({
       title: "Termin absagen?",
       description:
-        "Der/die Bürger:in wird per E-Mail informiert. Ein neuer Termin kann gebucht werden.",
+        "Ein neuer Termin kann gebucht werden. Der/die Bürger:in wird per E-Mail informiert.",
       color: "danger",
       confirmLabel: "Absagen",
       onConfirm: () => cancelAppointment(appointment),
@@ -244,8 +242,7 @@ export function AppointmentsTable({
   function openCloseAppointmentDialog(appointment: ApiOmsAppointment) {
     openConfirmationDialog({
       title: "Termin abschließen?",
-      description:
-        "Der/die Bürger:in wird per E-Mail informiert. Ein neuer Termin kann gebucht werden.",
+      description: "Der Termin kann nicht mehr editiert werden.",
       confirmLabel: "Abschließen",
       onConfirm: () => closeAppointment(appointment),
     });
@@ -255,7 +252,7 @@ export function AppointmentsTable({
     openConfirmationDialog({
       title: "Terminoption zurückziehen?",
       description:
-        "Der/die Bürger:in wird per E-Mail informiert. Eine neue Terminoption kann erstellt werden.",
+        "Es kan kein Termin über das Online Portal mehr gebucht werden. Der/die Bürger:in wird per E-Mail informiert.",
       color: "danger",
       confirmLabel: "Zurückziehen",
       onConfirm: () => withdrawAppointment(appointment),
@@ -271,7 +268,6 @@ export function AppointmentsTable({
           openCancelAppointmentDialog(appointment),
         openCloseAppointmentDialog,
         openWithdrawAppointmentDialog,
-        closeAppointment,
       });
 
   return <DataTable data={procedure.appointments} columns={columns} />;
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ConcernSidebar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ConcernSidebar.tsx
index 56955156248cc179bba871de976c6763812ce991..0c432c8d2cc13ec7ab87ad286ce54b8765100edb 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ConcernSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ConcernSidebar.tsx
@@ -3,15 +3,15 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
+import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import {
   ApiConcern,
   ApiConcernCategoryConfig,
   ApiConcernConfig,
   ApiEmployeeOmsProcedureDetails,
   ApiGetConcernsResponse,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
-import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
+} from "@eshg/official-medical-service-api";
 import { Grid } from "@mui/joy";
 import { Formik, useFormikContext } from "formik";
 
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/EmailNotificationSidebar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/EmailNotificationSidebar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..640140854e7a9c03c653e0e8eff9c5e43987be85
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/EmailNotificationSidebar.tsx
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiEmployeeOmsProcedureDetails } from "@eshg/official-medical-service-api";
+
+import { usePatchEmailNotifications } from "@/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi";
+import {
+  EmailNotificationsForm,
+  EmailNotificationsFormValues,
+} from "@/lib/businessModules/officialMedicalService/components/procedures/details/EmailNotificationsForm";
+import {
+  SidebarWithFormRefProps,
+  UseSidebarWithFormRefResult,
+  useSidebarWithFormRef,
+} from "@/lib/shared/hooks/useSidebarWithFormRef";
+
+export function useEmailNotificationSidebar(): UseSidebarWithFormRefResult<EmailNotificationSidebarProps> {
+  return useSidebarWithFormRef({ component: EmailNotificationSidebar });
+}
+
+interface EmailNotificationSidebarProps extends SidebarWithFormRefProps {
+  procedure: ApiEmployeeOmsProcedureDetails;
+}
+
+function EmailNotificationSidebar(
+  props: Readonly<EmailNotificationSidebarProps>,
+) {
+  const patchEmailNotifications = usePatchEmailNotifications(
+    props.procedure.id,
+  );
+
+  async function handleSubmit(values: EmailNotificationsFormValues) {
+    await patchEmailNotifications.mutateAsync(
+      { sendEmailNotifications: values.sendEmailNotifications },
+      {
+        onSuccess: () => {
+          props.onClose(true);
+        },
+      },
+    );
+  }
+
+  return (
+    <EmailNotificationsForm
+      title={"E-Mail-Benachrichtigungen"}
+      onSubmit={handleSubmit}
+      onCancel={props.onClose}
+      formRef={props.formRef}
+      initialValues={{
+        sendEmailNotifications: props.procedure.sendEmailNotifications,
+      }}
+      submitLabel="Speichern"
+    />
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/EmailNotificationsForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/EmailNotificationsForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7a0885bdfdd0f4a0bc0d635ea73912f56bfe8a57
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/EmailNotificationsForm.tsx
@@ -0,0 +1,62 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Stack } from "@mui/joy";
+import { Formik } from "formik";
+import { Ref } from "react";
+
+import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
+import {
+  SidebarForm,
+  SidebarFormHandle,
+} from "@/lib/shared/components/form/SidebarForm";
+import { SwitchField } from "@/lib/shared/components/formFields/SwitchField";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+
+export interface EmailNotificationsFormValues {
+  sendEmailNotifications: boolean;
+}
+
+interface EmailNotificationsFormProps {
+  initialValues: EmailNotificationsFormValues;
+  formRef: Ref<SidebarFormHandle>;
+  onCancel: () => void;
+  onSubmit: (values: EmailNotificationsFormValues) => Promise<void>;
+  title: string;
+  submitLabel: string;
+}
+
+export function EmailNotificationsForm(
+  props: Readonly<EmailNotificationsFormProps>,
+) {
+  return (
+    <Formik
+      initialValues={props.initialValues}
+      onSubmit={props.onSubmit}
+      enableReinitialize
+    >
+      {({ isSubmitting }) => (
+        <SidebarForm ref={props.formRef}>
+          <SidebarContent title={props.title}>
+            <Stack gap={2} rowGap={2}>
+              <SwitchField
+                label="E-Mail-Benachrichtigungen an Bürger:in"
+                name="sendEmailNotifications"
+              />
+            </Stack>
+          </SidebarContent>
+          <SidebarActions>
+            <MultiFormButtonBar
+              submitLabel={props.submitLabel}
+              submitting={isSubmitting}
+              onCancel={props.onCancel}
+            />
+          </SidebarActions>
+        </SidebarForm>
+      )}
+    </Formik>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/FacilityPanel.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/FacilityPanel.tsx
index 6d2f04bdd82df4c82056c8950fad45e52f7425e8..7b9f2ae6125a0d66bdad66340a827bdb2693c1fe 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/FacilityPanel.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/FacilityPanel.tsx
@@ -7,8 +7,7 @@ import {
   ApiEmployeeOmsProcedureDetails,
   ApiFacilitySync,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { Sheet } from "@mui/joy";
+} from "@eshg/official-medical-service-api";
 import { SxProps } from "@mui/joy/styles/types";
 import { isDefined } from "remeda";
 
@@ -21,7 +20,7 @@ import {
   SyncBarrier,
   useSyncBarrier,
 } from "@/lib/shared/components/centralFile/sync/SyncBarrier";
-import { DetailsSection } from "@/lib/shared/components/detailsSection/DetailsSection";
+import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
 import { useSidebarWithFormRef } from "@/lib/shared/hooks/useSidebarWithFormRef";
 
 const COLUMN_STYLE: SxProps = {
@@ -38,6 +37,13 @@ export function FacilityPanel({
     component: UpdateFacilitySidebar,
   });
 
+  function openUpdateFacilitySidebar() {
+    updateFacilitySidebar.open({
+      procedureId: procedure.id,
+      facility: procedure.facility!,
+    });
+  }
+
   const syncRoute =
     procedure.facility?.facilitySync !== undefined
       ? routes.procedures
@@ -63,38 +69,33 @@ export function FacilityPanel({
   }
 
   return (
-    <Sheet data-testid="facility">
-      <DetailsSection
-        title={"Auftraggeber"}
-        buttons={
-          isDefined(procedure.facility) &&
-          !procedureClosed() && (
-            <SyncBarrier
-              outdated={procedure.facility?.facilitySync?.outdated ?? false}
-              syncHref={syncRoute}
-            >
-              <EditButton
-                aria-label="Auftraggeber bearbeiten"
-                onClick={syncBarrier(() =>
-                  updateFacilitySidebar.open({
-                    procedureId: procedure.id,
-                    facility: procedure.facility!,
-                  }),
-                )}
-              />
-            </SyncBarrier>
-          )
-        }
-      >
-        {procedureDraft() && !isDefined(procedure.facility) ? (
-          <AddFacility id={procedure.id} />
-        ) : (
-          <CentralFileFacilityDetails
-            facility={{ ...procedure.facility! }}
-            columnSx={COLUMN_STYLE}
-          ></CentralFileFacilityDetails>
-        )}
-      </DetailsSection>
-    </Sheet>
+    <InfoTile
+      data-testid="facility"
+      name="facility"
+      title="Auftraggeber"
+      controls={
+        isDefined(procedure.facility) &&
+        !procedureClosed() && (
+          <SyncBarrier
+            outdated={procedure.facility?.facilitySync?.outdated ?? false}
+            syncHref={syncRoute}
+          >
+            <EditButton
+              aria-label="Auftraggeber bearbeiten"
+              onClick={syncBarrier(openUpdateFacilitySidebar)}
+            />
+          </SyncBarrier>
+        )
+      }
+    >
+      {procedureDraft() && !isDefined(procedure.facility) ? (
+        <AddFacility id={procedure.id} />
+      ) : (
+        <CentralFileFacilityDetails
+          facility={{ ...procedure.facility! }}
+          columnSx={COLUMN_STYLE}
+        />
+      )}
+    </InfoTile>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/MedicalOpinionStatusPanel.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/MedicalOpinionStatusPanel.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..47ab2b3075237f93da550a481f2a2166f15d2eac
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/MedicalOpinionStatusPanel.tsx
@@ -0,0 +1,111 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
+import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
+import {
+  ApiEmployeeOmsProcedureDetails,
+  ApiMedicalOpinionStatus,
+} from "@eshg/official-medical-service-api";
+import { Formik, FormikHelpers } from "formik";
+
+import { usePatchMedicalOpinionStatus } from "@/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi";
+import { STATUS_NAMES_MEDICAL_OPINION_STATUS } from "@/lib/businessModules/officialMedicalService/shared/translations";
+import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
+import { FormStack } from "@/lib/shared/components/form/FormStack";
+import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
+import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
+
+export function MedicalOpinionStatusPanel({
+  procedure,
+}: Readonly<{
+  procedure: ApiEmployeeOmsProcedureDetails;
+}>) {
+  const { openConfirmationDialog } = useConfirmationDialog();
+  const patchMedicalOpinionStatus = usePatchMedicalOpinionStatus();
+  const snackbar = useSnackbar();
+
+  function isMedicalOpinionAccomplished(status: ApiMedicalOpinionStatus) {
+    return status === ApiMedicalOpinionStatus.Accomplished;
+  }
+
+  function handleSubmit(
+    values: ApiEmployeeOmsProcedureDetails,
+    helpers: FormikHelpers<ApiEmployeeOmsProcedureDetails>,
+  ) {
+    if (procedure.medicalOpinionStatus !== values.medicalOpinionStatus) {
+      openConfirmationDialog({
+        onConfirm: async () => {
+          await patchMedicalOpinionStatus.mutateAsync({
+            id: procedure.id,
+            body: values.medicalOpinionStatus,
+          });
+        },
+        onCancel: () => helpers.resetForm(),
+        confirmLabel: "Bestätigen",
+        title: "Gutachtenstatus ändern?",
+        description:
+          "Der/Die Bürger:in wird per Mail über den neuen Status informiert. Die Statusänderung kann nicht rückgängig gemacht werden.",
+      });
+    } else {
+      snackbar.notification("Gutachtenstatus wurde nicht verändert.");
+      helpers.resetForm();
+    }
+  }
+
+  return (
+    <InfoTile
+      data-testid="medical-opinion-status"
+      name="medicalOpinionStatus"
+      title="Gutachtenstatus"
+    >
+      <Formik
+        initialValues={procedure}
+        onSubmit={(values, helpers) => handleSubmit(values, helpers)}
+        enableReinitialize
+      >
+        {({ isSubmitting, handleSubmit, initialValues }) => {
+          const opinionUnacomplished = !isMedicalOpinionAccomplished(
+            initialValues.medicalOpinionStatus,
+          );
+          return (
+            <FormStack onSubmit={handleSubmit}>
+              {opinionUnacomplished ? (
+                <SelectField
+                  label="Status"
+                  name="medicalOpinionStatus"
+                  options={buildEnumOptions(
+                    STATUS_NAMES_MEDICAL_OPINION_STATUS,
+                  )}
+                />
+              ) : (
+                <DetailsItem
+                  label="Status"
+                  value={
+                    STATUS_NAMES_MEDICAL_OPINION_STATUS[
+                      initialValues.medicalOpinionStatus
+                    ]
+                  }
+                ></DetailsItem>
+              )}
+              {opinionUnacomplished && (
+                <ButtonBar
+                  right={
+                    <SubmitButton submitting={isSubmitting}>
+                      Speichern
+                    </SubmitButton>
+                  }
+                />
+              )}
+            </FormStack>
+          );
+        }}
+      </Formik>
+    </InfoTile>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianForm.tsx
index 327962800a9b61f8ab6d1899578542c091506c29..17aacf27f1eedc38ced7869ae2874b41299b7f1b 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianForm.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianForm.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUser } from "@eshg/employee-portal-api/officialMedicalService";
 import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/autocomplete/SingleAutocompleteField";
+import { ApiUser } from "@eshg/official-medical-service-api";
 import { Stack } from "@mui/joy";
 import { Formik } from "formik";
 import { Ref } from "react";
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianSidebar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianSidebar.tsx
index 6a29ac9de425ef9179280c292c7207235e4988d0..3cfe2fe11846974d378b1e2d6aaa8da50c42fb41 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/PhysicianSidebar.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiEmployeeOmsProcedureDetails } from "@eshg/employee-portal-api/officialMedicalService";
+import { ApiEmployeeOmsProcedureDetails } from "@eshg/official-medical-service-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { isDefined } from "remeda";
 
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureActionsPanel.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureActionsPanel.tsx
index b4bdbb60f9d95d117f545cbc5a5a08d01f268385..16579f4a6f168ee6dd92052ecd5f417ace8a314e 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureActionsPanel.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureActionsPanel.tsx
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiEmployeeOmsProcedureDetails,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/officialMedicalService";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+} from "@eshg/official-medical-service-api";
 import { Button } from "@mui/joy";
 import { useRouter } from "next/navigation";
 import { ReactNode } from "react";
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureDetailsTab.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureDetailsTab.tsx
index 5cb04e834cd857d7abc7ba9a586824e86386743c..5388130ff1009bd0786a9e62aef63b88ba030bfb 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureDetailsTab.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureDetailsTab.tsx
@@ -6,6 +6,7 @@
 "use client";
 
 import { Grid, Stack } from "@mui/joy";
+import { useSuspenseQueries } from "@tanstack/react-query";
 
 import { useGetProcedureDetails } from "@/lib/businessModules/officialMedicalService/api/queries/employeeOmsProcedureApi";
 import { AdditionalInfoPanel } from "@/lib/businessModules/officialMedicalService/components/procedures/details/AdditionalInfoPanel";
@@ -13,7 +14,10 @@ import { AffectedPersonPanel } from "@/lib/businessModules/officialMedicalServic
 import { AppointmentsPanel } from "@/lib/businessModules/officialMedicalService/components/procedures/details/AppointmentsPanel";
 import { DetailsGrid } from "@/lib/businessModules/officialMedicalService/components/procedures/details/DetailsGrid";
 import { FacilityPanel } from "@/lib/businessModules/officialMedicalService/components/procedures/details/FacilityPanel";
+import { MedicalOpinionStatusPanel } from "@/lib/businessModules/officialMedicalService/components/procedures/details/MedicalOpinionStatusPanel";
 import { ProcedureActionsPanel } from "@/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureActionsPanel";
+import { WaitingRoomPanel } from "@/lib/businessModules/officialMedicalService/components/procedures/details/WaitingRoomPanel";
+import { isProcedureOpenOrInProgress } from "@/lib/businessModules/officialMedicalService/shared/helpers";
 
 const SPACING = { xxs: 2, sm: 3, md: 3, xxl: 3 };
 
@@ -24,7 +28,9 @@ interface ProcedureDetailsTabProps {
 export function ProcedureDetailsTab({
   procedureId,
 }: Readonly<ProcedureDetailsTabProps>) {
-  const { data: procedure } = useGetProcedureDetails(procedureId);
+  const [{ data: procedure }] = useSuspenseQueries({
+    queries: [useGetProcedureDetails(procedureId)],
+  });
 
   return (
     <DetailsGrid data-testid="procedure-detail-page">
@@ -38,6 +44,10 @@ export function ProcedureDetailsTab({
       <Grid xs={3}>
         <Stack spacing={SPACING}>
           <AdditionalInfoPanel procedure={procedure} />
+          <MedicalOpinionStatusPanel procedure={procedure} />
+          {isProcedureOpenOrInProgress(procedure) && (
+            <WaitingRoomPanel procedure={procedure} />
+          )}
           <ProcedureActionsPanel
             procedure={procedure}
             dataTestid="procedure-actions"
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureDetailsTabHeader.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureDetailsTabHeader.tsx
index 92126eefe888382788e402df58a278ed6cdde31d..ffe519aeac1fa4c75c97adbfdbf483d9ff67e478 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureDetailsTabHeader.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProcedureDetailsTabHeader.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiEmployeeOmsProcedureHeader } from "@eshg/employee-portal-api/officialMedicalService";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiEmployeeOmsProcedureHeader } from "@eshg/official-medical-service-api";
 
 import {
   TabNavigationHeader,
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProceduresDetailsToolbar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProceduresDetailsToolbar.tsx
index 13c14905d3de31e17dde220a50fd223aa17b8f34..4c7e0fbf7602025602280265aaa6217910f34bca 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProceduresDetailsToolbar.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/ProceduresDetailsToolbar.tsx
@@ -6,7 +6,11 @@
 "use client";
 
 import { ApiUserRole } from "@eshg/base-api";
-import { TextSnippetOutlined, TimelineOutlined } from "@mui/icons-material";
+import {
+  DescriptionOutlined,
+  TextSnippetOutlined,
+  TimelineOutlined,
+} from "@mui/icons-material";
 import { Chip } from "@mui/joy";
 
 import { procedureStatusNames } from "@/lib/baseModule/api/procedures/enums";
@@ -56,6 +60,11 @@ function buildTabItems(id: string): TabNavigationItem[] {
       href: routes.procedures.byId(id).details,
       decorator: <TextSnippetOutlined />,
     },
+    {
+      tabButtonName: "Dokumente",
+      href: routes.procedures.byId(id).documents,
+      decorator: <DescriptionOutlined />,
+    },
     {
       tabButtonName: "Verlaufseinträge",
       href: routes.procedures.byId(id).progressEntries,
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/UpdateAffectedPersonSidebar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/UpdateAffectedPersonSidebar.tsx
index 241173c564cfeba8f65a186a41e3286e9629403c..07e39ebc24baead96ae8a893f6995d71582bd422 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/UpdateAffectedPersonSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/UpdateAffectedPersonSidebar.tsx
@@ -3,38 +3,41 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiAffectedPerson } from "@eshg/employee-portal-api/officialMedicalService";
 import { mapOptional } from "@eshg/lib-employee-portal/api/models/utils";
 import { toDateString } from "@eshg/lib-portal/helpers/dateTime";
+import { ApiAffectedPerson } from "@eshg/official-medical-service-api";
 
 import { usePatchAffectedPerson } from "@/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi";
 import { mapToPatchAffectedPersonRequest } from "@/lib/businessModules/officialMedicalService/shared/helpers";
 import { mapApiAddressToForm } from "@/lib/shared/components/form/address/helpers";
-import { PersonEditSidebar } from "@/lib/shared/components/personSidebar/PersonEditSidebar";
 import {
   DefaultPersonForm,
   DefaultPersonFormValues,
 } from "@/lib/shared/components/personSidebar/form/DefaultPersonForm";
+import { PersonSidebarForm } from "@/lib/shared/components/personSidebar/form/PersonSidebarForm";
 import { normalizeListInputs } from "@/lib/shared/components/personSidebar/helpers";
-import { useSidebarForm } from "@/lib/shared/hooks/useSidebarForm";
+import {
+  SidebarWithFormRefProps,
+  useSidebarWithFormRef,
+} from "@/lib/shared/hooks/useSidebarWithFormRef";
+
+export function useUpdateAffectedPersonSidebar() {
+  return useSidebarWithFormRef({
+    component: UpdateAffectedPersonSidebar,
+  });
+}
 
-interface UpdateAffectedPersonSidebarProps {
+interface UpdateAffectedPersonSidebarProps extends SidebarWithFormRefProps {
   affectedPerson: ApiAffectedPerson;
   procedureId: string;
-  open: boolean;
-  onClose: () => void;
 }
 
-export function UpdateAffectedPersonSidebar({
+function UpdateAffectedPersonSidebar({
   affectedPerson,
   procedureId,
-  open,
+  formRef,
   onClose,
 }: UpdateAffectedPersonSidebarProps) {
-  const { closeSidebar, handleClose, sidebarFormRef } = useSidebarForm({
-    onClose,
-  });
-
   const updateAffectedPerson = usePatchAffectedPerson();
 
   const version = affectedPerson.version;
@@ -49,18 +52,18 @@ export function UpdateAffectedPersonSidebar({
         ),
       },
       {
-        onSuccess: closeSidebar,
+        onSuccess: () => onClose(true),
       },
     );
   }
 
   return (
-    <PersonEditSidebar
-      open={open}
+    <PersonSidebarForm
+      mode={"edit"}
       title={"Betroffene Person bearbeiten"}
-      onCancel={handleClose}
+      onCancel={onClose}
       onSubmit={handleSubmit}
-      sidebarFormRef={sidebarFormRef}
+      sidebarFormRef={formRef}
       initialValues={mapPersonDetailsToForm(affectedPerson)}
       component={DefaultPersonForm}
       addressRequired
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/UpdateFacilitySidebar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/UpdateFacilitySidebar.tsx
index 99f90a53dd4a1f3b274339cecc1c53db322e873a..98e9a3307b1e6cef797a0d011ff388a166ecf24d 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/UpdateFacilitySidebar.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/UpdateFacilitySidebar.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiFacility } from "@eshg/employee-portal-api/officialMedicalService";
+import { ApiFacility } from "@eshg/official-medical-service-api";
 
 import { usePatchFacility } from "@/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi";
 import {
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/WaitingRoomPanel.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/WaitingRoomPanel.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f577f95a91846429c57892c642f03e7eb23fd2dc
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/WaitingRoomPanel.tsx
@@ -0,0 +1,102 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
+import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
+import {
+  mapOptionalValue,
+  parseOptionalValue,
+} from "@eshg/lib-portal/helpers/form";
+import {
+  OptionalFieldValue,
+  SetFieldValueHelper,
+} from "@eshg/lib-portal/types/form";
+import {
+  ApiEmployeeOmsProcedureDetails,
+  ApiWaitingStatus,
+} from "@eshg/official-medical-service-api";
+import { Button } from "@mui/joy";
+import { Formik } from "formik";
+
+import { usePatchWaitingRoom } from "@/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi";
+import { WAITING_STATUS_OPTIONS } from "@/lib/businessModules/officialMedicalService/components/appointmentBlocks/options";
+import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
+import { FormStack } from "@/lib/shared/components/form/FormStack";
+import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
+import { InfoTile } from "@/lib/shared/components/infoTile/InfoTile";
+
+interface WaitingRoomValues {
+  info: OptionalFieldValue<string>;
+  status: OptionalFieldValue<ApiWaitingStatus>;
+}
+
+export function WaitingRoomPanel({
+  procedure,
+}: Readonly<{
+  procedure: ApiEmployeeOmsProcedureDetails;
+}>) {
+  const patchWaitingRoom = usePatchWaitingRoom();
+
+  async function handleSubmit(values: WaitingRoomValues) {
+    await patchWaitingRoom.mutateAsync({
+      id: procedure.id,
+      apiWaitingRoom: {
+        info: mapOptionalValue(values.info),
+        status: mapOptionalValue(values.status),
+      },
+    });
+  }
+
+  async function handleReset(setFieldValue: SetFieldValueHelper) {
+    void setFieldValue("info", "");
+    void setFieldValue("status", "");
+
+    await handleSubmit({ info: "", status: "" });
+  }
+
+  return (
+    <InfoTile data-testid="waiting-room" name="waitingRoom" title="Wartezimmer">
+      <Formik
+        initialValues={{
+          info: parseOptionalValue(procedure.waitingRoom.info),
+          status: parseOptionalValue(procedure.waitingRoom.status),
+        }}
+        onSubmit={handleSubmit}
+      >
+        {({ isSubmitting, handleSubmit, setFieldValue }) => {
+          return (
+            <FormStack onSubmit={handleSubmit}>
+              <TextareaField
+                name="info"
+                label="Zusätzliche Info"
+                sxTextarea={{ maxHeight: "37px" }}
+              />
+              <SelectField
+                label="Status"
+                name="status"
+                options={WAITING_STATUS_OPTIONS}
+              />
+              <ButtonBar
+                right={
+                  <>
+                    <Button
+                      variant="outlined"
+                      onClick={() => handleReset(setFieldValue)}
+                    >
+                      Zurücksetzen
+                    </Button>
+                    <SubmitButton submitting={isSubmitting}>
+                      Speichern
+                    </SubmitButton>
+                  </>
+                }
+              />
+            </FormStack>
+          );
+        }}
+      </Formik>
+    </InfoTile>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e171f8af3e90a6fd6b080f194574902de276d1e9
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentForm.tsx
@@ -0,0 +1,215 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+"use client";
+
+import { FormAddMoreButton } from "@eshg/lib-portal/components/form/FormAddMoreButton";
+import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
+import { RadioGroupField } from "@eshg/lib-portal/components/formFields/RadioGroupField";
+import Delete from "@mui/icons-material/Delete";
+import { Divider, IconButton, Radio, Stack, Typography } from "@mui/joy";
+import { Formik, FormikErrors } from "formik";
+import { Ref } from "react";
+import { isDefined } from "remeda";
+
+import { theme } from "@/lib/baseModule/theme/theme";
+import { FilesSection } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/FilesSection";
+import { SwitchField } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/SwitchField";
+import { HorizontalFieldLabelEnd } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/shared/HorizontalFieldLabelEnd";
+import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
+import {
+  SidebarForm,
+  SidebarFormHandle,
+} from "@/lib/shared/components/form/SidebarForm";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+
+export interface AddDocumentFormValues {
+  documentTypeDe: string;
+  documentTypeEn?: string;
+  helpTextDe?: string;
+  helpTextEn?: string;
+  mandatoryDocument: boolean;
+  uploadInCitizenPortal: boolean;
+  files?: File[];
+  note?: string;
+  upload?: string;
+}
+
+interface AddDocumentFormProps {
+  initialValues: AddDocumentFormValues;
+  formRef: Ref<SidebarFormHandle>;
+  onCancel: () => void;
+  onSubmit: (values: AddDocumentFormValues) => Promise<void>;
+  title: string;
+  submitLabel: string;
+}
+
+export function AddDocumentForm(props: Readonly<AddDocumentFormProps>) {
+  async function handleChange(
+    values: AddDocumentFormValues,
+    newType: string,
+    setFieldValue: (
+      field: string,
+      value: boolean | File[] | string,
+    ) => Promise<void | FormikErrors<AddDocumentFormValues>>,
+    setFieldTouched: (
+      field: string,
+      isTouched: boolean,
+      shouldValidate: boolean,
+    ) => Promise<void | FormikErrors<AddDocumentFormValues>>,
+  ) {
+    await setFieldTouched("uploadInCitizenPortal", true, false);
+    if (isDefined(values.files) && values.files.length >= 1) {
+      await setFieldValue("files", []);
+    }
+    if (newType === "citizen") {
+      await setFieldValue("uploadInCitizenPortal", true);
+      await setFieldValue("note", "");
+      return;
+    }
+    if (newType === "later") {
+      await setFieldValue("uploadInCitizenPortal", false);
+      await setFieldValue("note", "");
+      return;
+    }
+    if (newType === "now") {
+      await setFieldValue("uploadInCitizenPortal", false);
+    }
+  }
+
+  return (
+    <Formik
+      initialValues={props.initialValues}
+      onSubmit={props.onSubmit}
+      enableReinitialize
+    >
+      {({ isSubmitting, values, setFieldValue, setFieldTouched }) => (
+        <SidebarForm ref={props.formRef}>
+          <SidebarContent title={props.title}>
+            <Stack gap={2} rowGap={4}>
+              <Typography level={"title-md"}>Angaben zum Dokument</Typography>
+              <Stack direction="column" gap={1}>
+                <InputField
+                  name="documentTypeDe"
+                  label="Dokumentenart"
+                  required="Bitte geben Sie eine Dokumentenart an"
+                />
+                {isDefined(values.documentTypeEn) ? (
+                  <InputField
+                    name="documentTypeEn"
+                    label="Dokumentenart (EN)"
+                    endDecorator={
+                      <IconButton
+                        color="danger"
+                        aria-label="Dokumentenart (EN) entfernen"
+                        onClick={async () => {
+                          await setFieldValue("documentTypeEn", undefined);
+                        }}
+                      >
+                        <Delete />
+                      </IconButton>
+                    }
+                  />
+                ) : (
+                  <FormAddMoreButton
+                    onClick={() => setFieldValue("documentTypeEn", "", false)}
+                    aria-label="Dokument Übersetzen"
+                  >
+                    Übersetzung ergänzen
+                  </FormAddMoreButton>
+                )}
+              </Stack>
+              <Stack direction="column" gap={1}>
+                <InputField name="helpTextDe" label="Hilfstext" />
+                {isDefined(values.helpTextEn) ? (
+                  <InputField
+                    name="helpTextEn"
+                    label="Hilfstext (EN)"
+                    endDecorator={
+                      <IconButton
+                        color="danger"
+                        aria-label="Hilfstext (EN) entfernen"
+                        onClick={async () => {
+                          await setFieldValue("helpTextEn", undefined);
+                        }}
+                      >
+                        <Delete />
+                      </IconButton>
+                    }
+                  />
+                ) : (
+                  <FormAddMoreButton
+                    onClick={() => setFieldValue("helpTextEn", "", false)}
+                    aria-label="Hilfstext Übersetzen"
+                  >
+                    Übersetzung ergänzen
+                  </FormAddMoreButton>
+                )}
+              </Stack>
+              <SwitchField
+                name="mandatoryDocument"
+                label="Pflichtdokument"
+                sx={{
+                  ".MuiFormLabel-root": {
+                    fontSize: theme.typography["body-md"].fontSize,
+                    fontWeight: theme.typography["body-md"].fontWeight,
+                  },
+                }}
+                component={HorizontalFieldLabelEnd}
+              />
+              <Divider orientation="horizontal" />
+              <Stack direction="column" gap={2}>
+                <RadioGroupField
+                  name="upload"
+                  label="Dateien"
+                  sx={{
+                    ".MuiFormLabel-root": {
+                      fontSize: theme.typography["title-md"].fontSize,
+                      fontWeight: theme.typography["title-md"].fontWeight,
+                      pb: theme.spacing(2),
+                    },
+                  }}
+                  onChange={async (newType) =>
+                    await handleChange(
+                      values,
+                      newType,
+                      setFieldValue,
+                      setFieldTouched,
+                    )
+                  }
+                >
+                  <Stack direction="column" gap={4}>
+                    <Radio value="citizen" label="Upload durch Bürger:in" />
+                    <Radio value="later" label="Dateien später hochladen" />
+                    <Radio value="now" label="Dateien jetzt hochladen" />
+                  </Stack>
+                </RadioGroupField>
+                {values.upload === "now" && (
+                  <Stack gap={2}>
+                    <FilesSection
+                      name="files"
+                      canAdd={true}
+                      withInitialField={true}
+                      addLabel="Weitere Datei hochladen"
+                    />
+                    <InputField name="note" label="Stichwörter" />
+                  </Stack>
+                )}
+              </Stack>
+            </Stack>
+          </SidebarContent>
+          <SidebarActions>
+            <MultiFormButtonBar
+              submitLabel={props.submitLabel}
+              submitting={isSubmitting}
+              onCancel={props.onCancel}
+            />
+          </SidebarActions>
+        </SidebarForm>
+      )}
+    </Formik>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentSidebar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentSidebar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..dcd9131f234c3154659ba9044fef126b26d6690c
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentSidebar.tsx
@@ -0,0 +1,73 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { PostDocumentRequest } from "@eshg/official-medical-service-api";
+
+import { usePostDocument } from "@/lib/businessModules/officialMedicalService/api/mutations/employeeOmsProcedureApi";
+import {
+  AddDocumentForm,
+  AddDocumentFormValues,
+} from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentForm";
+import {
+  SidebarWithFormRefProps,
+  UseSidebarWithFormRefResult,
+  useSidebarWithFormRef,
+} from "@/lib/shared/hooks/useSidebarWithFormRef";
+
+export function useAddDocumentSidebar(): UseSidebarWithFormRefResult<AddDocumentSidebarProps> {
+  return useSidebarWithFormRef({ component: AddDocumentSidebar });
+}
+
+interface AddDocumentSidebarProps extends SidebarWithFormRefProps {
+  procedureId: string;
+}
+
+const INITIAL_VALUES: AddDocumentFormValues = {
+  documentTypeDe: "",
+  documentTypeEn: undefined,
+  helpTextDe: "",
+  helpTextEn: undefined,
+  mandatoryDocument: false,
+  uploadInCitizenPortal: false,
+  files: [],
+  note: "",
+  upload: "later",
+};
+
+function AddDocumentSidebar(props: Readonly<AddDocumentSidebarProps>) {
+  const postDocument = usePostDocument();
+
+  async function handleSubmit(values: AddDocumentFormValues) {
+    const request: PostDocumentRequest = {
+      id: props.procedureId,
+      postDocumentRequest: {
+        documentTypeDe: values.documentTypeDe,
+        documentTypeEn: values.documentTypeEn,
+        helpTextDe: values.helpTextDe,
+        helpTextEn: values.helpTextEn,
+        mandatoryDocument: values.mandatoryDocument,
+        uploadInCitizenPortal: values.uploadInCitizenPortal,
+      },
+      files: values.files as Blob[],
+      note: values.note,
+    };
+    await postDocument.mutateAsync(request, {
+      onSuccess: () => {
+        props.onClose(true);
+      },
+    });
+  }
+
+  return (
+    <AddDocumentForm
+      title="Dokument anlegen"
+      onSubmit={handleSubmit}
+      onCancel={props.onClose}
+      formRef={props.formRef}
+      initialValues={INITIAL_VALUES}
+      submitLabel="Anlegen"
+    />
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/Columns.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/Columns.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f10a3a390d1466daadbe4507b03bde405a81fa72
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/Columns.tsx
@@ -0,0 +1,166 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+import {
+  ApiDocument,
+  ApiDocumentStatus,
+} from "@eshg/official-medical-service-api";
+import { Delete, ModeEditOutlineOutlined } from "@mui/icons-material";
+import { Chip } from "@mui/joy";
+import { ColumnHelper, createColumnHelper } from "@tanstack/react-table";
+
+import { statusColorsDocumentStatus } from "@/lib/businessModules/officialMedicalService/shared/constants";
+import { STATUS_NAMES_DOCUMENT_STATUS } from "@/lib/businessModules/officialMedicalService/shared/translations";
+import { ActionsMenu } from "@/lib/shared/components/buttons/ActionsMenu";
+import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
+
+const columnHelper: ColumnHelper<ApiDocument> =
+  createColumnHelper<ApiDocument>();
+
+interface ColumnsProps {
+  onEdit: (document: ApiDocument) => void;
+  onDelete: (document: ApiDocument) => Promise<void>;
+  isProcedureFinalized: () => boolean;
+}
+
+export function Columns({
+  onEdit,
+  onDelete,
+  isProcedureFinalized,
+}: Readonly<ColumnsProps>) {
+  const { openConfirmationDialog } = useConfirmationDialog();
+
+  return [
+    columnHelper.accessor("documentTypeDe", {
+      header: "Dokumentenart",
+      cell: (props) => props.getValue(),
+      enableSorting: true,
+      meta: { canNavigate: { parentRow: true } },
+    }),
+    columnHelper.accessor("helpTextDe", {
+      header: "Hilfstext",
+      cell: (props) => props.getValue(),
+      enableSorting: true,
+      meta: { canNavigate: { parentRow: true } },
+    }),
+    columnHelper.accessor("documentStatus", {
+      header: "Status",
+      cell: (props) => {
+        const status: ApiDocumentStatus = props.getValue();
+        return (
+          <Chip color={statusColorsDocumentStatus[status]} size="md">
+            {STATUS_NAMES_DOCUMENT_STATUS[status]}
+          </Chip>
+        );
+      },
+      enableSorting: true,
+      meta: { canNavigate: { parentRow: true } },
+    }),
+    // ToDo: missing in R4D,
+    // columnHelper.accessor("uploadInCitizenPortal", {
+    //   header: "Upload-Option",
+    //   cell: (props) => {
+    //     return (
+    //       <Chip color="primary" size="md">
+    //         {props.getValue() ? "Mitarbeiter:in" : "Bürger:in"}
+    //       </Chip>
+    //     );
+    //   },
+    //   enableSorting: true,
+    // }),
+    // ToDo: missing attribute in BE "Hochgeladen von"; for now fixed value is displayed
+    // columnHelper.accessor("??", {
+    //   header: "Hochgeladen von",
+    //   cell: (props) => {
+    //     return (
+    //       <Chip color={props.getValue() ? "warning" : "primary"} size="md">
+    //         {props.getValue() ? "Extern" : "Intern"}
+    //       </Chip>
+    //     );
+    //   },
+    //   enableSorting: true,
+    // }),
+    columnHelper.display({
+      header: "Hochgeladen von",
+      cell: () => {
+        return (
+          <Chip color="primary" size="md">
+            Intern
+          </Chip>
+        );
+      },
+      enableSorting: true,
+      meta: { canNavigate: { parentRow: true } },
+    }),
+    columnHelper.accessor("mandatoryDocument", {
+      header: "Pflicht",
+      cell: (props) => {
+        return (
+          <Chip color={props.getValue() ? "danger" : "primary"} size="md">
+            {props.getValue() ? "Ja" : "Nein"}
+          </Chip>
+        );
+      },
+      enableSorting: true,
+      meta: { canNavigate: { parentRow: true } },
+    }),
+    columnHelper.accessor("lastDocumentUpload", {
+      header: "Letzte Aktualisierung",
+      cell: (props) => formatDateTime(props.getValue()),
+      enableSorting: true,
+      meta: { canNavigate: { parentRow: true } },
+    }),
+    columnHelper.accessor("files", {
+      header: "Dateien",
+      cell: (props) => props.getValue()?.length,
+      enableSorting: true,
+      meta: { canNavigate: { parentRow: true } },
+    }),
+    columnHelper.accessor("note", {
+      header: "Stichwörter",
+      cell: (props) => props.getValue(),
+      enableSorting: true,
+      meta: { canNavigate: { parentRow: true } },
+    }),
+    columnHelper.display({
+      header: "Aktionen",
+      cell: (props) => (
+        <ActionsMenu
+          actionItems={[
+            {
+              label: "Bearbeiten",
+              onClick: () => onEdit(props.row.original),
+              startDecorator: <ModeEditOutlineOutlined />,
+            },
+            ...(isProcedureFinalized()
+              ? []
+              : [
+                  {
+                    label: "Löschen",
+                    onClick: () => {
+                      openConfirmationDialog({
+                        title: "Dokument löschen?",
+                        description:
+                          "Möchten Sie das Dokument wirklich löschen? Die Aktion lässt sich nicht widerrufen.",
+                        confirmLabel: "Löschen",
+                        onConfirm: async () => {
+                          await onDelete(props.row.original);
+                        },
+                        color: "danger",
+                      });
+                    },
+                    startDecorator: <Delete color="danger" />,
+                  },
+                ]),
+          ]}
+        />
+      ),
+      meta: {
+        width: 96,
+      },
+    }),
+  ];
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6a7218c73a7ce0f29e2c262249b5a1f0fe313700
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentForm.tsx
@@ -0,0 +1,156 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  ApiDocument,
+  ApiDocumentStatus,
+} from "@eshg/official-medical-service-api";
+import { Formik } from "formik";
+import { Ref } from "react";
+
+import { useReviewDocument } from "@/lib/businessModules/officialMedicalService/api/mutations/omsDocumentApi";
+import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
+import {
+  SidebarForm,
+  SidebarFormHandle,
+} from "@/lib/shared/components/form/SidebarForm";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
+
+import { DocumentFormContent } from "./DocumentFormContent";
+
+export interface DocumentFormValues {
+  documentTypeDe: string;
+  documentTypeEn?: string;
+  helpTextDe?: string;
+  helpTextEn?: string;
+  mandatoryDocument: boolean;
+  uploadInCitizenPortal: boolean;
+  files?: File[];
+  note?: string;
+}
+
+interface DocumentFormProps {
+  initialValues: DocumentFormValues;
+  document: ApiDocument;
+  formRef: Ref<SidebarFormHandle>;
+  onCancel: () => void;
+  onSubmit: (values: DocumentFormValues) => Promise<void>;
+  title: string;
+  submitLabel: string;
+  onEditInformation?: () => void;
+  onEditNote?: () => void;
+  onReject?: () => void;
+  onClose: () => void;
+  isProcedureFinalized: boolean;
+}
+
+export function DocumentForm(props: Readonly<DocumentFormProps>) {
+  const { openConfirmationDialog } = useConfirmationDialog();
+  const { mutateAsync: reviewDocument } = useReviewDocument();
+
+  return (
+    <Formik
+      initialValues={props.initialValues}
+      onSubmit={async (values) => {
+        if (isCompletableWithConfirmation({ ...props, ...values })) {
+          openConfirmationDialog({
+            onConfirm: () => props.onSubmit(values),
+            title: "Datei-Upload abschließen?",
+            confirmLabel: "Abschließen",
+            description:
+              'Wenn Sie fortfahren, wird der Status auf "Akzeptiert" gesetzt und es können keine weiteren Dateien hinzugefügt werden.',
+          });
+        } else if (isCompletableWithoutConfirmation({ ...props, ...values })) {
+          await props.onSubmit(values);
+          props.onClose();
+        } else if (needsReview(props)) {
+          openConfirmationDialog({
+            onConfirm: async () => {
+              await reviewDocument({
+                id: props.document.id,
+                apiPatchDocumentReviewRequest: {
+                  result: ApiDocumentStatus.Accepted,
+                },
+              });
+              props.onClose();
+            },
+            title: "Dokument akzeptieren?",
+            confirmLabel: "Akzeptieren",
+            description:
+              'Wenn Sie fortfahren, wird der Status auf "Akzeptiert" gesetzt und es können keine weiteren Dateien hinzugefügt werden.',
+          });
+        } else {
+          props.onClose();
+        }
+      }}
+      enableReinitialize
+    >
+      {({ isSubmitting, values }) => {
+        const isCompletable =
+          isCompletableWithConfirmation({ ...props, ...values }) ||
+          isCompletableWithoutConfirmation({ ...props, ...values });
+        return (
+          <SidebarForm ref={props.formRef}>
+            <DocumentFormContent {...props} />
+            <SidebarActions>
+              {needsReview(props) ? (
+                <MultiFormButtonBar
+                  onCancel={props.onClose}
+                  onReject={props.onReject}
+                  submitLabel="Akzeptieren"
+                  submitting={isSubmitting}
+                />
+              ) : isCompletable ? (
+                <MultiFormButtonBar
+                  submitLabel="Abschließen"
+                  onCancel={props.onCancel}
+                  submitting={isSubmitting}
+                />
+              ) : (
+                <MultiFormButtonBar
+                  submitLabel={props.submitLabel}
+                  submitting={isSubmitting}
+                />
+              )}
+            </SidebarActions>
+          </SidebarForm>
+        );
+      }}
+    </Formik>
+  );
+}
+
+function needsReview({ document }: { document: ApiDocument }): boolean {
+  return document.documentStatus === ApiDocumentStatus.Submitted;
+}
+
+function isCompletableWithConfirmation({
+  document,
+  files,
+}: {
+  document: ApiDocument;
+  files?: File[];
+}): boolean {
+  return (
+    document.documentStatus !== ApiDocumentStatus.Accepted &&
+    !!files &&
+    files.length > 0
+  );
+}
+
+function isCompletableWithoutConfirmation({
+  document,
+  files,
+}: {
+  document: ApiDocument;
+  files?: File[];
+}): boolean {
+  return (
+    document.documentStatus === ApiDocumentStatus.Rejected &&
+    !!files &&
+    files.length > 0
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentFormContent.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentFormContent.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e927662c90336201f0a4c5125f452674bb97ec5b
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentFormContent.tsx
@@ -0,0 +1,192 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  ApiDocument,
+  ApiDocumentStatus,
+} from "@eshg/official-medical-service-api";
+import { WarningAmber } from "@mui/icons-material";
+import {
+  Alert,
+  Box,
+  Chip,
+  ChipProps,
+  Divider,
+  Stack,
+  Typography,
+} from "@mui/joy";
+import { ReactNode } from "react";
+import { isEmpty } from "remeda";
+
+import { FilesSection } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/FilesSection";
+import { statusColorsDocumentStatus } from "@/lib/businessModules/officialMedicalService/shared/constants";
+import { STATUS_NAMES_DOCUMENT_STATUS } from "@/lib/businessModules/officialMedicalService/shared/translations";
+import { EditButton } from "@/lib/shared/components/buttons/EditButton";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+
+export function DocumentFormContent(props: {
+  title: string;
+  document: ApiDocument;
+  onEditInformation?: () => void;
+  onEditNote?: () => void;
+  isProcedureFinalized: boolean;
+}) {
+  return (
+    <SidebarContent title={props.title}>
+      <Stack rowGap={3}>
+        <Stack
+          gap={3}
+          direction="row"
+          flexWrap="wrap"
+          width={"90%"}
+          data-testid="core-data"
+        >
+          <ChipItem
+            label="Status"
+            color={statusColorsDocumentStatus[props.document.documentStatus]}
+            value={STATUS_NAMES_DOCUMENT_STATUS[props.document.documentStatus]}
+          />
+          <ChipItem
+            label="Pflichtdokument"
+            color={props.document.mandatoryDocument ? "danger" : "neutral"}
+            value={props.document.mandatoryDocument ? "Ja" : "Nein"}
+          />
+          {props.document.documentStatus !== ApiDocumentStatus.Missing && (
+            <ChipItem
+              label="Hochgeladen von"
+              color={
+                props.document.uploadInCitizenPortal ? "warning" : "primary"
+              }
+              value={props.document.uploadInCitizenPortal ? "Extern" : "Intern"}
+            />
+          )}
+          <ChipItem
+            label={"Upload-Option"}
+            color={props.document.uploadInCitizenPortal ? "warning" : "neutral"}
+            value={
+              props.document.uploadInCitizenPortal
+                ? "Intern und Extern"
+                : "Intern"
+            }
+          />
+        </Stack>
+        <Divider orientation="horizontal" />
+        {props.document.documentStatus !== ApiDocumentStatus.Submitted &&
+          props.document.reasonForRejection && (
+            <>
+              <DetailsItem
+                label="Ablehnungsgrund"
+                value={props.document.reasonForRejection}
+                slotProps={{
+                  label: { level: "title-md", textColor: "text.primary" },
+                  value: { level: "body-md" },
+                }}
+              />
+              <Divider orientation="horizontal" />
+            </>
+          )}
+        <Stack gap={2}>
+          <Typography level={"title-md"}>Dateien</Typography>
+          {props.document.documentStatus === ApiDocumentStatus.Submitted &&
+            props.document.reasonForRejection && (
+              <>
+                <Alert color={"warning"} startDecorator={<WarningAmber />}>
+                  Neu hochgeladene Dateien nach Ablehnung
+                </Alert>
+                <DetailsItem
+                  label="Ablehnungsgrund"
+                  value={props.document.reasonForRejection}
+                />
+              </>
+            )}
+          <FilesSection
+            name="files"
+            canAdd={
+              (props.document.documentStatus === ApiDocumentStatus.Missing ||
+                props.document.documentStatus === ApiDocumentStatus.Rejected) &&
+              !props.isProcedureFinalized
+            }
+            withInitialField={false}
+            addLabel="Datei hinzufügen"
+            files={props.document.files}
+          />
+          <Stack
+            direction="row"
+            gap={2}
+            justifyContent="space-between"
+            alignItems="start"
+            data-testid="noteSection"
+          >
+            <DetailsItem
+              label="Stichwörter"
+              value={!isEmpty(props.document.note) ? props.document.note : "-"}
+              slotProps={{ value: { pt: 1 } }}
+            />
+            {!isEmpty(props.document.files) && !props.isProcedureFinalized && (
+              <EditButton
+                aria-label="Stichwörter bearbeiten"
+                onClick={props.onEditNote}
+              />
+            )}
+          </Stack>
+        </Stack>
+
+        <Divider orientation="horizontal" />
+        <Stack direction="column" gap={2} data-testid="additional-info">
+          <Stack direction={"row"} gap={2} justifyContent={"space-between"}>
+            <Typography level="title-md">Dokument-Angaben</Typography>
+            {props.document.documentStatus === ApiDocumentStatus.Missing &&
+              !props.isProcedureFinalized && (
+                <EditButton
+                  aria-label={"Dokument-Angaben bearbeiten"}
+                  onClick={props.onEditInformation}
+                />
+              )}
+          </Stack>
+          <DetailsItem
+            label="Dokumentenart (EN)"
+            value={props.document.documentTypeEn ?? "-"}
+          />
+          <DetailsItem
+            label="Hilfstext"
+            value={
+              !isEmpty(props.document.helpTextDe)
+                ? props.document.helpTextDe
+                : "-"
+            }
+          />
+          <DetailsItem
+            label="Hilfstext (EN)"
+            value={props.document.helpTextEn ?? "-"}
+          />
+        </Stack>
+      </Stack>
+    </SidebarContent>
+  );
+}
+
+function ChipItem({
+  label,
+  color,
+  value,
+}: {
+  label: string;
+  color: ChipProps["color"];
+  value: ReactNode;
+}) {
+  return (
+    <DetailsItem
+      label={label}
+      value={
+        <Chip color={color} size="md">
+          {value}
+        </Chip>
+      }
+      slots={{ value: Box }}
+      slotProps={{ value: { sx: { pt: 1 } } }}
+    />
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentSidebar.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentSidebar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bba40c5c6fff873572a765f2f597e821e68ef89e
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentSidebar.tsx
@@ -0,0 +1,194 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  PatchCompleteDocumentFileUploadRequest,
+  PatchDocumentInformationRequest,
+  PatchDocumentNoteRequest,
+} from "@eshg/official-medical-service-api";
+import { useSuspenseQueries } from "@tanstack/react-query";
+import { useState } from "react";
+
+import {
+  usePatchCompleteDocumentFileUpload,
+  usePatchDocumentInformation,
+  usePatchDocumentNote,
+} from "@/lib/businessModules/officialMedicalService/api/mutations/omsDocumentApi";
+import { useGetAllDocuments } from "@/lib/businessModules/officialMedicalService/api/queries/employeeOmsProcedureApi";
+import {
+  DocumentForm,
+  DocumentFormValues,
+} from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentForm";
+import { EditDocumentInformationForm } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/EditDocumentInformationForm";
+import { EditDocumentNoteForm } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/EditDocumentNoteForm";
+import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
+import {
+  SidebarWithFormRefProps,
+  UseSidebarWithFormRefResult,
+  useSidebarWithFormRef,
+} from "@/lib/shared/hooks/useSidebarWithFormRef";
+
+import { RejectDocumentForm } from "./RejectDocumentForm";
+
+export function useDocumentSidebar(): UseSidebarWithFormRefResult<DocumentSidebarProps> {
+  return useSidebarWithFormRef({ component: DocumentSidebar });
+}
+
+interface DocumentSidebarProps extends SidebarWithFormRefProps {
+  procedureId: string;
+  documentId: string;
+  isProcedureFinalized: boolean;
+}
+
+export enum DocumentSidebarMode {
+  default,
+  editInformation,
+  editNote,
+  reject,
+}
+
+function DocumentSidebar({
+  documentId,
+  procedureId,
+  isProcedureFinalized,
+  ...props
+}: Readonly<DocumentSidebarProps>) {
+  const patchCompleteDocumentFileUpload = usePatchCompleteDocumentFileUpload();
+  const patchDocumentInformation = usePatchDocumentInformation();
+  const patchDocumentNote = usePatchDocumentNote();
+  const { openCancelDialog } = useConfirmationDialog();
+
+  const [{ data: allDocuments }] = useSuspenseQueries({
+    queries: [useGetAllDocuments(procedureId)],
+  });
+  const document = allDocuments.find((doc) => doc.id === documentId)!;
+
+  const [mode, setMode] = useState<DocumentSidebarMode>(
+    DocumentSidebarMode.default,
+  );
+
+  async function handleDocumentSubmit(values: DocumentFormValues) {
+    const request: PatchCompleteDocumentFileUploadRequest = {
+      id: document.id,
+      files: values.files as Blob[],
+    };
+
+    await patchCompleteDocumentFileUpload.mutateAsync(request, {
+      onSuccess: () => {
+        props.onClose(true);
+      },
+    });
+  }
+
+  async function handleEditInformation(values: DocumentFormValues) {
+    const request: PatchDocumentInformationRequest = {
+      id: document.id,
+      apiPatchDocumentInformationRequest: {
+        documentTypeDe: values.documentTypeDe,
+        documentTypeEn: values.documentTypeEn,
+        helpTextDe: values.helpTextDe,
+        helpTextEn: values.helpTextEn,
+        mandatoryDocument: values.mandatoryDocument,
+        uploadInCitizenPortal: values.uploadInCitizenPortal,
+      },
+    };
+
+    await patchDocumentInformation.mutateAsync(request, {
+      onSuccess: () => {
+        setMode(DocumentSidebarMode.default);
+      },
+    });
+  }
+
+  async function handleEditNote(values: DocumentFormValues) {
+    const request: PatchDocumentNoteRequest = {
+      id: document.id,
+      apiPatchDocumentNoteRequest: {
+        note: values.note,
+      },
+    };
+
+    await patchDocumentNote.mutateAsync(request, {
+      onSuccess: () => {
+        setMode(DocumentSidebarMode.default);
+      },
+    });
+  }
+
+  function handleCancel() {
+    openCancelDialog({
+      onConfirm: () => {
+        props.onClose(true);
+      },
+      confirmLabel: "Verwerfen",
+      title: "Hochgeladene Dateien verwerfen?",
+      description:
+        "Wenn Sie fortfahren, werden die von Ihnen hochgeladenen Dateien  nicht gespeichert.",
+    });
+  }
+
+  const INITIAL_VALUES: DocumentFormValues = {
+    documentTypeDe: document.documentTypeDe,
+    documentTypeEn: document.documentTypeEn ?? "",
+    helpTextDe: document.helpTextDe ?? "",
+    helpTextEn: document.helpTextEn ?? "",
+    mandatoryDocument: document.mandatoryDocument,
+    uploadInCitizenPortal: document.uploadInCitizenPortal,
+    files: [],
+    note: document.note ?? "",
+  };
+
+  return (
+    <>
+      {mode === DocumentSidebarMode.default && (
+        <DocumentForm
+          title={document.documentTypeDe}
+          onSubmit={handleDocumentSubmit}
+          onCancel={handleCancel}
+          onClose={props.onClose}
+          onEditInformation={() => setMode(DocumentSidebarMode.editInformation)}
+          onEditNote={() => setMode(DocumentSidebarMode.editNote)}
+          onReject={() => setMode(DocumentSidebarMode.reject)}
+          formRef={props.formRef}
+          initialValues={INITIAL_VALUES}
+          document={document}
+          submitLabel="Schließen"
+          isProcedureFinalized={isProcedureFinalized}
+        />
+      )}
+      {mode === DocumentSidebarMode.editInformation && (
+        <EditDocumentInformationForm
+          title="Angaben bearbeiten"
+          onSubmit={handleEditInformation}
+          onCancel={() => {
+            setMode(DocumentSidebarMode.default);
+          }}
+          formRef={props.formRef}
+          initialValues={INITIAL_VALUES}
+          submitLabel="Speichern"
+        />
+      )}
+      {mode === DocumentSidebarMode.editNote && (
+        <EditDocumentNoteForm
+          title="Stichwörter bearbeiten"
+          onSubmit={handleEditNote}
+          onCancel={() => {
+            setMode(DocumentSidebarMode.default);
+          }}
+          formRef={props.formRef}
+          initialValues={INITIAL_VALUES}
+          submitLabel="Speichern"
+        />
+      )}
+      {mode === DocumentSidebarMode.reject && (
+        <RejectDocumentForm
+          onClose={props.onClose}
+          formRef={props.formRef}
+          document={document}
+        />
+      )}
+    </>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentsTable.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentsTable.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..9d780fd74c8cc977ad4bef617ca3a737a3d090b3
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentsTable.tsx
@@ -0,0 +1,136 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+"use client";
+
+import { ApiDocument } from "@eshg/official-medical-service-api";
+import { AddOutlined, DescriptionOutlined } from "@mui/icons-material";
+import { Button, Stack, Typography } from "@mui/joy";
+import { useSuspenseQueries } from "@tanstack/react-query";
+
+import { useDeleteDocument } from "@/lib/businessModules/officialMedicalService/api/mutations/omsDocumentApi";
+import {
+  useGetAllDocuments,
+  useGetProcedureDetails,
+} from "@/lib/businessModules/officialMedicalService/api/queries/employeeOmsProcedureApi";
+import { useAddDocumentSidebar } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentSidebar";
+import { Columns } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/Columns";
+import { useDocumentSidebar } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentSidebar";
+import { isProcedureFinalized } from "@/lib/businessModules/officialMedicalService/shared/helpers";
+import { TableTitle } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/TableTitle";
+import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
+import { DataTable } from "@/lib/shared/components/table/DataTable";
+import { TablePage } from "@/lib/shared/components/table/TablePage";
+import { TableSheet } from "@/lib/shared/components/table/TableSheet";
+
+interface DocumentsTableProps {
+  procedureId: string;
+}
+
+export function DocumentsTable({ procedureId }: Readonly<DocumentsTableProps>) {
+  const addDocumentSidebar = useAddDocumentSidebar();
+  const documentSidebar = useDocumentSidebar();
+  const [{ data: allDocuments }, { data: procedureDetails }] =
+    useSuspenseQueries({
+      queries: [
+        useGetAllDocuments(procedureId),
+        useGetProcedureDetails(procedureId),
+      ],
+    });
+  const deleteDocument = useDeleteDocument();
+
+  return (
+    <TablePage
+      fullHeight
+      controls={
+        !isProcedureFinalized(procedureDetails) && (
+          <ButtonBar
+            right={
+              <Button
+                endDecorator={<AddOutlined />}
+                onClick={() => addDocumentSidebar.open({ procedureId })}
+                aria-label="Dokument hinzufügen"
+              >
+                Dokument hinzufügen
+              </Button>
+            }
+            alignItems="flex-end"
+          />
+        )
+      }
+    >
+      <TableSheet title={<TableTitle title="Dokumente" />}>
+        <DataTable
+          data={allDocuments}
+          columns={Columns({
+            onEdit: (document: ApiDocument) => {
+              documentSidebar.open({
+                documentId: document.id,
+                procedureId: procedureId,
+                isProcedureFinalized: isProcedureFinalized(procedureDetails),
+              });
+            },
+            onDelete: async (document: ApiDocument) => {
+              await deleteDocument.mutateAsync(document.id);
+            },
+            isProcedureFinalized: () => {
+              return isProcedureFinalized(procedureDetails);
+            },
+          })}
+          rowNavigation={{
+            onClick: (row) => () => {
+              documentSidebar.open({
+                documentId: row.original.id,
+                procedureId: procedureId,
+                isProcedureFinalized: isProcedureFinalized(procedureDetails),
+              });
+            },
+            focusColumnAccessorKey: "documentTypeDe",
+          }}
+          noDataComponent={() => (
+            <NoDocumentsAvailable
+              onAdd={() => addDocumentSidebar.open({ procedureId })}
+              isProcedureFinalized={isProcedureFinalized(procedureDetails)}
+            />
+          )}
+        />
+      </TableSheet>
+    </TablePage>
+  );
+}
+
+interface NoDocumentsAvailableProps {
+  onAdd?: () => void;
+  isProcedureFinalized: boolean;
+}
+
+function NoDocumentsAvailable({
+  onAdd,
+  isProcedureFinalized,
+}: Readonly<NoDocumentsAvailableProps>) {
+  return (
+    <Stack
+      sx={{
+        alignItems: "center",
+        justifyContent: "center",
+        flex: 1,
+      }}
+    >
+      <DescriptionOutlined sx={{ height: "40px", width: "40px" }} />
+      <Typography sx={{ mt: 2, mb: 3 }}>
+        Noch keine Dokumente hinzugefügt
+      </Typography>
+      {!isProcedureFinalized && (
+        <Button
+          endDecorator={<AddOutlined />}
+          onClick={onAdd}
+          aria-label="Dokument hinzufügen"
+        >
+          Dokument hinzufügen
+        </Button>
+      )}
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/EditDocumentInformationForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/EditDocumentInformationForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b70658293b1bcc184a2d787c82832355d92ffd65
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/EditDocumentInformationForm.tsx
@@ -0,0 +1,88 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
+import { Stack } from "@mui/joy";
+import { Formik } from "formik";
+import { Ref } from "react";
+
+import { theme } from "@/lib/baseModule/theme/theme";
+import { DocumentFormValues } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentForm";
+import { SwitchField } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/SwitchField";
+import { HorizontalFieldLabelEnd } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/shared/HorizontalFieldLabelEnd";
+import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
+import {
+  SidebarForm,
+  SidebarFormHandle,
+} from "@/lib/shared/components/form/SidebarForm";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+
+interface EditDocumentInformationFormProps {
+  initialValues: DocumentFormValues;
+  formRef: Ref<SidebarFormHandle>;
+  onCancel: () => void;
+  onSubmit: (values: DocumentFormValues) => Promise<void>;
+  title: string;
+  submitLabel: string;
+}
+
+export function EditDocumentInformationForm(
+  props: Readonly<EditDocumentInformationFormProps>,
+) {
+  return (
+    <Formik
+      initialValues={props.initialValues}
+      onSubmit={props.onSubmit}
+      enableReinitialize
+    >
+      {({ isSubmitting }) => (
+        <SidebarForm ref={props.formRef}>
+          <SidebarContent title={props.title}>
+            <Stack gap={2} rowGap={2}>
+              <SwitchField
+                name="mandatoryDocument"
+                label="Pflichtdokument"
+                sx={{
+                  ".MuiFormLabel-root": {
+                    fontSize: theme.typography["body-md"].fontSize,
+                    fontWeight: theme.typography["body-md"].fontWeight,
+                  },
+                }}
+                component={HorizontalFieldLabelEnd}
+              />
+              <SwitchField
+                name="uploadInCitizenPortal"
+                label="Upload durch Bürger:in"
+                sx={{
+                  ".MuiFormLabel-root": {
+                    fontSize: theme.typography["body-md"].fontSize,
+                    fontWeight: theme.typography["body-md"].fontWeight,
+                  },
+                }}
+                component={HorizontalFieldLabelEnd}
+              />
+              <InputField
+                name="documentTypeDe"
+                label="Dokumentenart"
+                required="Bitte geben Sie eine Dokumentenart an"
+              />
+              <InputField name="documentTypeEn" label="Dokumentenart (EN)" />
+              <InputField name="helpTextDe" label="Hilfstext" />
+              <InputField name="helpTextEn" label="Hilfstext (EN)" />
+            </Stack>
+          </SidebarContent>
+          <SidebarActions>
+            <MultiFormButtonBar
+              submitLabel={props.submitLabel}
+              submitting={isSubmitting}
+              onCancel={props.onCancel}
+            />
+          </SidebarActions>
+        </SidebarForm>
+      )}
+    </Formik>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/EditDocumentNoteForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/EditDocumentNoteForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..09687311237e504260da81db0d5d4a3a1268ba43
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/EditDocumentNoteForm.tsx
@@ -0,0 +1,55 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
+import { Stack } from "@mui/joy";
+import { Formik } from "formik";
+import { Ref } from "react";
+
+import { DocumentFormValues } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentForm";
+import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
+import {
+  SidebarForm,
+  SidebarFormHandle,
+} from "@/lib/shared/components/form/SidebarForm";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+
+interface EditDocumentNoteFormProps {
+  initialValues: DocumentFormValues;
+  formRef: Ref<SidebarFormHandle>;
+  onCancel: () => void;
+  onSubmit: (values: DocumentFormValues) => Promise<void>;
+  title: string;
+  submitLabel: string;
+}
+export function EditDocumentNoteForm(
+  props: Readonly<EditDocumentNoteFormProps>,
+) {
+  return (
+    <Formik
+      initialValues={props.initialValues}
+      onSubmit={props.onSubmit}
+      enableReinitialize
+    >
+      {({ isSubmitting }) => (
+        <SidebarForm ref={props.formRef}>
+          <SidebarContent title={props.title}>
+            <Stack gap={2} rowGap={2}>
+              <InputField name="note" label="Stichwörter" />
+            </Stack>
+          </SidebarContent>
+          <SidebarActions>
+            <MultiFormButtonBar
+              submitLabel={props.submitLabel}
+              submitting={isSubmitting}
+              onCancel={props.onCancel}
+            />
+          </SidebarActions>
+        </SidebarForm>
+      )}
+    </Formik>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/FilesSection.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/FilesSection.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f56d35281d5198b67426a32e0159d11ea3587e87
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/FilesSection.tsx
@@ -0,0 +1,143 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { useFileDownload } from "@eshg/lib-portal/api/files/download";
+import { FormAddMoreButton } from "@eshg/lib-portal/components/form/FormAddMoreButton";
+import { FileType } from "@eshg/lib-portal/components/formFields/file/FileType";
+import { ApiFileType } from "@eshg/lib-procedures-api";
+import { ApiOmsFile } from "@eshg/official-medical-service-api";
+import { Delete, FileDownloadOutlined } from "@mui/icons-material";
+import { Stack } from "@mui/joy";
+import { useFormikContext } from "formik";
+import { isDefined } from "remeda";
+
+import { useOmsFileApi } from "@/lib/businessModules/officialMedicalService/api/clients";
+import { AddDocumentFormValues } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/AddDocumentForm";
+import { DocumentFormValues } from "@/lib/businessModules/officialMedicalService/components/procedures/details/documents/DocumentForm";
+import { FileCard } from "@/lib/shared/components/FileCard";
+import { FileField } from "@/lib/shared/components/formFields/file/FileField";
+import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
+import { useToggle } from "@/lib/shared/hooks/useToggle";
+
+interface FilesSectionProps {
+  name: string;
+  canAdd: boolean;
+  withInitialField: boolean;
+  addLabel?: string;
+  files?: ApiOmsFile[];
+}
+
+export function FilesSection(props: Readonly<FilesSectionProps>) {
+  const [active, toggleActive] = useToggle(props.withInitialField);
+  const { openCancelDialog } = useConfirmationDialog();
+
+  const { setFieldValue, setFieldTouched, values } = useFormikContext<
+    AddDocumentFormValues | DocumentFormValues
+  >();
+
+  const omsFileApi = useOmsFileApi();
+
+  const { download } = useFileDownload((fileId: string) =>
+    omsFileApi.getDownloadFileRaw({ fileId }),
+  );
+
+  return (
+    <Stack gap={2} data-testid="files">
+      <Stack gap={1}>
+        {props.canAdd &&
+          isDefined(values.files) &&
+          values.files.length >= 1 &&
+          values.files.map((file, index) => (
+            <FileCard
+              key={`${file.name}.${index}`}
+              name={file.name}
+              type={file.type.split("/").pop()?.toUpperCase() as ApiFileType}
+              creationDate={new Date(file.lastModified)}
+              size={file.size}
+              actions={[
+                {
+                  onClick: () => {
+                    openCancelDialog({
+                      onConfirm: async () => {
+                        const newArr = isDefined(values.files)
+                          ? values.files.filter((i) => i !== file)
+                          : [];
+                        if (newArr.length === 0) {
+                          await setFieldTouched("files", false, false);
+                          toggleActive();
+                        }
+                        await setFieldValue("files", newArr, false);
+                      },
+                      confirmLabel: "Löschen",
+                      title: "Datei wirklich löschen?",
+                      description:
+                        "Möchten Sie die Datei wirklich löschen? Die Aktion kann nicht rückgängig gemacht werden.",
+                    });
+                  },
+                  indicator: <Delete color="danger" />,
+                  color: "primary",
+                  name: "Löschen",
+                },
+              ]}
+            />
+          ))}
+        {isDefined(props.files) &&
+          props.files.map((file) => (
+            <FileCard
+              key={file.id}
+              name={file.name}
+              type={file.fileType as ApiFileType}
+              creationDate={file.creationDate}
+              size={file.size}
+              actions={[
+                {
+                  onClick: () => download(file.id),
+                  indicator: <FileDownloadOutlined />,
+                  color: "primary",
+                  name: "Herunterladen",
+                },
+                // ToDo: @saschl what about preview?
+                // {
+                //   onClick: () => preview(file.id),
+                //   indicator: <DeleteOutlined />,
+                //   color: "warning",
+                //   name: "Preview",
+                // },);
+              ]}
+            />
+          ))}
+      </Stack>
+      {props.canAdd && (
+        <>
+          {active && (
+            // ToDo: Bug in FileField validation? filetype validation runs via drag and drop only
+            <FileField
+              label="Datei hochladen (PDF, JPG oder PNG)"
+              name="files"
+              placeholder="Auswählen"
+              accept={[FileType.Pdf, FileType.Jpeg, FileType.Png]}
+              onChange={async (value) => {
+                await setFieldTouched("files", true, false);
+                await setFieldValue(
+                  props.name,
+                  [...values.files!, value],
+                  false,
+                );
+                toggleActive();
+              }}
+            />
+          )}
+          <FormAddMoreButton
+            onClick={() => {
+              toggleActive();
+            }}
+          >
+            {props.addLabel}
+          </FormAddMoreButton>
+        </>
+      )}
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/RejectDocumentForm.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/RejectDocumentForm.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..646a3cad16aa96ca3a4104318ec497f53a88a713
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/RejectDocumentForm.tsx
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  ApiDocument,
+  ApiReviewResult,
+} from "@eshg/official-medical-service-api";
+import { WarningAmber } from "@mui/icons-material";
+import { Alert, Stack } from "@mui/joy";
+import { Formik } from "formik";
+import { Ref } from "react";
+
+import { useReviewDocument } from "@/lib/businessModules/officialMedicalService/api/mutations/omsDocumentApi";
+import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
+import {
+  SidebarForm,
+  SidebarFormHandle,
+} from "@/lib/shared/components/form/SidebarForm";
+import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+
+interface RejectDocumentFormProps {
+  document: ApiDocument;
+  formRef: Ref<SidebarFormHandle>;
+  onClose: (force?: boolean) => void;
+}
+
+export function RejectDocumentForm({
+  document,
+  formRef,
+  onClose,
+}: Readonly<RejectDocumentFormProps>) {
+  const { mutateAsync: reviewDocument } = useReviewDocument();
+
+  return (
+    <Formik
+      initialValues={{ reasonForRejection: document.reasonForRejection }}
+      onSubmit={async (values) => {
+        await reviewDocument({
+          id: document.id,
+          apiPatchDocumentReviewRequest: {
+            result: ApiReviewResult.Rejected,
+            reasonForRejection: values.reasonForRejection,
+          },
+        });
+        onClose(true);
+      }}
+      enableReinitialize
+    >
+      {({ isSubmitting }) => (
+        <SidebarForm ref={formRef}>
+          <SidebarContent title="Dokument ablehnen">
+            <Stack gap={2} rowGap={2}>
+              <Alert color={"warning"} startDecorator={<WarningAmber />}>
+                Bei Ablehnung werden die Dateien dauerhaft gelöscht.
+              </Alert>
+              <TextareaField
+                name="reasonForRejection"
+                label="Ablehnungsgrund"
+                required="Bitte geben Sie einen Ablehnungsgrund an"
+              />
+            </Stack>
+          </SidebarContent>
+          <SidebarActions>
+            <MultiFormButtonBar
+              submitLabel="Ablehnen"
+              submitting={isSubmitting}
+              onCancel={onClose}
+            />
+          </SidebarActions>
+        </SidebarForm>
+      )}
+    </Formik>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/SwitchField.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/SwitchField.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..542887abe1cd5f6535a9fe72bb6549661884708b
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/details/documents/SwitchField.tsx
@@ -0,0 +1,49 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  BaseField,
+  FieldComponentProps,
+  useBaseField,
+} from "@eshg/lib-portal/components/formFields/BaseField";
+import { FieldProps } from "@eshg/lib-portal/types/form";
+import { Switch } from "@mui/joy";
+import { SxProps } from "@mui/joy/styles/types";
+
+// ToDo: @saschl replace old field or rename
+interface SwitchFieldProps extends FieldProps<boolean>, FieldComponentProps {
+  sx?: SxProps;
+}
+
+export function SwitchField(props: SwitchFieldProps) {
+  const FieldComponent = props.component ?? BaseField;
+  const field = useBaseField<boolean>(props);
+
+  return (
+    <FieldComponent
+      label={props.label}
+      helperText={field.helperText}
+      required={field.required}
+      error={field.error}
+      sx={{
+        display: "flex",
+        flexDirection: "row",
+        justifyContent: "space-between",
+        ...props.sx,
+      }}
+    >
+      <Switch
+        checked={field.input.value}
+        onChange={(checked) => field.helpers.setValue(checked.target.checked)}
+        sx={{
+          "--Switch-trackRadius": "16px",
+          "--Switch-trackHeight": "24px",
+          "--Switch-trackWidth": "49px",
+          "--Switch-thumbSize": "16px",
+        }}
+      />
+    </FieldComponent>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/CreateProcedure.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/CreateProcedure.tsx
index 8781a097a2c8ab5b207007b025d72a0a510e900d..d947e0a5ee035781f22259bd93337aeade74404e 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/CreateProcedure.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/CreateProcedure.tsx
@@ -6,7 +6,7 @@
 "use client";
 
 import { ApiGetReferencePersonResponse } from "@eshg/base-api";
-import { ApiPostEmployeeOmsProcedureRequest } from "@eshg/employee-portal-api/officialMedicalService";
+import { ApiPostEmployeeOmsProcedureRequest } from "@eshg/official-medical-service-api";
 import { Add } from "@mui/icons-material";
 import { Button } from "@mui/joy";
 import { useRouter } from "next/navigation";
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/ProceduresOverviewTable.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/ProceduresOverviewTable.tsx
index 6712e03e8692d68bc23614eb5c59f541a24fde74..cfde956921b80bd0e3d6d0ec16d6805176324690 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/ProceduresOverviewTable.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/ProceduresOverviewTable.tsx
@@ -5,10 +5,10 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
-import { GetAllEmployeeProceduresRequest } from "@eshg/employee-portal-api/officialMedicalService";
 import { optionsFromRecord } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import { useToggleableState } from "@eshg/lib-portal/hooks/useToggleableState";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
+import { GetAllEmployeeProceduresRequest } from "@eshg/official-medical-service-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { ColumnSort } from "@tanstack/react-table";
 import { ReactNode, useMemo, useState } from "react";
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/procedureOverviewColumns.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/procedureOverviewColumns.tsx
index e4fdb8e6f5eced739562246e86248dbabf17e98c..b5403e3f97757cb7f7dbfacbc6991a2f9b01ec52 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/procedureOverviewColumns.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/procedures/overview/procedureOverviewColumns.tsx
@@ -3,13 +3,15 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiEmployeeOmsProcedureOverview } from "@eshg/employee-portal-api/officialMedicalService";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiEmployeeOmsProcedureOverview } from "@eshg/official-medical-service-api";
 import { WarningAmberOutlined } from "@mui/icons-material";
 import { Chip, Tooltip } from "@mui/joy";
 import { ColumnHelper, createColumnHelper } from "@tanstack/react-table";
 
+import { statusColorsMedicalOpinionStatus } from "@/lib/businessModules/officialMedicalService/shared/constants";
+import { STATUS_NAMES_MEDICAL_OPINION_STATUS } from "@/lib/businessModules/officialMedicalService/shared/translations";
 import {
   procedureStatusNames,
   statusColors,
@@ -110,6 +112,24 @@ export function procedureOverviewTableColumns() {
         },
       },
     }),
+    columnHelper.accessor("medicalOpinionStatus", {
+      header: "Gutachten Status",
+      cell: (props) => (
+        <Chip
+          color={statusColorsMedicalOpinionStatus[props.getValue()]}
+          size="md"
+        >
+          {STATUS_NAMES_MEDICAL_OPINION_STATUS[props.getValue()]}
+        </Chip>
+      ),
+      enableSorting: true,
+      meta: {
+        width: 120,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
     columnHelper.accessor("nextAppointment", {
       header: "Nächster Termin",
       cell: (props) => formatDateTime(props.getValue()),
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/waitingRoom/WaitingRoomTable.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/waitingRoom/WaitingRoomTable.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..260fb779ea57c08884cb3013f974887200af6589
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/waitingRoom/WaitingRoomTable.tsx
@@ -0,0 +1,92 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+"use client";
+
+import { ApiWaitingRoomSortKey } from "@eshg/official-medical-service-api";
+import { ColumnSort } from "@tanstack/react-table";
+
+import { useGetWaitingRoomProcedures } from "@/lib/businessModules/officialMedicalService/api/queries/waitingRoomApi";
+import { waitingRoomColumns } from "@/lib/businessModules/officialMedicalService/components/waitingRoom/waitingRoomColumns";
+import { routes } from "@/lib/businessModules/officialMedicalService/shared/routes";
+import { Pagination } from "@/lib/shared/components/pagination/Pagination";
+import { DataTable } from "@/lib/shared/components/table/DataTable";
+import { TablePage } from "@/lib/shared/components/table/TablePage";
+import { TableSheet } from "@/lib/shared/components/table/TableSheet";
+import { getSortDirection } from "@/lib/shared/components/table/sorting";
+import {
+  CustomSortingProps,
+  useTableControl,
+} from "@/lib/shared/hooks/searchParams/useTableControl";
+
+const initialSorting: ColumnSort = {
+  id: "modifiedAt",
+  desc: true,
+};
+
+export function WaitingRoomTable() {
+  const tableControl = useTableControl({
+    serverSideSorting: true,
+    sortFieldName: "sortKey",
+    sortDirectionName: "sortDirection",
+    initialSorting: initialSorting,
+  });
+
+  const procedures = useGetWaitingRoomProcedures({
+    pageNumber: tableControl.paginationProps.pageNumber,
+    pageSize: tableControl.paginationProps.pageSize,
+    sortKey: getSortKey(tableControl.tableSorting),
+    sortDirection: getSortDirection(tableControl.tableSorting),
+  });
+
+  return (
+    <TablePage fullHeight data-testid="waiting-room-table">
+      <TableSheet
+        loading={procedures.isFetching}
+        footer={
+          <Pagination
+            totalCount={procedures.data.totalNumberOfElements}
+            {...tableControl.paginationProps}
+          />
+        }
+      >
+        <DataTable
+          data={procedures.data.elements}
+          columns={waitingRoomColumns()}
+          sorting={tableControl.tableSorting}
+          enableSortingRemoval={false}
+          rowNavigation={{
+            route: (row) => routes.procedures.byId(row.original.id).details,
+            focusColumnAccessorKey: "lastName",
+          }}
+          minWidth={1200}
+        ></DataTable>
+      </TableSheet>
+    </TablePage>
+  );
+}
+
+const SORT_KEY_MAPPING: Record<string, ApiWaitingRoomSortKey> = {
+  firstName: ApiWaitingRoomSortKey.Firstname,
+  lastName: ApiWaitingRoomSortKey.Lastname,
+  dateOfBirth: ApiWaitingRoomSortKey.DateOfBirth,
+  facilityName: ApiWaitingRoomSortKey.Facility,
+  physicianName: ApiWaitingRoomSortKey.Physician,
+  waitingRoom_info: ApiWaitingRoomSortKey.Info,
+  waitingRoom_status: ApiWaitingRoomSortKey.Status,
+  modifiedAt: ApiWaitingRoomSortKey.ModifiedAt,
+};
+
+function getSortKey(
+  sortingProps: CustomSortingProps,
+): ApiWaitingRoomSortKey | undefined {
+  const sorting = sortingProps.manualSorting
+    ? sortingProps.sortingState
+    : sortingProps.initialSorting;
+  if (sorting?.[0] === undefined) return undefined;
+
+  const columnId = sorting[0].id;
+  return SORT_KEY_MAPPING[columnId];
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/components/waitingRoom/waitingRoomColumns.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/components/waitingRoom/waitingRoomColumns.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..57bfd368c83b8e607c496fc082fdf62521dcad44
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/components/waitingRoom/waitingRoomColumns.tsx
@@ -0,0 +1,113 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiWaitingRoomProcedure } from "@eshg/official-medical-service-api";
+import { Chip } from "@mui/joy";
+import { ColumnHelper, createColumnHelper } from "@tanstack/react-table";
+
+import { statusColorsWaitingStatus } from "@/lib/businessModules/officialMedicalService/shared/constants";
+import { WAITING_STATUS_VALUES } from "@/lib/businessModules/officialMedicalService/shared/translations";
+import { formatDateTimeRangeToNow } from "@/lib/shared/helpers/dateTime";
+
+const columnHelper: ColumnHelper<ApiWaitingRoomProcedure> =
+  createColumnHelper<ApiWaitingRoomProcedure>();
+
+export function waitingRoomColumns() {
+  return [
+    columnHelper.accessor("firstName", {
+      header: "Vorname",
+      cell: (props) => props.getValue(),
+      enableSorting: true,
+      meta: {
+        width: 180,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("lastName", {
+      header: "Nachname",
+      cell: (props) => props.getValue(),
+      enableSorting: true,
+      meta: {
+        width: 180,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("dateOfBirth", {
+      header: "Geburtsdatum",
+      cell: (props) => formatDate(props.getValue()),
+      enableSorting: true,
+      meta: {
+        width: 160,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("facilityName", {
+      header: "Auftraggeber",
+      cell: (props) => props.getValue(),
+      enableSorting: true,
+      meta: {
+        width: 250,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("physicianName", {
+      header: "Ärzt:in",
+      cell: (props) => props.getValue(),
+      enableSorting: true,
+      meta: {
+        width: 180,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("waitingRoom.status", {
+      header: "Wartezimmer Status",
+      cell: (props) => (
+        <Chip color={statusColorsWaitingStatus[props.getValue()!]} size="md">
+          {WAITING_STATUS_VALUES[props.getValue()!]}
+        </Chip>
+      ),
+      enableSorting: true,
+      meta: {
+        width: 200,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("waitingRoom.info", {
+      header: "Info",
+      cell: (props) => props.getValue(),
+      enableSorting: true,
+      meta: {
+        width: 200,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("modifiedAt", {
+      header: "Seit",
+      cell: (props) => formatDateTimeRangeToNow(props.getValue()),
+      enableSorting: true,
+      meta: {
+        width: 120,
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+  ];
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/shared/DetailsCellInlineEdit.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/shared/DetailsItemInlineEdit.tsx
similarity index 50%
rename from employee-portal/src/lib/businessModules/officialMedicalService/shared/DetailsCellInlineEdit.tsx
rename to employee-portal/src/lib/businessModules/officialMedicalService/shared/DetailsItemInlineEdit.tsx
index 50ed529e4279aead6628730797606e984f7c8962..04fa02b71579084536a98cda5b34d42c8c5983c1 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/shared/DetailsCellInlineEdit.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/shared/DetailsItemInlineEdit.tsx
@@ -7,15 +7,16 @@ import { Stack } from "@mui/joy";
 import { ReactNode } from "react";
 
 import {
-  DetailsCell,
-  DetailsCellProps,
-} from "@/lib/shared/components/detailsSection/DetailsCell";
+  DetailsItem,
+  DetailsItemProps,
+} from "@/lib/shared/components/detailsSection/items/DetailsItem";
 
-interface DetailsCellInlineEditProps extends DetailsCellProps {
+interface DetailsItemInlineEditProps<TLabelProps, TValueProps>
+  extends DetailsItemProps<TLabelProps, TValueProps> {
   renderEditButton?: ReactNode;
 }
-export function DetailsCellInlineEdit(
-  props: Readonly<DetailsCellInlineEditProps>,
+export function DetailsItemInlineEdit<TLabelProps, TValueProps>(
+  props: Readonly<DetailsItemInlineEditProps<TLabelProps, TValueProps>>,
 ) {
   return (
     <Stack
@@ -27,7 +28,7 @@ export function DetailsCellInlineEdit(
       }}
       width={"100%"}
     >
-      <DetailsCell name={props.name} label={props.label} value={props.value} />
+      <DetailsItem label={props.label} value={props.value} />
       {props.renderEditButton}
     </Stack>
   );
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/shared/constants.ts b/employee-portal/src/lib/businessModules/officialMedicalService/shared/constants.ts
index 7bb25e0a5d5c08c83cd855915c0c7bfdb478d42e..8f6c7c000c1f16d3905245a354d7fe1580286c0f 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/shared/constants.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/shared/constants.ts
@@ -3,10 +3,51 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import {
+  ApiDocumentStatus,
+  ApiMedicalOpinionStatus,
+  ApiWaitingStatus,
+} from "@eshg/official-medical-service-api";
+import { ChipProps } from "@mui/joy";
+
 export const systemProgressEntryTypeTitles: Record<string, string> = {
   UPDATE_AFFECTED_PERSON: "Geänderte Personendaten übernommen",
   SYNC_AFFECTED_PERSON: "Geänderte Personendaten synchronisiert",
   SYNC_FACILITY: "Geänderte Auftraggeberdaten übernommen",
   PHYSICIAN_CHANGED: "Geänderte(r) Ärzt:in übernommen",
   PROCEDURE_STARTED: "Vorgang gestartet",
+  DOCUMENT_DELETED: "Dokument gelöscht",
+  APPOINTMENT_FOR_SELF_BOOKING_ADDED: "Selbstbucheroption hinzugefügt",
+  APPOINTMENT_ADDED_WITH_BOOKING: "Termin mit Buchung hinzugefügt",
+  APPOINTMENT_BOOKED: "Termin gebucht",
+  APPOINTMENT_REBOOKED: "Termin geändert",
+  APPOINTMENT_CANCELED: "Termin abgesagt",
+  APPOINTMENT_OPTION_WITHDRAWN: "Terminoption zurückgezogen",
+  APPOINTMENT_CLOSED: "Termin wurde geschlossen",
+  DOCUMENT_MISSING_BY_CITIZEN:
+    "Dokument hinzugefügt mit Upload durch Bürger:In Option",
+  DOCUMENT_MISSING_BY_EMPLOYEE: "Dokument hinzugefügt mit Upload später Option",
+  DOCUMENT_ACCEPTED: "Dokument hinzugefügt mit Dateien",
+  DOCUMENT_INFORMATION_CHANGED:
+    "Dokument bearbeitet mit Änderung Dokumentenart und/oder Hilfstext",
+  DOCUMENT_STATUS_CHANGE_ACCEPTED:
+    "Dokument von “Fehlt”  nach “Akzeptiert” (Upload durch MA)",
 };
+
+export const statusColorsDocumentStatus = {
+  [ApiDocumentStatus.Accepted]: "success",
+  [ApiDocumentStatus.Missing]: "danger",
+  [ApiDocumentStatus.Rejected]: "danger",
+  [ApiDocumentStatus.Submitted]: "warning",
+} satisfies Record<ApiDocumentStatus, ChipProps["color"]>;
+
+export const statusColorsMedicalOpinionStatus = {
+  [ApiMedicalOpinionStatus.InProgress]: "neutral",
+  [ApiMedicalOpinionStatus.Accomplished]: "success",
+} satisfies Record<ApiMedicalOpinionStatus, ChipProps["color"]>;
+
+export const statusColorsWaitingStatus = {
+  [ApiWaitingStatus.WaitingForConsultation]: "warning",
+  [ApiWaitingStatus.InConsultation]: "primary",
+  [ApiWaitingStatus.Done]: "success",
+} satisfies Record<ApiWaitingStatus, ChipProps["color"]>;
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/shared/helpers.ts b/employee-portal/src/lib/businessModules/officialMedicalService/shared/helpers.ts
index 3da15bb72b5558d4d49840c151d1ce1129494d7d..4a56e3e422efa107ed47d947718a5c83628f3990 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/shared/helpers.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/shared/helpers.ts
@@ -14,7 +14,7 @@ import {
   ApiPatchEmployeeOmsProcedureFacilityRequest,
   ApiPostEmployeeOmsProcedureRequest,
   ApiProcedureStatus,
-} from "@eshg/employee-portal-api/officialMedicalService";
+} from "@eshg/official-medical-service-api";
 
 import { DefaultFacilityFormValues } from "@/lib/shared/components/facilitySidebar/create/FacilityForm";
 import {
@@ -120,3 +120,13 @@ export function isProcedureFinalized(procedure: {
   ];
   return finalizedStates.includes(procedure.status);
 }
+
+export function isProcedureOpenOrInProgress(procedure: {
+  status: ApiProcedureStatus;
+}): boolean {
+  const openOrInProgressStates: ApiProcedureStatus[] = [
+    ApiProcedureStatus.Open,
+    ApiProcedureStatus.InProgress,
+  ];
+  return openOrInProgressStates.includes(procedure.status);
+}
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/shared/routes.ts b/employee-portal/src/lib/businessModules/officialMedicalService/shared/routes.ts
index f3e8532b4ae415f87bff083d93cc228d1a0ebca6..d4aeb832f4172aaeecb3ccc76d740e4fe1c9fe3c 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/shared/routes.ts
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/shared/routes.ts
@@ -11,6 +11,7 @@ export const routes = defineRoutes("/official-medical-service", (omsPath) => ({
     byId: (procedureId: string) =>
       defineRoutes(proceduresPath(`/${procedureId}`), (procedurePath) => ({
         details: procedurePath("/details"),
+        documents: procedurePath("/documents"),
         progressEntries: procedurePath("/progress-entries"),
         syncAffectedPerson: (fileStateId: string, personVersion: number) =>
           procedurePath(
@@ -27,4 +28,5 @@ export const routes = defineRoutes("/official-medical-service", (omsPath) => ({
       new: appointmentBlockGroupsPath("/new"),
     }),
   ),
+  waitingRoom: omsPath("/waiting-room"),
 }));
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/shared/sideNavigationItem.tsx b/employee-portal/src/lib/businessModules/officialMedicalService/shared/sideNavigationItem.tsx
index 88ce47043e095faf601d94c9e6f17b26b57127c2..98746ba2d72d67c86d17202a1a43f4f5a489d4a6 100644
--- a/employee-portal/src/lib/businessModules/officialMedicalService/shared/sideNavigationItem.tsx
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/shared/sideNavigationItem.tsx
@@ -29,6 +29,11 @@ const NAVIGATION_ITEMS: SideNavigationItem[] = [
         href: routes.appointmentBlockGroups.index,
         accessCheck: hasUserRole(ApiUserRole.OfficialMedicalServiceAdmin),
       },
+      {
+        name: "Wartezimmer",
+        href: routes.waitingRoom,
+        accessCheck: hasUserRole(ApiUserRole.OfficialMedicalServiceAdmin),
+      },
     ].filter(isPlainObject),
   },
 ];
diff --git a/employee-portal/src/lib/businessModules/officialMedicalService/shared/translations.ts b/employee-portal/src/lib/businessModules/officialMedicalService/shared/translations.ts
new file mode 100644
index 0000000000000000000000000000000000000000..44ff5fead20f3659175613f60549b295f6d800fd
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/officialMedicalService/shared/translations.ts
@@ -0,0 +1,30 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { EnumMap } from "@eshg/lib-portal/types/helpers";
+import {
+  ApiDocumentStatus,
+  ApiMedicalOpinionStatus,
+  ApiWaitingStatus,
+} from "@eshg/official-medical-service-api";
+
+export const STATUS_NAMES_DOCUMENT_STATUS: EnumMap<ApiDocumentStatus> = {
+  [ApiDocumentStatus.Accepted]: "Akzeptiert",
+  [ApiDocumentStatus.Missing]: "Fehlt",
+  [ApiDocumentStatus.Rejected]: "Nachreichen",
+  [ApiDocumentStatus.Submitted]: "Zu prüfen",
+};
+
+export const STATUS_NAMES_MEDICAL_OPINION_STATUS: EnumMap<ApiMedicalOpinionStatus> =
+  {
+    [ApiMedicalOpinionStatus.InProgress]: "In Arbeit",
+    [ApiMedicalOpinionStatus.Accomplished]: "Fertig",
+  };
+
+export const WAITING_STATUS_VALUES: EnumMap<ApiWaitingStatus> = {
+  [ApiWaitingStatus.WaitingForConsultation]: "Wartet auf Termin",
+  [ApiWaitingStatus.InConsultation]: "Im Gespräch",
+  [ApiWaitingStatus.Done]: "Fertig",
+};
diff --git a/employee-portal/src/lib/businessModules/schoolEntry/api/queries/archiving.ts b/employee-portal/src/lib/businessModules/schoolEntry/api/queries/archiving.ts
index 9db276a6b32cedf90e7a0f6353a544c344bc4130..756474d5c5ea0c8e9be8a4eec4e3e80153a5bc84 100644
--- a/employee-portal/src/lib/businessModules/schoolEntry/api/queries/archiving.ts
+++ b/employee-portal/src/lib/businessModules/schoolEntry/api/queries/archiving.ts
@@ -6,7 +6,7 @@
 import {
   GetArchivableProceduresRequest,
   GetRelevantArchivableProceduresRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 
 import { useArchivingApi } from "@/lib/businessModules/schoolEntry/api/clients";
 import { archivingApiQueryKey } from "@/lib/businessModules/schoolEntry/api/queries/apiQueryKeys";
diff --git a/employee-portal/src/lib/businessModules/schoolEntry/features/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx b/employee-portal/src/lib/businessModules/schoolEntry/features/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
index e7607af7d5a19abb42dcdbea98fc9ac57948a516..1d3a610d314dd539102f3f34155ff7a97c64e56c 100644
--- a/employee-portal/src/lib/businessModules/schoolEntry/features/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
+++ b/employee-portal/src/lib/businessModules/schoolEntry/features/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
@@ -21,7 +21,6 @@ import { AppointmentStaffSelection } from "@/lib/shared/components/appointmentBl
 import { validateAppointmentBlock } from "@/lib/shared/components/appointmentBlocks/validateAppointmentBlock";
 import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
 import { FormSheet } from "@/lib/shared/components/form/FormSheet";
-import { fullName } from "@/lib/shared/components/users/userFormatter";
 import { validateFieldArray } from "@/lib/shared/helpers/validators";
 
 const DEFAULT_PARALLEL_EXAMINATIONS = 1;
@@ -77,13 +76,15 @@ export function AppointmentBlockGroupForm(
   props: AppointmentBlockGroupFormProps,
 ) {
   const physicianOptions = props.allPhysicians.map((option) => ({
-    value: option.userId,
-    label: fullName(option),
+    userId: option.userId,
+    firstName: option.firstName,
+    lastName: option.lastName,
   }));
 
   const medicalAssistantsOptions = props.allMfas.map((option) => ({
-    value: option.userId,
-    label: fullName(option),
+    userId: option.userId,
+    firstName: option.firstName,
+    lastName: option.lastName,
   }));
   const appointmentDurations = Object.fromEntries(
     props.allAppointmentTypes.map((currentType) => [
diff --git a/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/procedureDetails/UpdateProcedureSidebar.tsx b/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/procedureDetails/UpdateProcedureSidebar.tsx
index 4001b4936aa799da3840d0d8fd67f71fa7ccd50a..eb08d93ea37f623ec052bb553db22479a210bd00 100644
--- a/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/procedureDetails/UpdateProcedureSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/procedureDetails/UpdateProcedureSidebar.tsx
@@ -201,12 +201,14 @@ function UpdateProcedureSidebar(props: UpdateProcedureSidebarProps) {
               <SelectContactField
                 name="school"
                 label="Schule"
+                placeholder="Schule suchen"
                 categories={new Set([ApiContactCategory.School])}
               />
               {isHealthDepartmentSelectionMode(locationSelectionMode) && (
                 <SelectContactField
                   name="location"
                   label="Gesundheitsamt"
+                  placeholder="Gesundheitsamt suchen"
                   categories={new Set([ApiContactCategory.HealthDepartment])}
                 />
               )}
diff --git a/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/proceduresTable/ProcedureFilterSettings.tsx b/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/proceduresTable/ProcedureFilterSettings.tsx
index ddf2a7e25f363eb4daee6a4b6eb1f31708cfb6d1..da5b5237573cc355076afb8c8b88dd43071fb5b1 100644
--- a/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/proceduresTable/ProcedureFilterSettings.tsx
+++ b/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/proceduresTable/ProcedureFilterSettings.tsx
@@ -192,6 +192,7 @@ export function ProcedureFilterSettings(props: ProcedureFilterSettingsProps) {
             onChange={(schoolId) =>
               props.setFilterFormValue("schoolIdFilter", schoolId)
             }
+            placeholder="Schule suchen"
           />
         </FormControl>
         <FormControl>
diff --git a/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/proceduresTable/ProceduresTable.tsx b/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/proceduresTable/ProceduresTable.tsx
index 6904a6c94002e8755edc892211a3ef470ed8f213..6ba918bcd768c9f3d612755bb089eddcce095aee 100644
--- a/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/proceduresTable/ProceduresTable.tsx
+++ b/employee-portal/src/lib/businessModules/schoolEntry/features/procedures/proceduresTable/ProceduresTable.tsx
@@ -5,12 +5,12 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
 import {
   formatDate,
   formatDateTime,
 } from "@eshg/lib-portal/formatters/dateTime";
 import { useToggleableState } from "@eshg/lib-portal/hooks/useToggleableState";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 import { ApiSchoolEntryProcedureSortKey } from "@eshg/school-entry-api";
 import { Chip, Stack } from "@mui/joy";
 import { useSuspenseQueries } from "@tanstack/react-query";
diff --git a/employee-portal/src/lib/businessModules/statistics/api/mapper/getActiveFilterLabels.ts b/employee-portal/src/lib/businessModules/statistics/api/mapper/getActiveFilterLabels.ts
index 13458b0dfa0867c52decbeeb0f5a226451688a94..2f42d64f5c1ac9a262ce2f4d20b9a83e05c894ec 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/mapper/getActiveFilterLabels.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/mapper/getActiveFilterLabels.ts
@@ -8,7 +8,7 @@ import { isDefined } from "remeda";
 import { FilterDefinition } from "@/lib/shared/components/filterSettings/models/FilterDefinition";
 import { getDefinitionByValue } from "@/lib/shared/components/filterSettings/models/getDefinitionByValue";
 
-import { SuppertedEvaluationFilterValues } from "./suppertedEvaluationFilterValues";
+import { SupportedEvaluationFilterValues } from "./supportedEvaluationFilterValues";
 
 const includeNullString = "leere Felder";
 
@@ -29,7 +29,7 @@ function createNumberFilterLabels(
 }
 
 export function getActiveFilterLabels(
-  filterValues: SuppertedEvaluationFilterValues[] | undefined,
+  filterValues: SupportedEvaluationFilterValues[] | undefined,
   filterDefinitions: FilterDefinition[],
 ) {
   if (isDefined(filterValues) && filterValues.length > 0) {
@@ -37,7 +37,10 @@ export function getActiveFilterLabels(
       if (filterValue.type === "Enum") {
         const definition = getDefinitionByValue(filterDefinitions, filterValue);
         return `${definition.name}: ${filterValue.selectedValues.map((value) => definition.options.find((option) => option.value === value)!.label).join(", ")}`;
-      } else {
+      } else if (filterValue.type === "Text") {
+        const definition = getDefinitionByValue(filterDefinitions, filterValue);
+        return `${definition.name}: ${filterValue.value}`;
+      } else if (filterValue.type === "Number") {
         const includeNull =
           filterValue.comparison.nullInclusion === "INCLUDE_NULL";
         const definition = getDefinitionByValue(filterDefinitions, filterValue);
diff --git a/employee-portal/src/lib/businessModules/statistics/api/mapper/mapAttributesToFilterDefinitions.ts b/employee-portal/src/lib/businessModules/statistics/api/mapper/mapAttributesToFilterDefinitions.ts
index d479b77114f7ab72538b0ac8ad687e6e9682e7c1..9d239e3ff989b684585b046588e86f9c383d75e7 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/mapper/mapAttributesToFilterDefinitions.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/mapper/mapAttributesToFilterDefinitions.ts
@@ -13,6 +13,7 @@ import {
 import { EnumFilterDefinition } from "@/lib/shared/components/filterSettings/models/EnumFilter";
 import { FilterDefinition } from "@/lib/shared/components/filterSettings/models/FilterDefinition";
 import { NumberFilterDefinition } from "@/lib/shared/components/filterSettings/models/NumberFilter";
+import { TextFilterDefinition } from "@/lib/shared/components/filterSettings/models/TextFilter";
 
 export function mapAttributesToFilterDefinitions(
   attributes: FlatAttribute[],
@@ -44,6 +45,13 @@ export function mapAttributesToFilterDefinitions(
             maxValue: attribute.maxValue,
             unit: attribute.unit,
           } satisfies NumberFilterDefinition;
+        case "TextAttribute":
+          return {
+            type: "Text",
+            key: attribute.key,
+            name: attribute.name,
+            inAccordion: true,
+          } satisfies TextFilterDefinition;
       }
     })
     .filter(isNonNullish);
diff --git a/employee-portal/src/lib/businessModules/statistics/api/mapper/mapEvaluationFilterToFilterValue.ts b/employee-portal/src/lib/businessModules/statistics/api/mapper/mapEvaluationFilterToFilterValue.ts
index 66a2661ce115c325718748941fd7efb52e31f55a..41b1b862f4d2a367c95b090183af4caee82b8c73 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/mapper/mapEvaluationFilterToFilterValue.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/mapper/mapEvaluationFilterToFilterValue.ts
@@ -11,11 +11,11 @@ import {
   ENUM_TRUE_VALUE,
 } from "@/lib/businessModules/statistics/components/evaluations/details/filter/enumFilterMappings";
 
-import { SuppertedEvaluationFilterValues } from "./suppertedEvaluationFilterValues";
+import { SupportedEvaluationFilterValues } from "./supportedEvaluationFilterValues";
 
 export function mapEvaluationFilterToFilterValue(
   filter: EvaluationFilter,
-): SuppertedEvaluationFilterValues {
+): SupportedEvaluationFilterValues {
   switch (filter.type) {
     case "ValueOptionFilterParameter": {
       const selectedValues = filter.searchValues;
@@ -83,6 +83,12 @@ export function mapEvaluationFilterToFilterValue(
             : "EXCLUDE_NULL",
         },
       };
+    case "TextFilterParameter":
+      return {
+        type: "Text",
+        key: mapAttributeSelectionToKey(filter.attribute),
+        value: filter.text,
+      };
     default:
       throw new Error("Not Implemented!");
   }
diff --git a/employee-portal/src/lib/businessModules/statistics/api/mapper/mapFilterValuesToEvaluationFilters.ts b/employee-portal/src/lib/businessModules/statistics/api/mapper/mapFilterValuesToEvaluationFilters.ts
index 4bbada063fecbd3a7d643b2037cf0283c0a7fcaa..f8392011fac3324042111c39f2f32f62d50dcf82 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/mapper/mapFilterValuesToEvaluationFilters.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/mapper/mapFilterValuesToEvaluationFilters.ts
@@ -93,6 +93,13 @@ export function mapFilterValuesToEvaluationFilters(
               withNullValues: withNullValues,
             } satisfies EvaluationFilter;
           }
+        case "TextAttribute":
+          assertFilterType(filterValue, "Text");
+          return {
+            type: "TextFilterParameter",
+            text: filterValue.value,
+            attribute: attributeSelection,
+          } satisfies EvaluationFilter;
         default:
           throw new Error(`Attribute of type ${attribute.type} not expected`);
       }
diff --git a/employee-portal/src/lib/businessModules/statistics/api/mapper/suppertedEvaluationFilterValues.ts b/employee-portal/src/lib/businessModules/statistics/api/mapper/supportedEvaluationFilterValues.ts
similarity index 64%
rename from employee-portal/src/lib/businessModules/statistics/api/mapper/suppertedEvaluationFilterValues.ts
rename to employee-portal/src/lib/businessModules/statistics/api/mapper/supportedEvaluationFilterValues.ts
index 0ce31fb097b7e83ef7397015d49fb8d986dc6add..bd2673ac17df1e4ba1e52b4a1f97918345c2ae22 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/mapper/suppertedEvaluationFilterValues.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/mapper/supportedEvaluationFilterValues.ts
@@ -6,8 +6,9 @@
 import { EnumFilterValue } from "@/lib/shared/components/filterSettings/models/EnumFilter";
 import { FilterValue } from "@/lib/shared/components/filterSettings/models/FilterValue";
 import { NumberFilterValue } from "@/lib/shared/components/filterSettings/models/NumberFilter";
+import { TextFilterValue } from "@/lib/shared/components/filterSettings/models/TextFilter";
 
-export type SuppertedEvaluationFilterValues = Extract<
+export type SupportedEvaluationFilterValues = Extract<
   FilterValue,
-  EnumFilterValue | NumberFilterValue
+  EnumFilterValue | NumberFilterValue | TextFilterValue
 >;
diff --git a/employee-portal/src/lib/businessModules/statistics/api/models/evaluationDetailsTableView.ts b/employee-portal/src/lib/businessModules/statistics/api/models/evaluationDetailsTableView.ts
index 2aa45e0788ec0507db751a7e291a6c0ba2dbf3b5..9d57a1c859b5ea83da7e8243c1275ceb3327d82a 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/models/evaluationDetailsTableView.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/models/evaluationDetailsTableView.ts
@@ -27,6 +27,8 @@ export interface EvaluationDetailsTableView {
   tableData: EvaluationDetailsTableRow[];
   procedureReferences: ProcedureReferences | undefined;
   totalNumberOfElements: number;
+  sortAttribute: ApiGetEvaluationResponse["sortAttribute"];
+  sortDirection: ApiGetEvaluationResponse["sortDirection"];
 }
 
 export function mapEvaluationToTableView(
@@ -47,5 +49,7 @@ export function mapEvaluationToTableView(
     tableData,
     procedureReferences: mapProcedureReferences({ tableData, attributes }),
     totalNumberOfElements: evaluation.totalNumberOfElements,
+    sortAttribute: evaluation.sortAttribute,
+    sortDirection: evaluation.sortDirection,
   };
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes.ts b/employee-portal/src/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes.ts
index 36f391cc138ca87a6f974e682815e18c8775789e..25d3510e72c7fae853a6e5a327104e07ce1acd67 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes.ts
@@ -154,6 +154,8 @@ export interface AnalysisHistogramDiagramConfiguration {
   grouping?: DiagramGrouping;
   binning: DiagramBinning;
   bins?: number;
+  minBin?: number;
+  maxBin?: number;
 }
 
 export interface AnalysisLineDiagramConfiguration {
diff --git a/employee-portal/src/lib/businessModules/statistics/api/mutations/useAddAnalysis.ts b/employee-portal/src/lib/businessModules/statistics/api/mutations/useAddAnalysis.ts
index a5231931be3a63a3a51b73bcb2ada6c64d38d679..2d14dfaef200775ce67bc5a4f610875aaf895b63 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/mutations/useAddAnalysis.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/mutations/useAddAnalysis.ts
@@ -9,7 +9,7 @@ import {
   ApiAddAnalysisRequest,
   ApiAddAnalysisRequestChartConfiguration,
 } from "@eshg/statistics-api";
-import { isNonNullish } from "remeda";
+import { isNonNullish, isNumber } from "remeda";
 
 import { useAnalysisApi } from "@/lib/businessModules/statistics/api/clients";
 import { mapKeyToAttributeSelection } from "@/lib/businessModules/statistics/api/mapper/mapAttributeSelectionKey";
@@ -68,6 +68,7 @@ export function mapModelToChartConfiguration({
       const hasSecondaryAttribute = mapSelectionKeyToBoolean(
         chartConfigurationModel.secondaryAttribute,
       );
+      const manualBinning = chartConfigurationModel.binning === "MANUAL";
       return {
         type: "HistogramChartConfiguration",
         primaryAttribute: mapKeyToAttributeSelection(
@@ -85,9 +86,14 @@ export function mapModelToChartConfiguration({
           ? chartConfigurationModel.grouping
           : undefined,
         binningMode: chartConfigurationModel.binning,
-        numberOfBins:
-          chartConfigurationModel.binning === "MANUAL"
-            ? chartConfigurationModel.bins
+        numberOfBins: manualBinning ? chartConfigurationModel.bins : undefined,
+        minBin:
+          manualBinning && isNumber(chartConfigurationModel.minBin)
+            ? chartConfigurationModel.minBin
+            : undefined,
+        maxBin:
+          manualBinning && isNumber(chartConfigurationModel.maxBin)
+            ? chartConfigurationModel.maxBin
             : undefined,
       };
     }
diff --git a/employee-portal/src/lib/businessModules/statistics/api/queries/useGetDetailPageInformation.ts b/employee-portal/src/lib/businessModules/statistics/api/queries/useGetDetailPageInformation.ts
index 1d0e645e2cb3bf82e30cfe592fee41b4a4803360..d7beefebe4d0b58bf00e18540605a4d328ce051f 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/queries/useGetDetailPageInformation.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/queries/useGetDetailPageInformation.ts
@@ -10,9 +10,8 @@ import {
   ApiGetDetailPageInformationResponse,
   EvaluationApi,
 } from "@eshg/statistics-api";
-import { useSuspenseQuery } from "@tanstack/react-query";
+import { queryOptions } from "@tanstack/react-query";
 
-import { useEvaluationApi } from "@/lib/businessModules/statistics/api/clients";
 import { mapAttributeSelectionToKey } from "@/lib/businessModules/statistics/api/mapper/mapAttributeSelectionKey";
 import { mapTimeRangeEndApiToFrontend } from "@/lib/businessModules/statistics/api/mapper/mapTimeRangeEnd";
 import { mapToApiBusinessModule } from "@/lib/businessModules/statistics/api/mapper/mapToApiBusinessModule";
@@ -65,6 +64,8 @@ function mapConfiguration(
         scaling: diagramConfiguration.scaling,
         binning: diagramConfiguration.binningMode,
         bins: diagramConfiguration.numberOfBins,
+        minBin: diagramConfiguration.minBin,
+        maxBin: diagramConfiguration.maxBin,
         primaryAttribute: getApiAttribute(
           diagramConfiguration.primaryAttribute,
         )!,
@@ -165,17 +166,9 @@ export function createQueryGetDetailPageInformation(
   evaluationApi: EvaluationApi,
   evaluationId: string,
 ) {
-  return {
+  return queryOptions({
     queryKey: evaluationApiQueryKey(["getDetailPageInformation", evaluationId]),
     queryFn: () => evaluationApi.getDetailPageInformation(evaluationId),
     select: mapToEvaluationDetailsView,
-  };
-}
-
-export function useGetDetailPageInformation(evaluationId: string) {
-  const evaluationApi = useEvaluationApi();
-  const queryResult = useSuspenseQuery(
-    createQueryGetDetailPageInformation(evaluationApi, evaluationId),
-  );
-  return queryResult.data;
+  });
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/api/queries/useGetEvaluation.ts b/employee-portal/src/lib/businessModules/statistics/api/queries/useGetEvaluation.ts
index ae0b4a8f7a0ddf49b1f1183b913cfdffcf90bd8b..1aa786c6d1846cdf41aef9f15ddb54091ea7bdeb 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/queries/useGetEvaluation.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/queries/useGetEvaluation.ts
@@ -5,6 +5,7 @@
 
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { EvaluationApi, GetEvaluationRequest } from "@eshg/statistics-api";
+import { queryOptions } from "@tanstack/react-query";
 
 import { mapEvaluationToTableView } from "@/lib/businessModules/statistics/api/models/evaluationDetailsTableView";
 
@@ -14,10 +15,10 @@ export function createQueryGetEvaluation(
   evaluationApi: EvaluationApi,
   evaluationRequest: GetEvaluationRequest,
 ) {
-  return {
+  return queryOptions({
     queryKey: evaluationApiQueryKey(["getEvaluation", evaluationRequest]),
     queryFn: () =>
       evaluationApi.getEvaluationRaw(evaluationRequest).then(unwrapRawResponse),
     select: mapEvaluationToTableView,
-  };
+  });
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/api/queries/useGetEvaluationDetailsTablePage.ts b/employee-portal/src/lib/businessModules/statistics/api/queries/useGetEvaluationDetailsTablePage.ts
index 065b5c108f409b547b6c56853a598ad52d0aefc4..12b1d4db0beb6777f139d6fcc7349c02f881f9d3 100644
--- a/employee-portal/src/lib/businessModules/statistics/api/queries/useGetEvaluationDetailsTablePage.ts
+++ b/employee-portal/src/lib/businessModules/statistics/api/queries/useGetEvaluationDetailsTablePage.ts
@@ -3,8 +3,14 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { GetEvaluationRequest } from "@eshg/statistics-api";
+import {
+  ApiAttributeSelection,
+  ApiSortDirection,
+  GetEvaluationRequest,
+} from "@eshg/statistics-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
+import { useEffect, useRef } from "react";
+import { isDeepEqual, isNullish } from "remeda";
 
 import {
   useEvaluationApi,
@@ -19,11 +25,43 @@ export function useGetEvaluationDetailsTablePage(
 ) {
   const evaluationApi = useEvaluationApi();
   const filterTemplateApi = useFilterTemplateApi();
+
+  const defaultSortAttributeRef = useRef<ApiAttributeSelection>();
+  const defaultSortDirectionRef = useRef<ApiSortDirection>();
+
   const [{ data: evaluation }, { data: filterTemplates }] = useSuspenseQueries({
     queries: [
-      createQueryGetEvaluation(evaluationApi, evaluationRequest),
+      createQueryGetEvaluation(evaluationApi, {
+        ...evaluationRequest,
+        apiGetEvaluationRequest: {
+          ...evaluationRequest.apiGetEvaluationRequest,
+          sortAttribute: !isDeepEqual(
+            defaultSortAttributeRef.current,
+            evaluationRequest.apiGetEvaluationRequest.sortAttribute,
+          )
+            ? evaluationRequest.apiGetEvaluationRequest.sortAttribute
+            : undefined,
+          sortDirection: !isDeepEqual(
+            defaultSortDirectionRef.current,
+            evaluationRequest.apiGetEvaluationRequest.sortDirection,
+          )
+            ? evaluationRequest.apiGetEvaluationRequest.sortDirection
+            : undefined,
+        },
+      }),
       createQueryGetFilterTemplates(filterTemplateApi, evaluationId),
     ],
   });
-  return { evaluation, filterTemplates };
+
+  useEffect(() => {
+    if (isNullish(defaultSortAttributeRef.current)) {
+      defaultSortAttributeRef.current = evaluation.sortAttribute;
+      defaultSortDirectionRef.current = evaluation.sortDirection;
+    }
+  }, [evaluation.sortAttribute, evaluation.sortDirection]);
+
+  return {
+    evaluation,
+    filterTemplates,
+  };
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/ChooseAttributesStep.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/ChooseAttributesStep.tsx
index a3e9c497d5aef78fd0269ac0b565f4c6c0a80f01..f4c8846f14d7e8782e12e98d816dee92d92b0529 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/ChooseAttributesStep.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/ChooseAttributesStep.tsx
@@ -3,20 +3,19 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { Stack } from "@mui/joy";
+import { Checkbox, Stack } from "@mui/joy";
+import { useField } from "formik";
+import { useMemo, useState } from "react";
 import { groupBy } from "remeda";
 
-import { ChooseAttributeStepOrChooseEvaluationStepFormModel } from "@/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/createEvaluationFromScratchFormModel";
+import { ChooseAttributesStepFormModel } from "@/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/chooseAttributesStepFormModel";
 import {
   SearchableGroup,
   SearchableGroupItem,
   SearchableGroups,
 } from "@/lib/shared/components/SearchableGroups";
 import { SidebarStepContentProps } from "@/lib/shared/components/SidebarStepper/sidebarStep";
-import {
-  CheckboxField,
-  CheckboxFieldProps,
-} from "@/lib/shared/components/formFields/CheckboxField";
+import { CheckboxFieldProps } from "@/lib/shared/components/formFields/CheckboxField";
 
 type SearchableCheckboxGroupItem = SearchableGroupItem & {
   checkboxFieldProps: CheckboxFieldProps;
@@ -31,44 +30,76 @@ export interface CategorizedFlatAttribute {
 }
 
 export interface ChooseAttributesStepProps
-  extends SidebarStepContentProps<ChooseAttributeStepOrChooseEvaluationStepFormModel> {
+  extends SidebarStepContentProps<ChooseAttributesStepFormModel> {
   attributes: CategorizedFlatAttribute[];
   dataSourceName: string;
 }
 
-export function ChooseAttributesStep(props: ChooseAttributesStepProps) {
-  const groupedAttributesWithoutReference = groupBy(
-    props.attributes.filter(
-      (attribute) => attribute.code !== "PROCEDURE_REFERENCE",
-    ),
-    (attribute) => attribute.category,
+export function ChooseAttributesStep({
+  fieldName,
+  dataSourceName,
+  attributes,
+}: ChooseAttributesStepProps) {
+  const selectedAttributeKeysFieldName = fieldName("selectedAttributeKeys");
+  const [input, , helper] = useField<Set<string>>(
+    selectedAttributeKeysFieldName,
   );
 
-  const searchableCheckboxGroups: SearchableGroup<SearchableCheckboxGroupItem>[] =
-    Object.entries(groupedAttributesWithoutReference).map(
-      ([category, attributes]) => ({
-        name: category,
-        inAccordion: true,
-        items: attributes.flatMap((attribute) =>
-          mapToCheckboxGroupItem(
-            attribute,
-            props.fieldName("selectedAttributeKeys"),
-          ),
-        ),
-      }),
+  // Make sure, that this expensive component is not re-rendered on value changed
+  return useMemo(() => {
+    const groupedAttributesWithoutReference = groupBy(
+      attributes.filter(
+        (attribute) => attribute.code !== "PROCEDURE_REFERENCE",
+      ),
+      (attribute) => attribute.category,
     );
 
-  return (
-    <Stack>
-      <SearchableGroups
-        groups={searchableCheckboxGroups}
-        label={props.dataSourceName}
-        placeholder="Attribut suchen"
-        startExpanded={searchableCheckboxGroups.length === 1}
-        renderItem={(item) => <CheckboxField {...item.checkboxFieldProps} />}
-      />
-    </Stack>
-  );
+    const searchableCheckboxGroups: SearchableGroup<SearchableCheckboxGroupItem>[] =
+      Object.entries(groupedAttributesWithoutReference).map(
+        ([category, attributes]) => ({
+          name: category,
+          inAccordion: true,
+          items: attributes.flatMap((attribute) =>
+            mapToCheckboxGroupItem(attribute, selectedAttributeKeysFieldName),
+          ),
+        }),
+      );
+
+    function onChange(value: string, checked: boolean) {
+      // Avoid triggering validation of all checkboxes
+      // And avoid rerendering by changing it inline
+      if (checked) {
+        input.value.add(value);
+      } else {
+        input.value.delete(value);
+      }
+      void helper.setValue(input.value, true);
+    }
+
+    return (
+      <Stack>
+        <SearchableGroups
+          groups={searchableCheckboxGroups}
+          label={dataSourceName}
+          placeholder="Attribut suchen"
+          startExpanded={searchableCheckboxGroups.length === 1}
+          renderItem={(item) => (
+            <CheckboxItem
+              item={item}
+              onChange={onChange}
+              isChecked={(key: string) => input.value.has(key)}
+            />
+          )}
+        />
+      </Stack>
+    );
+  }, [
+    dataSourceName,
+    attributes,
+    selectedAttributeKeysFieldName,
+    input.value,
+    helper,
+  ]);
 }
 
 function mapToCheckboxGroupItem(
@@ -85,3 +116,31 @@ function mapToCheckboxGroupItem(
     },
   };
 }
+
+function CheckboxItem({
+  item,
+  onChange,
+  isChecked,
+}: {
+  item: SearchableCheckboxGroupItem;
+  onChange: (value: string, checked: boolean) => void;
+  isChecked: (key: string) => boolean;
+}) {
+  const [checked, setChecked] = useState(
+    isChecked(item.checkboxFieldProps.representingValue!),
+  );
+  return (
+    <Checkbox
+      label={item.checkboxFieldProps.label}
+      value={item.checkboxFieldProps.representingValue}
+      checked={checked}
+      onChange={(changeEvent) => {
+        setChecked(changeEvent.currentTarget.checked);
+        onChange(
+          item.checkboxFieldProps.representingValue!,
+          changeEvent.currentTarget.checked,
+        );
+      }}
+    />
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/chooseAttributesStepFormModel.ts b/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/chooseAttributesStepFormModel.ts
index c92d071eb3e4cb22fc970eb350824133b1784aed..c06f0955d7417d2fcb9218572a88548b820305ad 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/chooseAttributesStepFormModel.ts
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/chooseAttributesStepFormModel.ts
@@ -6,5 +6,5 @@
 import { FormikValues } from "formik";
 
 export interface ChooseAttributesStepFormModel extends FormikValues {
-  selectedAttributeKeys?: string[];
+  selectedAttributeKeys?: Set<string>;
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/validateChooseAttributeStep.ts b/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/validateChooseAttributeStep.ts
index c83d340ae6ca95f378bed6820157f18d12786285..3cef06ef38be211abf9f3b26e6c84dc35a3270f1 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/validateChooseAttributeStep.ts
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/ChooseAttributesStep/validateChooseAttributeStep.ts
@@ -12,7 +12,7 @@ export function validateChooseAttributeStep(
 ) {
   if (
     isNullish(model.selectedAttributeKeys) ||
-    (model.selectedAttributeKeys.length ?? 0) === 0
+    (model.selectedAttributeKeys?.size ?? 0) === 0
   ) {
     return {
       noAttribute: "Bitte Attribut wählen.",
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/CreateEvaluationFromScratchSidebar.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/CreateEvaluationFromScratchSidebar.tsx
index f5233b4dc0b2c5566bbd3e11b4be0a0b679f6c1e..9d2cbb1d349996231ea2d19a3087a9a2814d765c 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/CreateEvaluationFromScratchSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/CreateEvaluationSidebar/CreateEvaluationFromScratchSidebar.tsx
@@ -107,7 +107,7 @@ export function CreateEvaluationFromScratchSidebar({
       const attributeGroups = groupBy(
         getAttributesFromKeys(
           [
-            ...model[1].selectedAttributeKeys!,
+            ...model[1].selectedAttributeKeys!.values(),
             attributeProcedureReference,
           ].filter(isDefined),
           dataSource,
@@ -187,7 +187,7 @@ export function CreateEvaluationFromScratchSidebar({
                 },
               }),
               initialValues: {
-                selectedAttributeKeys: [],
+                selectedAttributeKeys: new Set<string>(),
               },
               validator: validateChooseAttributeStep,
             };
@@ -242,7 +242,7 @@ export function CreateEvaluationFromScratchSidebar({
                   isDefined(prevStepsValues[1].selectedAttributeKeys) &&
                   isDefined(dataSource)
                     ? getAttributesFromKeys(
-                        prevStepsValues[1].selectedAttributeKeys,
+                        [...prevStepsValues[1].selectedAttributeKeys.values()],
                         dataSource,
                       )
                     : undefined,
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ChartsSamplePreview.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ChartsSamplePreview.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bb7457a87e9178b08cb178d133cd6645c5501b8b
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ChartsSamplePreview.tsx
@@ -0,0 +1,281 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Sheet, Stack, Typography } from "@mui/joy";
+import { ReactNode } from "react";
+
+export function ChartsSamplePreview({ chart }: { chart: ReactNode }) {
+  return (
+    <Stack gap={3}>
+      <Typography level="h3" component="h2">
+        Vorschau
+      </Typography>
+      <Sheet
+        variant="soft"
+        color="neutral"
+        sx={{
+          display: "flex",
+          justifyContent: "center",
+          alignItems: "center",
+          borderRadius: (theme) => theme.radius.sm,
+          padding: 2,
+        }}
+      >
+        {chart}
+      </Sheet>
+    </Stack>
+  );
+}
+
+export const barChartSimpleSampleData = [
+  {
+    label: "A",
+    attributes: [
+      {
+        label: "A",
+        value: 8,
+      },
+    ],
+  },
+  {
+    label: "B",
+    attributes: [
+      {
+        label: "B",
+        value: 7,
+      },
+    ],
+  },
+  {
+    label: "C",
+    attributes: [
+      {
+        label: "C",
+        value: 10,
+      },
+    ],
+  },
+  {
+    label: "D",
+    attributes: [
+      {
+        label: "D",
+        value: 5,
+      },
+    ],
+  },
+];
+
+export const barChartGroupedSampleData = [
+  {
+    label: "A",
+    attributes: [
+      {
+        label: "a",
+        value: 7,
+      },
+      {
+        label: "b",
+        value: 8,
+      },
+    ],
+  },
+  {
+    label: "B",
+    attributes: [
+      {
+        label: "a",
+        value: 5,
+      },
+      {
+        label: "b",
+        value: 7,
+      },
+    ],
+  },
+  {
+    label: "C",
+    attributes: [
+      {
+        label: "a",
+        value: 3,
+      },
+      {
+        label: "b",
+        value: 10,
+      },
+    ],
+  },
+  {
+    label: "D",
+    attributes: [
+      {
+        label: "a",
+        value: 1,
+      },
+      {
+        label: "b",
+        value: 5,
+      },
+    ],
+  },
+];
+
+export function getHistogramSimpleSampleData(bins: number) {
+  const histogramSimple = [];
+  for (let i = 0; i < bins; i++) {
+    histogramSimple.push({
+      min: i,
+      max: i + 1,
+      attributes: [
+        {
+          label: "A",
+          value: 5 + i,
+        },
+      ],
+    });
+  }
+  return histogramSimple;
+}
+
+export function getHistogramGroupedSampleData(bins: number) {
+  const histogramGrouped = [];
+  for (let i = 0; i < bins; i++) {
+    histogramGrouped.push({
+      min: i,
+      max: i + 1,
+      attributes: [
+        {
+          label: "A",
+          value: 5 + i,
+        },
+        {
+          label: "B",
+          value: 8,
+        },
+        {
+          label: "C",
+          value: 3,
+        },
+        {
+          label: "D",
+          value: 15 - 0.5 * i,
+        },
+      ],
+    });
+  }
+  return histogramGrouped;
+}
+
+export const pieChartSampleData = [
+  {
+    label: "A",
+    value: 5,
+  },
+  {
+    label: "B",
+    value: 8,
+  },
+  {
+    label: "C",
+    value: 3,
+  },
+  {
+    label: "D",
+    value: 6,
+  },
+  {
+    label: "E",
+    value: 1,
+  },
+];
+
+export const lineChartSimpleSampleData = [
+  {
+    label: "Gruppe 1",
+    dataPoints: [
+      { x: 11, y: 11 },
+      { x: 22, y: 9.5 },
+      { x: 34, y: 12 },
+      { x: 46, y: 11 },
+      { x: 58, y: 14 },
+    ],
+  },
+];
+
+export const lineChartGroupedSampleData = [
+  ...lineChartSimpleSampleData,
+  {
+    label: "Gruppe 2",
+    dataPoints: [
+      { x: 12.5, y: 8 },
+      { x: 20, y: 12 },
+      { x: 30, y: 13 },
+      { x: 45, y: 18 },
+    ],
+  },
+];
+
+export function getScatterChartSimpleSampleData(hasTrendline: boolean) {
+  return [
+    {
+      label: "Gruppe 1",
+      dataPoints: [
+        { x: 14.2, y: 215 },
+        { x: 16.4, y: 325 },
+        { x: 11.9, y: 185 },
+        { x: 15.2, y: 332 },
+        { x: 18.5, y: 406 },
+        { x: 22.1, y: 522 },
+        { x: 19.4, y: 412 },
+        { x: 25.1, y: 614 },
+        { x: 23.4, y: 544 },
+        { x: 18.1, y: 421 },
+        { x: 22.6, y: 445 },
+        { x: 17.2, y: 408 },
+      ],
+      trendline: hasTrendline
+        ? {
+            offset: -216,
+            slope: 33,
+          }
+        : undefined,
+    },
+  ];
+}
+
+export function getScatterChartGroupedSampleData(hasTrendline: boolean) {
+  return [
+    ...getScatterChartSimpleSampleData(hasTrendline),
+    {
+      label: "Gruppe 2",
+      dataPoints: [
+        { x: 10, y: 500 },
+        { x: 15, y: 250 },
+        { x: 20, y: 400 },
+        { x: 25, y: 250 },
+        { x: 30, y: 300 },
+        { x: 35, y: 300 },
+      ],
+      trendline: hasTrendline
+        ? {
+            offset: 461.9,
+            slope: -5.714,
+          }
+        : undefined,
+    },
+  ];
+}
+
+export const chartSampleConfiguration = {
+  xAttribute: {
+    name: "A",
+    unit: "m",
+  },
+  yAttribute: {
+    name: "B",
+    unit: "kg",
+  },
+};
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureBarChartStep/ConfigureBarChartStep.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureBarChartStep/ConfigureBarChartStep.tsx
index a9ee9aedff431651dadf0ba3dc281fcd179ddbeb..aea1ff12a3df8f24b718f8cf182ebae6a551fdde 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureBarChartStep/ConfigureBarChartStep.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureBarChartStep/ConfigureBarChartStep.tsx
@@ -9,8 +9,14 @@ import { Stack } from "@mui/joy";
 import { isNonNullish } from "remeda";
 
 import { FlatAttribute } from "@/lib/businessModules/statistics/api/models/flatAttribute";
+import {
+  ChartsSamplePreview,
+  barChartGroupedSampleData,
+  barChartSimpleSampleData,
+} from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ChartsSamplePreview";
 import { ConfigureChartFormModel } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/createAnalysisFormModel";
 import { mapAttributeToAutocompleteSelectionOption } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/mapAttribute";
+import { BarChart } from "@/lib/businessModules/statistics/components/shared/charts/BarChart";
 import {
   groupingValueNames,
   isCategorical,
@@ -45,41 +51,62 @@ export function ConfigureBarChartStep({
   const scaling = buildEnumOptions(scalingValueNames);
 
   return (
-    <Stack gap={3}>
-      <Stack gap={2}>
-        <SingleAutocompleteField
-          options={autocompleteSelectOptions}
-          name={fieldName("primaryAttribute")}
-          placeholder="Bitte wählen"
-          label="Primäres Attribut"
-          required="Bitte wählen Sie ein Attribut aus."
-        />
-        <SingleAutocompleteField
-          options={autocompleteSelectOptions}
-          name={fieldName("secondaryAttribute")}
-          placeholder="Optional"
-          label="Sekundäres Attribut"
+    <Stack gap={4}>
+      <Stack gap={3}>
+        <Stack gap={2}>
+          <SingleAutocompleteField
+            options={autocompleteSelectOptions}
+            name={fieldName("primaryAttribute")}
+            placeholder="Bitte wählen"
+            label="Primäres Attribut"
+            required="Bitte wählen Sie ein Attribut aus."
+          />
+          <SingleAutocompleteField
+            options={autocompleteSelectOptions}
+            name={fieldName("secondaryAttribute")}
+            placeholder="Optional"
+            label="Sekundäres Attribut"
+          />
+        </Stack>
+        <ToggleButtonGroupField
+          options={orientations}
+          name={fieldName("orientation")}
+          label="Ausrichtung"
         />
+        {showGroupedConfigurations && (
+          <>
+            <ToggleButtonGroupField
+              options={grouping}
+              name={fieldName("grouping")}
+              label="Anordnung"
+            />
+            <ToggleButtonGroupField
+              options={scaling}
+              name={fieldName("scaling")}
+              label="Verhältnisse"
+            />
+          </>
+        )}
       </Stack>
-      <ToggleButtonGroupField
-        options={orientations}
-        name={fieldName("orientation")}
-        label="Ausrichtung"
+      <ChartsSamplePreview
+        chart={
+          showGroupedConfigurations ? (
+            <BarChart
+              key={"groupedBarChart"}
+              diagramData={barChartGroupedSampleData}
+              orientation={values.orientation}
+              grouping={values.grouping}
+              scaling={values.scaling}
+            />
+          ) : (
+            <BarChart
+              key={"simpleBarChart"}
+              diagramData={barChartSimpleSampleData}
+              orientation={values.orientation}
+            />
+          )
+        }
       />
-      {showGroupedConfigurations && (
-        <>
-          <ToggleButtonGroupField
-            options={grouping}
-            name={fieldName("grouping")}
-            label="Anordnung"
-          />
-          <ToggleButtonGroupField
-            options={scaling}
-            name={fieldName("scaling")}
-            label="Verhältnisse"
-          />
-        </>
-      )}
     </Stack>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/ConfigureHistogramChartStep.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/ConfigureHistogramChartStep.tsx
index fcda202ed81ca03c973873cd440898fc225366fd..9edf43137cdabb0f12b4c6ed50a02b8549f9ffc0 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/ConfigureHistogramChartStep.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/ConfigureHistogramChartStep.tsx
@@ -3,14 +3,21 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { NumberField } from "@eshg/lib-portal/components/formFields/NumberField";
 import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/autocomplete/SingleAutocompleteField";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 import { Stack } from "@mui/joy";
 import { isDefined, isNonNullish } from "remeda";
 
 import { FlatAttribute } from "@/lib/businessModules/statistics/api/models/flatAttribute";
+import {
+  ChartsSamplePreview,
+  getHistogramGroupedSampleData,
+  getHistogramSimpleSampleData,
+} from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ChartsSamplePreview";
 import { ConfigureChartFormModel } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/createAnalysisFormModel";
 import { mapAttributeToAutocompleteSelectionOption } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/mapAttribute";
+import { Histogram } from "@/lib/businessModules/statistics/components/shared/charts/Histogram";
 import {
   binningValueNames,
   groupingValueNames,
@@ -54,51 +61,82 @@ export function ConfigureHistogramChartStep({
   const binning = buildEnumOptions(binningValueNames);
 
   return (
-    <Stack gap={3}>
-      <Stack gap={2}>
-        <SingleAutocompleteField
-          options={primaryAutocompleteSelectOptions}
-          name={fieldName("primaryAttribute")}
-          placeholder="Bitte wählen"
-          label="Primäres Attribut"
-          required="Bitte wählen Sie ein Attribut aus."
-        />
-        <SingleAutocompleteField
-          options={secondaryAutocompleteSelectOptions}
-          name={fieldName("secondaryAttribute")}
-          placeholder="Optional"
-          label="Sekundäres Attribut"
-        />
-      </Stack>
-      {showGroupedConfigurations && (
-        <>
-          <ToggleButtonGroupField
-            options={grouping}
-            name={fieldName("grouping")}
-            label="Anordnung"
+    <Stack gap={4}>
+      <Stack gap={3}>
+        <Stack gap={2}>
+          <SingleAutocompleteField
+            options={primaryAutocompleteSelectOptions}
+            name={fieldName("primaryAttribute")}
+            placeholder="Bitte wählen"
+            label="Primäres Attribut"
+            required="Bitte wählen Sie ein Attribut aus."
           />
-          <ToggleButtonGroupField
-            options={scaling}
-            name={fieldName("scaling")}
-            label="Verhältnisse"
-          />
-        </>
-      )}
-      <Stack gap={1}>
-        <ToggleButtonGroupField
-          options={binning}
-          name={fieldName("binning")}
-          label="Bins"
-        />
-        {showBins && (
-          <SliderField
-            min={1}
-            max={50}
-            name={fieldName("bins")}
-            ariaLabel="Anzahl Bins"
+          <SingleAutocompleteField
+            options={secondaryAutocompleteSelectOptions}
+            name={fieldName("secondaryAttribute")}
+            placeholder="Optional"
+            label="Sekundäres Attribut"
           />
+        </Stack>
+        {showGroupedConfigurations && (
+          <>
+            <ToggleButtonGroupField
+              options={grouping}
+              name={fieldName("grouping")}
+              label="Anordnung"
+            />
+            <ToggleButtonGroupField
+              options={scaling}
+              name={fieldName("scaling")}
+              label="Verhältnisse"
+            />
+          </>
         )}
+        <Stack gap={1}>
+          <ToggleButtonGroupField
+            options={binning}
+            name={fieldName("binning")}
+            label="Bins"
+          />
+          {showBins && (
+            <>
+              <SliderField
+                min={1}
+                max={50}
+                name={fieldName("bins")}
+                ariaLabel="Anzahl Bins"
+              />
+              <NumberField
+                label="Bin-Zentrum (unten)"
+                name={fieldName("minBin")}
+                required="Bitte geben Sie einen Wert ein."
+              />
+              <NumberField
+                label="Bin-Zentrum (oben)"
+                name={fieldName("maxBin")}
+                required="Bitte geben Sie einen Wert ein."
+              />
+            </>
+          )}
+        </Stack>
       </Stack>
+      <ChartsSamplePreview
+        chart={
+          showGroupedConfigurations ? (
+            <Histogram
+              key={"groupedHistogram"}
+              diagramData={getHistogramGroupedSampleData(values.bins)}
+              grouping={values.grouping}
+              scaling={values.scaling}
+            />
+          ) : (
+            <Histogram
+              key={"simpleHistogram"}
+              diagramData={getHistogramSimpleSampleData(values.bins)}
+            />
+          )
+        }
+      />
     </Stack>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/configureHistogramChartFormModel.ts b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/configureHistogramChartFormModel.ts
index 1bd993950e53fef65ee48d5f93be8639046344ae..cf9af522f48167d9cf9896f4b86e6a37c8cbeea3 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/configureHistogramChartFormModel.ts
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/configureHistogramChartFormModel.ts
@@ -3,6 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+
 import {
   DiagramBinning,
   DiagramGrouping,
@@ -16,4 +18,6 @@ export interface ConfigureHistogramChartFormModel {
   scaling: DiagramScaling;
   binning: DiagramBinning;
   bins: number;
+  minBin: OptionalFieldValue<number>;
+  maxBin: OptionalFieldValue<number>;
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/validateConfigureHistogramChartStep.ts b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/validateConfigureHistogramChartStep.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2120d0654bd5a564cefc115b6de1728eecf41709
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/validateConfigureHistogramChartStep.ts
@@ -0,0 +1,27 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { FormikErrors } from "formik";
+import { isNumber } from "remeda";
+
+import { ConfigureHistogramChartFormModel } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/configureHistogramChartFormModel";
+
+export function validateConfigureHistogramChartStep(
+  model: ConfigureHistogramChartFormModel,
+): FormikErrors<object> | undefined {
+  if (
+    model.binning === "MANUAL" &&
+    isNumber(model.minBin) &&
+    isNumber(model.maxBin) &&
+    model.minBin >= model.maxBin
+  ) {
+    return {
+      minBinMustBeLessThanMaxBin:
+        "Das untere Bin-Zentrum muss kleiner als das obere Bin-Zentrum sein.",
+    };
+  }
+
+  return undefined;
+}
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureLineChartStep/ConfigureLineChartStep.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureLineChartStep/ConfigureLineChartStep.tsx
index 127761319526a176d54b97d9cd1a72713e2edc73..8827942a4c4d8632d1e99180c6d17c46398a6bca 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureLineChartStep/ConfigureLineChartStep.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureLineChartStep/ConfigureLineChartStep.tsx
@@ -6,10 +6,18 @@
 import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/autocomplete/SingleAutocompleteField";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 import { Stack } from "@mui/joy";
+import { isNonNullish } from "remeda";
 
 import { FlatAttribute } from "@/lib/businessModules/statistics/api/models/flatAttribute";
+import {
+  ChartsSamplePreview,
+  chartSampleConfiguration,
+  lineChartGroupedSampleData,
+  lineChartSimpleSampleData,
+} from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ChartsSamplePreview";
 import { ConfigureChartFormModel } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/createAnalysisFormModel";
 import { mapAttributeToAutocompleteSelectionOption } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/mapAttribute";
+import { LineChart } from "@/lib/businessModules/statistics/components/shared/charts/LineChart";
 import {
   axisRangeValueNames,
   isCategorical,
@@ -26,6 +34,7 @@ export interface ConfigureLineChartStepProps
 export function ConfigureLineChartStep({
   attributes,
   fieldName,
+  values,
 }: ConfigureLineChartStepProps) {
   const axisAttributes = attributes.map(
     mapAttributeToAutocompleteSelectionOption((attribute) =>
@@ -39,34 +48,63 @@ export function ConfigureLineChartStep({
   );
   const axisRange = buildEnumOptions(axisRangeValueNames);
 
+  const showGroupedConfigurations =
+    isNonNullish(values.secondaryAttribute) &&
+    values.secondaryAttribute.length > 0;
+
   return (
-    <Stack gap={3}>
-      <Stack gap={2}>
-        <SingleAutocompleteField
-          options={axisAttributes}
-          name={fieldName("xAxis")}
-          placeholder="Bitte wählen"
-          label="X-Achse"
-          required="Bitte wählen Sie ein Attribut aus."
-        />
-        <SingleAutocompleteField
-          options={axisAttributes}
-          name={fieldName("yAxis")}
-          placeholder="Bitte wählen"
-          label="Y-Achse"
-          required="Bitte wählen Sie ein Attribut aus."
-        />
-        <SingleAutocompleteField
-          options={secondaryAttributes}
-          name={fieldName("secondaryAttribute")}
-          placeholder="Optional"
-          label="Sekundäres Attribut"
+    <Stack gap={4}>
+      <Stack gap={3}>
+        <Stack gap={2}>
+          <SingleAutocompleteField
+            options={axisAttributes}
+            name={fieldName("xAxis")}
+            placeholder="Bitte wählen"
+            label="X-Achse"
+            required="Bitte wählen Sie ein Attribut aus."
+          />
+          <SingleAutocompleteField
+            options={axisAttributes}
+            name={fieldName("yAxis")}
+            placeholder="Bitte wählen"
+            label="Y-Achse"
+            required="Bitte wählen Sie ein Attribut aus."
+          />
+          <SingleAutocompleteField
+            options={secondaryAttributes}
+            name={fieldName("secondaryAttribute")}
+            placeholder="Optional"
+            label="Sekundäres Attribut"
+          />
+        </Stack>
+        <ToggleButtonGroupField
+          options={axisRange}
+          name={fieldName("axisRange")}
+          label="Achsenskalierung"
         />
       </Stack>
-      <ToggleButtonGroupField
-        options={axisRange}
-        name={fieldName("axisRange")}
-        label="Achsenskalierung"
+      <ChartsSamplePreview
+        chart={
+          showGroupedConfigurations ? (
+            <LineChart
+              key={"groupedLineChart"}
+              diagramData={lineChartGroupedSampleData}
+              configuration={{
+                axisRange: values.axisRange,
+                ...chartSampleConfiguration,
+              }}
+            />
+          ) : (
+            <LineChart
+              key={"simpleLineChart"}
+              diagramData={lineChartSimpleSampleData}
+              configuration={{
+                axisRange: values.axisRange,
+                ...chartSampleConfiguration,
+              }}
+            />
+          )
+        }
       />
     </Stack>
   );
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigurePieChartStep/ConfigurePieChartStep.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigurePieChartStep/ConfigurePieChartStep.tsx
index 49ec0e83bd8444e2c44719b178ab2a7452610e83..a3b7d2f31efb9eeff38b0cf81fc6268c9b36cea6 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigurePieChartStep/ConfigurePieChartStep.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigurePieChartStep/ConfigurePieChartStep.tsx
@@ -7,8 +7,13 @@ import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/
 import { Stack } from "@mui/joy";
 
 import { FlatAttribute } from "@/lib/businessModules/statistics/api/models/flatAttribute";
+import {
+  ChartsSamplePreview,
+  pieChartSampleData,
+} from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ChartsSamplePreview";
 import { ConfigureChartFormModel } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/createAnalysisFormModel";
 import { mapAttributeToAutocompleteSelectionOption } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/mapAttribute";
+import { PieChart } from "@/lib/businessModules/statistics/components/shared/charts/PieChart";
 import { isCategorical } from "@/lib/businessModules/statistics/components/shared/charts/chartHelper";
 import { AutocompleteSelectOption } from "@/lib/shared/components/AutocompleteSelectOptions";
 import { SidebarStepContentProps } from "@/lib/shared/components/SidebarStepper/sidebarStep";
@@ -28,16 +33,17 @@ export function ConfigurePieChartStep({
     ),
   );
   return (
-    <Stack gap={3}>
-      <Stack gap={2}>
-        <SingleAutocompleteField
-          options={primaryAttributes}
-          name={fieldName("primaryAttribute")}
-          placeholder="Bitte wählen"
-          label="Primäres Attribut"
-          required="Bitte wählen Sie ein Attribut aus."
-        />
-      </Stack>
+    <Stack gap={4}>
+      <SingleAutocompleteField
+        options={primaryAttributes}
+        name={fieldName("primaryAttribute")}
+        placeholder="Bitte wählen"
+        label="Primäres Attribut"
+        required="Bitte wählen Sie ein Attribut aus."
+      />
+      <ChartsSamplePreview
+        chart={<PieChart diagramData={pieChartSampleData} />}
+      />
     </Stack>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureScatterChartStep/ConfigureScatterChartStep.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureScatterChartStep/ConfigureScatterChartStep.tsx
index 374434fa5465b136ef5a210c302b075605b7579a..e9c9eaeb94b1d9d4e4fab433b3ecb966b2d81440 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureScatterChartStep/ConfigureScatterChartStep.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureScatterChartStep/ConfigureScatterChartStep.tsx
@@ -6,10 +6,18 @@
 import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/autocomplete/SingleAutocompleteField";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 import { Stack } from "@mui/joy";
+import { isNonNullish } from "remeda";
 
 import { FlatAttribute } from "@/lib/businessModules/statistics/api/models/flatAttribute";
+import {
+  ChartsSamplePreview,
+  chartSampleConfiguration,
+  getScatterChartGroupedSampleData,
+  getScatterChartSimpleSampleData,
+} from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ChartsSamplePreview";
 import { ConfigureChartFormModel } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/createAnalysisFormModel";
 import { mapAttributeToAutocompleteSelectionOption } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/mapAttribute";
+import { ScatterChart } from "@/lib/businessModules/statistics/components/shared/charts/ScatterChart";
 import {
   axisRangeValueNames,
   isCategorical,
@@ -27,6 +35,7 @@ export interface ConfigureScatterChartStepProps
 export function ConfigureScatterChartStep({
   attributes,
   fieldName,
+  values,
 }: ConfigureScatterChartStepProps) {
   const axisAttributes = attributes.map(
     mapAttributeToAutocompleteSelectionOption((attribute) =>
@@ -40,38 +49,67 @@ export function ConfigureScatterChartStep({
   );
   const axisRange = buildEnumOptions(axisRangeValueNames);
 
+  const showGroupedConfigurations =
+    isNonNullish(values.secondaryAttribute) &&
+    values.secondaryAttribute.length > 0;
+
   return (
-    <Stack gap={3}>
-      <Stack gap={2}>
-        <SingleAutocompleteField
-          options={axisAttributes}
-          name={fieldName("xAxis")}
-          placeholder="Bitte wählen"
-          label="X-Achse"
-          required="Bitte wählen Sie ein Attribut aus."
-        />
-        <SingleAutocompleteField
-          options={axisAttributes}
-          name={fieldName("yAxis")}
-          placeholder="Bitte wählen"
-          label="Y-Achse"
-          required="Bitte wählen Sie ein Attribut aus."
-        />
-        <SingleAutocompleteField
-          options={secondaryAttributes}
-          name={fieldName("secondaryAttribute")}
-          placeholder="Optional"
-          label="Sekundäres Attribut"
-        />
-      </Stack>
-      <Stack gap={1}>
-        <ToggleButtonGroupField
-          options={axisRange}
-          name={fieldName("axisRange")}
-          label="Achsenskalierung"
-        />
-        <SwitchField name={fieldName("trendline")} label="Trendlinie" />
+    <Stack gap={4}>
+      <Stack gap={3}>
+        <Stack gap={2}>
+          <SingleAutocompleteField
+            options={axisAttributes}
+            name={fieldName("xAxis")}
+            placeholder="Bitte wählen"
+            label="X-Achse"
+            required="Bitte wählen Sie ein Attribut aus."
+          />
+          <SingleAutocompleteField
+            options={axisAttributes}
+            name={fieldName("yAxis")}
+            placeholder="Bitte wählen"
+            label="Y-Achse"
+            required="Bitte wählen Sie ein Attribut aus."
+          />
+          <SingleAutocompleteField
+            options={secondaryAttributes}
+            name={fieldName("secondaryAttribute")}
+            placeholder="Optional"
+            label="Sekundäres Attribut"
+          />
+        </Stack>
+        <Stack gap={1}>
+          <ToggleButtonGroupField
+            options={axisRange}
+            name={fieldName("axisRange")}
+            label="Achsenskalierung"
+          />
+          <SwitchField name={fieldName("trendline")} label="Trendlinie" />
+        </Stack>
       </Stack>
+      <ChartsSamplePreview
+        chart={
+          showGroupedConfigurations ? (
+            <ScatterChart
+              key={`groupedScatterChart_${values.trendline}`}
+              diagramData={getScatterChartGroupedSampleData(values.trendline)}
+              configuration={{
+                axisRange: values.axisRange,
+                ...chartSampleConfiguration,
+              }}
+            />
+          ) : (
+            <ScatterChart
+              key={`simpleScatterChart_${values.trendline}`}
+              diagramData={getScatterChartSimpleSampleData(values.trendline)}
+              configuration={{
+                axisRange: values.axisRange,
+                ...chartSampleConfiguration,
+              }}
+            />
+          )
+        }
+      />
     </Stack>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/CreateAnalysisSidebar.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/CreateAnalysisSidebar.tsx
index ba136159077623274b8f09f4aa2295ef2c594ad5..f773e5cc754e9c0301c122214e1e73e51b0b595f 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/CreateAnalysisSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/CreateAnalysisSidebar.tsx
@@ -12,6 +12,7 @@ import { ConfigureBarChartStep } from "@/lib/businessModules/statistics/componen
 import { validateConfigureBarChartStep } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureBarChartStep/validateConfigureBarChartStep";
 import { ConfigureChoroplethChartStep } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureChoroplethChartStep/ConfigureChoroplethChartStep";
 import { ConfigureHistogramChartStep } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/ConfigureHistogramChartStep";
+import { validateConfigureHistogramChartStep } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureHistogramChartStep/validateConfigureHistogramChartStep";
 import { ConfigureLineChartStep } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureLineChartStep/ConfigureLineChartStep";
 import { ConfigurePieChartStep } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigurePieChartStep/ConfigurePieChartStep";
 import { ConfigureScatterChartStep } from "@/lib/businessModules/statistics/components/evaluations/details/CreateAnalysisSidebar/ConfigureScatterChartStep/ConfigureScatterChartStep";
@@ -67,6 +68,8 @@ function CreateAnalysisSidebar({
     trendline: false,
     binning: "AUTO",
     bins: 8,
+    minBin: "",
+    maxBin: "",
     colorScheme: "UNIFORM",
     characteristicParameter: "MEAN",
   };
@@ -158,6 +161,7 @@ function CreateAnalysisSidebar({
                   componentProps: { attributes },
                 }),
                 initialValues: initialChartConfigurationValues,
+                validator: validateConfigureHistogramChartStep,
               };
           }
         },
diff --git a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/table/EvaluationDetailsTable.tsx b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/table/EvaluationDetailsTable.tsx
index c16aa2222d9ee3b4f9238ea9f502c7ce8270d318..4f2d42c6ce05576821bac78133c52e9f331543da 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/table/EvaluationDetailsTable.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/evaluations/details/table/EvaluationDetailsTable.tsx
@@ -46,7 +46,6 @@ export interface EvaluationDetailsTableProps {
   resolveProcedureId?: (
     procedureReferenceId: string | undefined,
   ) => string | undefined;
-  loading: boolean;
 }
 
 export function EvaluationDetailsTable(props: EvaluationDetailsTableProps) {
@@ -109,10 +108,7 @@ export function EvaluationDetailsTable(props: EvaluationDetailsTableProps) {
         )
       }
     >
-      <TableSheet
-        loading={props.loading}
-        footer={<Pagination {...props.paginationProps} />}
-      >
+      <TableSheet footer={<Pagination {...props.paginationProps} />}>
         <DataTable
           wrapContent
           wrapHeader
diff --git a/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisAccordionDetails.tsx b/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisAccordionDetails.tsx
index 914d5e911bcad7dea2ac2dd11b6d555e4d4dff40..4c984bf3ff4ab66351d43f0a4831b0aebbf596e2 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisAccordionDetails.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisAccordionDetails.tsx
@@ -190,6 +190,18 @@ function getDiagramConfigurationValues(
             ? String(diagramConfiguration.bins)
             : "Auto",
         ],
+        [
+          "Bin-Zentrum (unten)",
+          isNonNullish(diagramConfiguration.minBin)
+            ? String(diagramConfiguration.minBin)
+            : undefined,
+        ],
+        [
+          "Bin-Zentrum (oben)",
+          isNonNullish(diagramConfiguration.maxBin)
+            ? String(diagramConfiguration.maxBin)
+            : undefined,
+        ],
       ];
     case DiagramType.LINE_CHART:
       return lineAndScatterValues(diagramConfiguration);
diff --git a/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisChartDiagram.tsx b/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisChartDiagram.tsx
index f5f3d7253e13da141bfb532dd43e59c6cbb1e7f4..60d56532dd80f7d5d548ab6edcf41ec20daf9968 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisChartDiagram.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisChartDiagram.tsx
@@ -10,7 +10,7 @@ import {
   Edit,
   OpenInFullOutlined,
 } from "@mui/icons-material";
-import { IconButton, Stack, Typography } from "@mui/joy";
+import { IconButton, Stack, Tooltip, Typography } from "@mui/joy";
 import { useState } from "react";
 import { isObjectType } from "remeda";
 
@@ -173,6 +173,7 @@ export function AnalysisChartDiagram(props: {
       </BaseModal>
       <AnalysisDiagramBox
         description={props.analysisDiagram.description}
+        onShowMoreDescription={() => setOpenFullScreenChart(true)}
         filterLabels={props.analysisDiagram.filterLabels}
         evaluatedDataAmount={props.analysisDiagram.evaluatedDataAmount}
         evaluatedDataAmountTotal={props.evaluatedDataAmountTotal}
@@ -184,9 +185,21 @@ export function AnalysisChartDiagram(props: {
             alignItems="center"
             minWidth={0}
           >
-            <Typography level="title-md" data-testid="analysis-diagram-title">
-              {props.analysisDiagram.title}
-            </Typography>
+            <Tooltip title={props.analysisDiagram.title}>
+              <Typography
+                sx={{
+                  height: "1.5rem",
+                  whiteSpace: "nowrap",
+                  overflow: "hidden",
+                  textOverflow: "ellipsis",
+                  paddingRight: "1rem",
+                }}
+                level="title-md"
+                data-testid="analysis-diagram-title"
+              >
+                {props.analysisDiagram.title}
+              </Typography>
+            </Tooltip>
             <Stack direction="row" gap={1}>
               <IconButton
                 aria-label="Im Vollbildmodus anzeigen"
diff --git a/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisDiagramBox.tsx b/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisDiagramBox.tsx
index 7a867a42f08a4828ad950b82901458fe60c71119..fa81eb4c8012bd14bc7f3787a22fa2e56f408316 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisDiagramBox.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/shared/AnalysisAccordion/AnalysisDiagramBox.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { Box, Divider, Stack, Typography } from "@mui/joy";
+import { Box, Button, Divider, Stack, Typography } from "@mui/joy";
 import { ReactNode } from "react";
 
 interface AnalysisDiagramProps {
@@ -13,6 +13,7 @@ interface AnalysisDiagramProps {
   evaluatedDataAmountTotal: number;
   header?: ReactNode;
   getChart: () => ReactNode;
+  onShowMoreDescription?: () => void;
 }
 
 export function AnalysisDiagramBox({
@@ -22,6 +23,7 @@ export function AnalysisDiagramBox({
   evaluatedDataAmountTotal,
   header,
   getChart,
+  onShowMoreDescription,
 }: AnalysisDiagramProps) {
   function diagramContent() {
     if (evaluatedDataAmount === 0) {
@@ -56,11 +58,12 @@ export function AnalysisDiagramBox({
     >
       {header}
       {diagramContent()}
-      <Stack gap={2} marginTop={2}>
+      <Stack gap={2}>
         <Divider />
-        <Typography level="body-md" data-testid="analysis-diagram-description">
-          {description}
-        </Typography>
+        <Description
+          description={description}
+          onShowMoreDescription={onShowMoreDescription}
+        />
         <Stack gap={0.5}>
           <Typography
             level="body-xs"
@@ -81,3 +84,45 @@ export function AnalysisDiagramBox({
     </Stack>
   );
 }
+
+function Description(props: {
+  description: string | undefined;
+  onShowMoreDescription?: () => void;
+}) {
+  if (props.onShowMoreDescription) {
+    const MAX_DESCRIPTION_LENGTH = 95; // Determined through testing
+    const showMore = (props.description?.length ?? 0) > MAX_DESCRIPTION_LENGTH;
+
+    return (
+      <Typography
+        sx={{ height: "4rem" }}
+        level="body-md"
+        data-testid="analysis-diagram-description"
+      >
+        {props.description?.slice(0, MAX_DESCRIPTION_LENGTH)}
+        {showMore && "..."}
+        {showMore && (
+          <Button
+            variant="plain"
+            onClick={() => props.onShowMoreDescription!()}
+          >
+            Mehr anzeigen
+          </Button>
+        )}
+      </Typography>
+    );
+  } else {
+    return (
+      <Typography
+        sx={{
+          height: "10rem",
+          overflowY: "scroll",
+        }}
+        level="body-md"
+        data-testid="analysis-diagram-description"
+      >
+        {props.description}
+      </Typography>
+    );
+  }
+}
diff --git a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/BarChart.tsx b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/BarChart.tsx
index bc0dacf562a8eefbf77b4334d181792076278d7e..8fb440f23ab9c142ea2305256a27b632ab1fd8b3 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/BarChart.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/BarChart.tsx
@@ -18,7 +18,7 @@ import {
 } from "@/lib/businessModules/statistics/components/shared/charts/EChart";
 import {
   calculateRelativeFormatting,
-  formatBreakLongStringOnce,
+  formatChartLabel,
 } from "@/lib/businessModules/statistics/components/shared/charts/dataHelper";
 
 export interface BarChartProps {
@@ -141,20 +141,18 @@ export function BarChart(props: BarChartProps) {
     type: "category",
     data: series.labels,
     axisLabel: {
-      ...(props.orientation === "VERTICAL" &&
-      props.type !== DiagramType.HISTOGRAM_CHART
-        ? {
-            hideOverlap: false,
-            interval: 0,
-            width: 100,
-            overflow: "break",
-          }
-        : {}),
-      ...(props.orientation === "HORIZONTAL"
-        ? {
-            formatter: formatBreakLongStringOnce,
-          }
-        : {}),
+      formatter: (text: string) => {
+        if (props.orientation === "VERTICAL") {
+          return formatChartLabel(text, 100);
+        }
+        return formatChartLabel(text, 330);
+      },
+      hideOverlap: false,
+      interval:
+        props.orientation === "VERTICAL" &&
+        props.type !== DiagramType.HISTOGRAM_CHART
+          ? 0
+          : undefined,
     },
     axisLine: {
       show: props.type === DiagramType.HISTOGRAM_CHART,
diff --git a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/LineChart.tsx b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/LineChart.tsx
index 15571e0f209201f2c33b3527576e84109c95e2fe..f5c4b75611e4fc00034ba014997eba7b6a779f82 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/LineChart.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/LineChart.tsx
@@ -5,10 +5,7 @@
 
 import { EChartsOption, SeriesOption } from "echarts";
 
-import {
-  AnalysisDiagramLineChart,
-  AnalysisLineDiagramConfiguration,
-} from "@/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes";
+import { AnalysisDiagramLineChart } from "@/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes";
 import {
   ChartApi,
   EChart,
@@ -18,12 +15,11 @@ import {
   mapAxisTitleWithOptionalUnit,
 } from "@/lib/businessModules/statistics/components/shared/charts/dataHelper";
 
+import { NumericAxesConfiguration } from "./types";
+
 interface LineChartDiagramProps {
   diagramData: AnalysisDiagramLineChart["data"];
-  configuration: Pick<
-    AnalysisLineDiagramConfiguration,
-    "axisRange" | "xAttribute" | "yAttribute"
-  >;
+  configuration: NumericAxesConfiguration;
   eChartApi?: (eChartApi: ChartApi) => void;
 }
 
diff --git a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/ScatterChart.tsx b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/ScatterChart.tsx
index 566f208ffa4071caf1f260d7d457ab20e09e8766..e898cbac906d89bba0d995b61ee7a6298e16bb67 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/ScatterChart.tsx
+++ b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/ScatterChart.tsx
@@ -6,10 +6,7 @@
 import { EChartsOption, SeriesOption } from "echarts";
 import { unique } from "remeda";
 
-import {
-  AnalysisDiagramScatterChart,
-  AnalysisScatterDiagramConfiguration,
-} from "@/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes";
+import { AnalysisDiagramScatterChart } from "@/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes";
 import {
   ChartApi,
   EChart,
@@ -19,12 +16,11 @@ import {
   mapAxisTitleWithOptionalUnit,
 } from "@/lib/businessModules/statistics/components/shared/charts/dataHelper";
 
+import { NumericAxesConfiguration } from "./types";
+
 interface ScatterChartDiagramProps {
   diagramData: AnalysisDiagramScatterChart["data"];
-  configuration: Pick<
-    AnalysisScatterDiagramConfiguration,
-    "axisRange" | "xAttribute" | "yAttribute"
-  >;
+  configuration: NumericAxesConfiguration;
   eChartApi?: (eChartApi: ChartApi) => void;
 }
 
diff --git a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/dataHelper.ts b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/dataHelper.ts
index 068927763b1ce0f93a35c564f2788aee136e1622..9f8304c17524d5d2292ba7bb34fe7abd869d942a 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/dataHelper.ts
+++ b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/dataHelper.ts
@@ -9,7 +9,8 @@ import {
   AnalysisDiagramLineChart,
   AnalysisDiagramScatterChart,
 } from "@/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes";
-import { FlatAttribute } from "@/lib/businessModules/statistics/api/models/flatAttribute";
+
+import { XYAxes } from "./types";
 
 export function calculateXYMinMax(
   filterSet:
@@ -25,24 +26,118 @@ export function calculateXYMinMax(
   return [xMin, xMax, yMin, yMax];
 }
 
-export function formatBreakLongStringOnce(input: string) {
-  if (input.length <= 30) {
-    return input;
+function getTextWidth(text: string) {
+  const charWidths = new Map<string, number>([
+    ["f", 4],
+    ["i", 3],
+    ["j", 4],
+    ["l", 3],
+    ["m", 11],
+    ["r", 4],
+    ["t", 4],
+    ["w", 11],
+    ["A", 8],
+    ["B", 8],
+    ["C", 9],
+    ["D", 9],
+    ["E", 8],
+    ["F", 8],
+    ["G", 9],
+    ["H", 9],
+    ["I", 4],
+    ["J", 5],
+    ["K", 8],
+    ["L", 7],
+    ["M", 11],
+    ["N", 9],
+    ["O", 9],
+    ["P", 8],
+    ["Q", 9],
+    ["R", 8],
+    ["S", 8],
+    ["T", 8],
+    ["U", 9],
+    ["V", 8],
+    ["W", 11],
+    ["X", 8],
+    ["Y", 8],
+    ["Z", 8],
+    [" ", 3],
+    [".", 3],
+    [",", 3],
+    ["!", 3],
+    ["?", 6],
+    ["-", 4],
+    ["1", 4],
+  ]);
+
+  return text
+    .split("")
+    .reduce((acc, character) => acc + (charWidths.get(character) ?? 7), 0);
+}
+
+function splitWordEqually(word: string, maxWidth: number) {
+  // Determine Split point
+  const averageCharsFittingWidth = Math.floor(
+    maxWidth / (getTextWidth(word) / word.length),
+  );
+  let amountOfSplits = 1;
+  for (
+    ;
+    word.length / amountOfSplits > averageCharsFittingWidth;
+    ++amountOfSplits
+  ) {}
+
+  // Split words
+  const splitInterval = Math.ceil(word.length / amountOfSplits);
+  const splitWords = [];
+  let splitIndex = 0;
+  for (
+    ;
+    splitIndex + splitInterval < word.length;
+    splitIndex += splitInterval
+  ) {
+    splitWords.push(word.slice(splitIndex, splitIndex + splitInterval) + "-");
   }
+  splitWords.push(word.slice(splitIndex));
+
+  return splitWords;
+}
 
-  const textParts = input.split(" ");
-  const middle = Math.round(textParts.length / 2);
-  const topPart = textParts.slice(0, middle).join(" ");
-  const bottomPart = textParts.slice(middle).join(" ");
-  return topPart + "\n" + bottomPart;
+export function formatChartLabel(text: string, maxWidth: number) {
+  return text
+    .split(/\s|(?<=-)/)
+    .flatMap((it) => {
+      if (getTextWidth(it) > maxWidth) {
+        return splitWordEqually(it, maxWidth);
+      }
+      return [it];
+    })
+    .reduce((acc, currentValue) => {
+      if (
+        acc.length > 0 &&
+        getTextWidth([...acc[acc.length - 1]!, currentValue].join(" ")) <
+          maxWidth
+      ) {
+        return [
+          ...acc.slice(0, acc.length - 1),
+          [...acc[acc.length - 1]!, currentValue],
+        ];
+      }
+      return [...acc, [currentValue]];
+    }, [] as string[][])
+    .map((it) => it.join(" "))
+    .join("\n")
+    .replaceAll("- ", "-");
 }
 
-export function mapAxisTitleWithOptionalUnit(attribute: FlatAttribute) {
-  return (attribute.type === "DecimalAttribute" ||
-    attribute.type === "IntegerAttribute") &&
+export function mapAxisTitleWithOptionalUnit(attribute: XYAxes) {
+  return formatChartLabel(
     isDefined(attribute.unit)
-    ? `${formatBreakLongStringOnce(attribute.name)} [${attribute.unit}]`
-    : formatBreakLongStringOnce(attribute.name);
+      ? `${attribute.name} [${attribute.unit}]`
+      : attribute.name,
+    300,
+  );
 }
 
 export function calculateRelativeFormatting(value: number): string {
diff --git a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/types.ts b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/types.ts
index 1dd11f3ff1dd13374e7c7d8fee26771abd777d90..715c00ca56d8b28129c970e49a268cbe80d27e54 100644
--- a/employee-portal/src/lib/businessModules/statistics/components/shared/charts/types.ts
+++ b/employee-portal/src/lib/businessModules/statistics/components/shared/charts/types.ts
@@ -3,7 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiBaseModuleIdAttributeAllOfBaseAttribute } from "@eshg/statistics-api";
+import {
+  ApiBaseModuleIdAttributeAllOfBaseAttribute,
+  ApiDecimalAttribute,
+  ApiIntegerAttribute,
+} from "@eshg/statistics-api";
+
+import { DiagramAxisRange } from "@/lib/businessModules/statistics/api/models/evaluationDetailsViewTypes";
 
 export const ImageType = {
   SVG: "svg",
@@ -13,3 +19,14 @@ export const ImageType = {
 export type ImageType = (typeof ImageType)[keyof typeof ImageType];
 
 export type AttributeType = ApiBaseModuleIdAttributeAllOfBaseAttribute["type"];
+
+export type XYAxes = Pick<
+  ApiIntegerAttribute & ApiDecimalAttribute,
+  "name" | "unit"
+>;
+
+export interface NumericAxesConfiguration {
+  axisRange: DiagramAxisRange;
+  xAttribute: XYAxes;
+  yAttribute: XYAxes;
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/clients.ts b/employee-portal/src/lib/businessModules/stiProtection/api/clients.ts
index 166014d4c928e8ddf1caa9358affc3025ba790ff..2b3336b28f56bea939741e799cc327237c15bb9f 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/clients.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/clients.ts
@@ -7,6 +7,7 @@ import {
   Configuration as BaseConfiguration,
   CitizenAccessCodeUserApi,
 } from "@eshg/base-api";
+import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
 import {
   AppointmentBlockApi,
   AppointmentTypeApi,
@@ -22,9 +23,9 @@ import {
   ProcedureApi,
   ProgressEntryApi,
   StiProtectionProcedureApi,
+  TextTemplateApi,
   WaitingRoomApi,
-} from "@eshg/employee-portal-api/stiProtection";
-import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
+} from "@eshg/sti-protection-api";
 
 function useConfiguration() {
   const configParameters = useApiConfiguration(
@@ -114,3 +115,8 @@ export function useDiagnosisApi() {
   const config = useConfiguration();
   return new DiagnosisApi(config);
 }
+
+export function useTextTemplateApi() {
+  const config = useConfiguration();
+  return new TextTemplateApi(config);
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/models/AppointmentBlockGroup.ts b/employee-portal/src/lib/businessModules/stiProtection/api/models/AppointmentBlockGroup.ts
index 1e8cdf7de21ff44fdd1205e3639f10a0a5149ce3..99106e14926921c76060daa332a199f7784530f9 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/models/AppointmentBlockGroup.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/models/AppointmentBlockGroup.ts
@@ -3,16 +3,16 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiAppointmentType,
-  ApiGetAppointmentBlock,
-  ApiGetAppointmentBlockGroup,
-} from "@eshg/employee-portal-api/stiProtection";
 import {
   BaseEntity,
   mapBaseEntity,
 } from "@eshg/lib-employee-portal/api/models/BaseEntity";
 import { assertNonEmptyArray } from "@eshg/lib-portal/helpers/assertions";
+import {
+  ApiAppointmentType,
+  ApiGetAppointmentBlock,
+  ApiGetAppointmentBlockGroup,
+} from "@eshg/sti-protection-api";
 import { first, last, sumBy } from "remeda";
 
 export interface AppointmentBlockStiProtection extends BaseEntity {
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/models/AppointmentTypeConfig.ts b/employee-portal/src/lib/businessModules/stiProtection/api/models/AppointmentTypeConfig.ts
index 9ac9d5649cd3d68c8bdbbcd2870181efe920191c..c8e506b058776d112d3996e2f96ba6d1c5f5939e 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/models/AppointmentTypeConfig.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/models/AppointmentTypeConfig.ts
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiAppointmentType,
-  ApiAppointmentTypeConfig,
-} from "@eshg/employee-portal-api/stiProtection";
 import {
   BaseEntity,
   mapBaseEntity,
 } from "@eshg/lib-employee-portal/api/models/BaseEntity";
+import {
+  ApiAppointmentType,
+  ApiAppointmentTypeConfig,
+} from "@eshg/sti-protection-api";
 
 export interface AppointmentTypeConfig extends BaseEntity {
   appointmentTypeDto: ApiAppointmentType;
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/appointmentBlocks.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/appointmentBlocks.ts
index 0a5c5d507e1c10e05ea7c52a8400b52512284364..5bc231e0a88fc9cd297d6953c6f7645827a5921a 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/appointmentBlocks.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/appointmentBlocks.ts
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiCreateAppointmentBlockGroupResponse,
   ApiCreateDailyAppointmentBlockGroupRequest,
-} from "@eshg/employee-portal-api/stiProtection";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+} from "@eshg/sti-protection-api";
 import { MutationOptions, useMutation } from "@tanstack/react-query";
 
 import { useAppointmentBlockApi } from "@/lib/businessModules/stiProtection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/appointmentTypes.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/appointmentTypes.ts
index cd7257f6a2a5dedd10cd0b15e7b71fef384d3aa8..65164c0c65eebdb79a32d81220a4f7483d8c8560 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/appointmentTypes.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/appointmentTypes.ts
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import {
   ApiAppointmentTypeConfig,
   ApiUpdateAppointmentTypeRequest,
-} from "@eshg/employee-portal-api/stiProtection";
-import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+} from "@eshg/sti-protection-api";
 
 import { useAppointmentTypeApi } from "@/lib/businessModules/stiProtection/api/clients";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/consultation.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/consultation.ts
index bbb05a1cebddd05bfa26bfa2e009443ce1933840..27f433a3e7eb1ae01eb79dc416190f9b355319e1 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/consultation.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/consultation.ts
@@ -3,22 +3,53 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiConsultation } from "@eshg/employee-portal-api/stiProtection";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { MutationPassThrough } from "@eshg/lib-portal/types/query";
-import { useMutation } from "@tanstack/react-query";
+import { ApiConsultation } from "@eshg/sti-protection-api";
+import { MutationOptions, useMutation } from "@tanstack/react-query";
 
 import { useConsultationApi } from "@/lib/businessModules/stiProtection/api/clients";
 import { proceduresQueryKey } from "@/lib/businessModules/stiProtection/api/queries/apiQueryKeys";
 
-export function useUpsertConsultation(
-  procedureId: string,
-  passThrough: MutationPassThrough<ApiConsultation, void>,
-) {
-  const api = useConsultationApi();
-  return useMutation({
-    mutationFn: (consultation) =>
-      api.updateConsultation(procedureId, consultation),
+interface UpsertConsultationParams {
+  consultation: ApiConsultation;
+}
+
+export function useUpsertConsultationOptions({
+  procedureId,
+  passThrough,
+}: {
+  procedureId: string;
+  passThrough?: MutationPassThrough<UpsertConsultationParams, void>;
+}): MutationOptions<void, Error, UpsertConsultationParams> {
+  const consultationApi = useConsultationApi();
+  const snackbar = useSnackbar();
+
+  return {
+    mutationFn: ({ consultation }: UpsertConsultationParams) =>
+      consultationApi.updateConsultation(procedureId, consultation),
     mutationKey: proceduresQueryKey([procedureId, "consultation"]),
-    ...passThrough,
-  });
+    ...(passThrough ?? {
+      onSuccess: () => {
+        snackbar.confirmation(
+          "Die Konsultation wurde erfolgreich gespeichert.",
+        );
+      },
+      onError: () => {
+        snackbar.error("Die Konsultation konnte nicht gespeichert werden.");
+      },
+    }),
+  };
+}
+
+export function useUpsertConsultation({
+  procedureId,
+  passThrough,
+}: {
+  procedureId: string;
+  passThrough?: MutationPassThrough<UpsertConsultationParams, void>;
+}) {
+  const options = useUpsertConsultationOptions({ procedureId, passThrough });
+
+  return useMutation(options);
 }
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/diagnosis.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/diagnosis.ts
index ebe674a35dff2fe5249c6b5a5bd6d9212731644a..54e61af913fd1eca862747b7e3debdf42823e485 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/diagnosis.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/diagnosis.ts
@@ -3,22 +3,51 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiDiagnosis } from "@eshg/employee-portal-api/stiProtection";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { MutationPassThrough } from "@eshg/lib-portal/types/query";
-import { useMutation } from "@tanstack/react-query";
+import { ApiDiagnosis } from "@eshg/sti-protection-api";
+import { MutationOptions, useMutation } from "@tanstack/react-query";
 
 import { useDiagnosisApi } from "@/lib/businessModules/stiProtection/api/clients";
 import { proceduresQueryKey } from "@/lib/businessModules/stiProtection/api/queries/apiQueryKeys";
 
-export function useUpsertDiagnosis(
-  procedureId: string,
-  passThrough: MutationPassThrough<ApiDiagnosis, void>,
-) {
-  const api = useDiagnosisApi();
-  return useMutation({
-    mutationFn: (consultation) =>
-      api.updateDiagnosis(procedureId, consultation),
+interface UpsertDiagnosisParams {
+  diagnosis: ApiDiagnosis;
+}
+
+export function useUpsertDiagnosisOptions({
+  procedureId,
+  passThrough,
+}: {
+  procedureId: string;
+  passThrough?: MutationPassThrough<UpsertDiagnosisParams, void>;
+}): MutationOptions<void, Error, UpsertDiagnosisParams> {
+  const diagnosisApi = useDiagnosisApi();
+  const snackbar = useSnackbar();
+
+  return {
+    mutationFn: ({ diagnosis }: UpsertDiagnosisParams) =>
+      diagnosisApi.updateDiagnosis(procedureId, diagnosis),
     mutationKey: proceduresQueryKey([procedureId, "diagnosis"]),
-    ...passThrough,
-  });
+    ...(passThrough ?? {
+      onSuccess: () => {
+        snackbar.confirmation("Die Diagnose wurde erfolgreich gespeichert.");
+      },
+      onError: () => {
+        snackbar.error("Die Diagnose konnte nicht gespeichert werden.");
+      },
+    }),
+  };
+}
+
+export function useUpsertDiagnosis({
+  procedureId,
+  passThrough,
+}: {
+  procedureId: string;
+  passThrough?: MutationPassThrough<UpsertDiagnosisParams, void>;
+}) {
+  const options = useUpsertDiagnosisOptions({ procedureId, passThrough });
+
+  return useMutation(options);
 }
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/examination.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/examination.ts
index d0c36ed540466dd1ccd74167cedc61652e9f2337..fddc543b46b0454363da256f84cd19a1f35eef98 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/examination.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/examination.ts
@@ -3,53 +3,100 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { MutationPassThrough } from "@eshg/lib-portal/types/query";
 import {
   ApiLaboratoryTestExamination,
   ApiRapidTestExamination,
-} from "@eshg/employee-portal-api/stiProtection";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
-import { useMutation } from "@tanstack/react-query";
+} from "@eshg/sti-protection-api";
+import { MutationOptions, useMutation } from "@tanstack/react-query";
 
 import { useExaminationApi } from "@/lib/businessModules/stiProtection/api/clients";
 import { proceduresQueryKey } from "@/lib/businessModules/stiProtection/api/queries/apiQueryKeys";
 
-export function useUpsertRapidTest(procedureId: string) {
+interface UpsertRapidTestParams {
+  rapidTests: ApiRapidTestExamination;
+}
+
+export function useUpsertRapidTestOptions({
+  procedureId,
+  passThrough,
+}: {
+  procedureId: string;
+  passThrough?: MutationPassThrough<UpsertRapidTestParams, void>;
+}): MutationOptions<void, Error, UpsertRapidTestParams> {
   const examinationApi = useExaminationApi();
   const snackbar = useSnackbar();
 
-  return useMutation({
-    mutationFn: ({ rapidTests }: { rapidTests: ApiRapidTestExamination }) =>
+  return {
+    mutationFn: ({ rapidTests }: UpsertRapidTestParams) =>
       examinationApi.updateRapidTestExamination(procedureId, rapidTests),
-    onSuccess: () => {
-      snackbar.confirmation("Die Schnelltests wurden erfolgreich gespeichert.");
-    },
-    onError: () => {
-      snackbar.error("Die Schnelltests konnten nicht gespeichert werden.");
-    },
     mutationKey: proceduresQueryKey([procedureId, "rapidTests"]),
-  });
+    ...(passThrough ?? {
+      onSuccess: () => {
+        snackbar.confirmation(
+          "Die Schnelltests wurden erfolgreich gespeichert.",
+        );
+      },
+      onError: () => {
+        snackbar.error("Die Schnelltests konnten nicht gespeichert werden.");
+      },
+    }),
+  };
+}
+
+export function useUpsertRapidTests({
+  procedureId,
+  passThrough,
+}: {
+  procedureId: string;
+  passThrough?: MutationPassThrough<UpsertRapidTestParams, void>;
+}) {
+  const options = useUpsertRapidTestOptions({ procedureId, passThrough });
+
+  return useMutation(options);
+}
+
+interface UpsertLaboratoryTestParams {
+  laboratoryTests: ApiLaboratoryTestExamination;
 }
 
-export function useUpsertLaboratoryTest(procedureId: string) {
+export function useUpsertLaboratoryTestOptions({
+  procedureId,
+  passThrough,
+}: {
+  procedureId: string;
+  passThrough?: MutationPassThrough<UpsertLaboratoryTestParams, void>;
+}): MutationOptions<void, Error, UpsertLaboratoryTestParams> {
   const examinationApi = useExaminationApi();
   const snackbar = useSnackbar();
 
-  return useMutation({
-    mutationFn: ({
-      laboratoryTests,
-    }: {
-      laboratoryTests: ApiLaboratoryTestExamination;
-    }) =>
+  return {
+    mutationFn: ({ laboratoryTests }: UpsertLaboratoryTestParams) =>
       examinationApi.updateLaboratoryTestExamination(
         procedureId,
         laboratoryTests,
       ),
-    onSuccess: () => {
-      snackbar.confirmation("Die Labortests wurden erfolgreich gespeichert.");
-    },
-    onError: () => {
-      snackbar.error("Die Labortests konnten nicht gespeichert werden.");
-    },
     mutationKey: proceduresQueryKey([procedureId, "laboratoryTests"]),
-  });
+    ...(passThrough ?? {
+      onSuccess: () => {
+        snackbar.confirmation("Die Labortests wurden erfolgreich gespeichert.");
+      },
+      onError: () => {
+        snackbar.error("Die Labortests konnten nicht gespeichert werden.");
+      },
+    }),
+  };
+}
+
+export function useUpsertLaboratoryTest({
+  procedureId,
+  passThrough,
+}: {
+  procedureId: string;
+  passThrough?: MutationPassThrough<UpsertLaboratoryTestParams, void>;
+}) {
+  const options = useUpsertLaboratoryTestOptions({ procedureId, passThrough });
+
+  return useMutation(options);
 }
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/medicalHistory.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/medicalHistory.ts
index 9102afeac7e51312053702c93196295f216b83d4..d7fee90eaa9d207777251c6675889e378ee4fefd 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/medicalHistory.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/medicalHistory.ts
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiCreateMedicalHistoryRequest } from "@eshg/employee-portal-api/stiProtection";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { ApiCreateMedicalHistoryRequest } from "@eshg/sti-protection-api";
 import { MutationOptions, useMutation } from "@tanstack/react-query";
 
 import { useMedicalHistoryApi } from "@/lib/businessModules/stiProtection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/procedures.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/procedures.ts
index ae3cb1f97018b83bd696b265ced5d6b601f20439..66307a66455ac9b9ecebbbf654b95ec0ac7237d7 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/procedures.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/procedures.ts
@@ -3,17 +3,19 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { MutationPassThrough } from "@eshg/lib-portal/types/query";
 import {
   ApiCreateAppointmentRequest,
+  ApiCreateFollowUpProcedureRequest,
+  ApiCreateFollowUpProcedureResponse,
   ApiCreateProcedureRequest,
   ApiCreateProcedureResponse,
   ApiUpdateAppointmentRequest,
   ApiUpdatePersonDetailsRequest,
   CancelAppointmentRequest,
-} from "@eshg/employee-portal-api/stiProtection";
-import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
-import { MutationPassThrough } from "@eshg/lib-portal/types/query";
+} from "@eshg/sti-protection-api";
 import { MutationOptions } from "@tanstack/react-query";
 
 import { useStiProtectionProcedureApi } from "@/lib/businessModules/stiProtection/api/clients";
@@ -46,13 +48,8 @@ export function useCreateStiProcedureMutation({
   ApiCreateProcedureRequest,
   ApiCreateProcedureResponse
 > = {}) {
-  const api = useStiProtectionProcedureApi();
-  return useHandledMutation({
-    mutationFn: (data: ApiCreateProcedureRequest) => api.createProcedure(data),
-    mutationKey: stiProtectionApiQueryKey(["procedures"]),
-    onSuccess,
-    onError,
-  });
+  const options = useCreateStiProcedureOptions({ onSuccess, onError });
+  return useHandledMutation(options);
 }
 
 export function useCloseProcedureMutation({
@@ -109,6 +106,43 @@ export function useReopenProcedure({
   });
 }
 
+interface CreateFollowUpProcedureParams {
+  id: string;
+  data: ApiCreateFollowUpProcedureRequest;
+}
+
+export function useCreateStiFollowUpProcedureOptions({
+  onSuccess,
+  onError,
+}: MutationPassThrough<
+  CreateFollowUpProcedureParams,
+  ApiCreateFollowUpProcedureResponse
+> = {}): MutationOptions<
+  ApiCreateFollowUpProcedureResponse,
+  Error,
+  CreateFollowUpProcedureParams
+> {
+  const api = useStiProtectionProcedureApi();
+  return {
+    mutationFn: ({ id, data }: CreateFollowUpProcedureParams) =>
+      api.createFollowUpProcedure(id, data),
+    mutationKey: stiProtectionApiQueryKey(["procedures"]),
+    onSuccess,
+    onError,
+  };
+}
+
+export function useCreateStiFollowUpProcedureMutation({
+  onSuccess,
+  onError,
+}: MutationPassThrough<
+  CreateFollowUpProcedureParams,
+  ApiCreateFollowUpProcedureResponse
+> = {}) {
+  const options = useCreateStiFollowUpProcedureOptions({ onSuccess, onError });
+  return useHandledMutation(options);
+}
+
 interface UpdatePersonDetailsParams {
   id: string;
   data: ApiUpdatePersonDetailsRequest;
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/textTemplates.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/textTemplates.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d8869effdb03e74bf2b5963d93f093c1561d0465
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/textTemplates.ts
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+import {
+  ApiCreateTextTemplateRequest,
+  ApiCreateTextTemplateResponse,
+  ApiTextTemplate,
+} from "@eshg/sti-protection-api";
+
+import { useTextTemplateApi } from "@/lib/businessModules/stiProtection/api/clients";
+
+import { MutationPassThrough } from "./types";
+
+export function useCreateTextTemplate({
+  onSuccess,
+  onError,
+}: MutationPassThrough<
+  ApiCreateTextTemplateResponse,
+  ApiCreateTextTemplateRequest
+> = {}) {
+  const appointmentTypeApi = useTextTemplateApi();
+  return useHandledMutation({
+    mutationFn: (template: ApiCreateTextTemplateRequest) =>
+      appointmentTypeApi.createTextTemplate(template),
+    onSuccess,
+    onError,
+  });
+}
+
+export function useUpdateTextTemplate({
+  onSuccess,
+  onError,
+}: MutationPassThrough<void, ApiTextTemplate> = {}) {
+  const appointmentTypeApi = useTextTemplateApi();
+  return useHandledMutation({
+    mutationFn: (template: ApiTextTemplate) =>
+      appointmentTypeApi.updateTextTemplate(template.externalId, template),
+    onSuccess,
+    onError,
+  });
+}
+
+export function useDeleteTextTemplate({
+  onSuccess,
+  onError,
+}: MutationPassThrough<void, string> = {}) {
+  const appointmentTypeApi = useTextTemplateApi();
+  return useHandledMutation({
+    mutationFn: (id: string) => appointmentTypeApi.deleteTextTemplate(id),
+    onSuccess,
+    onError,
+  });
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/waitingRoomApi.ts b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/waitingRoomApi.ts
index 339adb52e3dcb8eb2e20948bc082d16891b78691..0cba56591a235bbd3fa63e94d7eadad4f2a2efa3 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/mutations/waitingRoomApi.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/mutations/waitingRoomApi.ts
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { UpdateWaitingRoomDetailsRequest } from "@eshg/employee-portal-api/stiProtection";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { MutationPassThrough } from "@eshg/lib-portal/types/query";
+import { UpdateWaitingRoomDetailsRequest } from "@eshg/sti-protection-api";
 
 import { useWaitingRoomApi } from "@/lib/businessModules/stiProtection/api/clients";
 import { stiProtectionApiQueryKey } from "@/lib/businessModules/stiProtection/api/queries/apiQueryKeys";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/apiQueryKeys.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/apiQueryKeys.ts
index 8d3cb0b728d67d50646bdb3e23239f55cfb0f01c..14c93c93ba41f7dfb4204166228757a199e2d560 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/queries/apiQueryKeys.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/apiQueryKeys.ts
@@ -34,3 +34,6 @@ export const appointmentTypesApiQueryKey = queryKeyFactory(
 export const archivingApiQueryKey = queryKeyFactory(
   stiProtectionApiQueryKey(["archivingApi"]),
 );
+export const textTemplateApiQueryKey = queryKeyFactory(
+  stiProtectionApiQueryKey(["textTemplateApi"]),
+);
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/appointmentBlocks.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/appointmentBlocks.ts
index 6fc5e17e696ac73b1fa3c3fabfe8b65080c85c62..dec5d998feb565e57eb066448e3c41a808b31f89 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/queries/appointmentBlocks.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/appointmentBlocks.ts
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { mapPaginatedList } from "@eshg/lib-employee-portal/api/models/PaginatedList";
+import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import {
   ApiAppointmentType,
   ApiCreateDailyAppointmentBlockGroupRequest,
   GetAppointmentBlockGroupsRequest,
-} from "@eshg/employee-portal-api/stiProtection";
-import { mapPaginatedList } from "@eshg/lib-employee-portal/api/models/PaginatedList";
-import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+} from "@eshg/sti-protection-api";
 import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
 
 import { useAppointmentBlockApi } from "@/lib/businessModules/stiProtection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/appointmentTypes.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/appointmentTypes.ts
index 8778af79d42ca85ecd9f36b2ec3819ead305d3d3..db5c280e5d5d67a777ef71a521d06b771efb0c5c 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/queries/appointmentTypes.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/appointmentTypes.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { AppointmentTypeApi } from "@eshg/employee-portal-api/stiProtection";
+import { AppointmentTypeApi } from "@eshg/sti-protection-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import { useAppointmentTypeApi } from "@/lib/businessModules/stiProtection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/archiving.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/archiving.ts
index 7db3c0997c803a3a6c131ab05ced6760c45f2f0f..d3b44501bf794141533c786f8627961124647dad 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/queries/archiving.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/archiving.ts
@@ -6,7 +6,7 @@
 import {
   GetArchivableProceduresRequest,
   GetRelevantArchivableProceduresRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 
 import { useArchivingApi } from "@/lib/businessModules/stiProtection/api/clients";
 import { archivingApiQueryKey } from "@/lib/businessModules/stiProtection/api/queries/apiQueryKeys";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/identity.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/identity.ts
index 88a58efa26b82a0b386461bcc1afde8f485a916f..1ca685d0070f08f4a753dbe1071e1ad67083e550 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/queries/identity.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/identity.ts
@@ -5,6 +5,7 @@
 
 "use client";
 
+import { STATIC_QUERY_OPTIONS } from "@eshg/lib-portal/api/queryOptions";
 import { useQuery } from "@tanstack/react-query";
 
 import { useStiProtectionProcedureApi } from "@/lib/businessModules/stiProtection/api/clients";
@@ -23,5 +24,6 @@ export function usePinCheck(procedureId: string, pin: string | undefined) {
     },
     queryKey: ["pin-validation", procedureId, pin],
     enabled: pin != null,
+    staleTime: STATIC_QUERY_OPTIONS.staleTime,
   });
 }
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/medicalHistoryDocument.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/medicalHistoryDocument.ts
index 40897ec4e36a3c5105dbac476696fb6d0df1159e..5c96c1c477d37b9b0b037c3144de95e28ee47591 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/queries/medicalHistoryDocument.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/medicalHistoryDocument.ts
@@ -6,7 +6,7 @@
 import {
   ApiConcern,
   MedicalHistoryDocumentApi,
-} from "@eshg/employee-portal-api/stiProtection";
+} from "@eshg/sti-protection-api";
 import { useSuspenseQuery } from "@tanstack/react-query";
 
 import { useMedicalHistoryDocumentApi } from "@/lib/businessModules/stiProtection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/procedures.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/procedures.ts
index b34bd052c10420b0ee53b9dc4c63232974e5fecc..0b8e0cdc94e3efe07c2ab177e6c3c252e0ead7f3 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/queries/procedures.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/procedures.ts
@@ -5,12 +5,12 @@
 
 "use client";
 
+import { useFileDownload } from "@eshg/lib-portal/api/files/download";
 import {
   ApiGetStiProtectionProceduresSortBy,
   ApiGetStiProtectionProceduresSortOrder,
   ApiStiProtectionProcedureOverview,
-} from "@eshg/employee-portal-api/stiProtection";
-import { useFileDownload } from "@eshg/lib-portal/api/files/download";
+} from "@eshg/sti-protection-api";
 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query";
 
 import { useStiProtectionProcedureApi } from "@/lib/businessModules/stiProtection/api/clients";
@@ -83,11 +83,9 @@ const SortByMap: Record<
   string,
   ApiGetStiProtectionProceduresSortBy | undefined
 > = {
-  yearOfBirth: ApiGetStiProtectionProceduresSortBy.YearOfBirth,
-  gender: ApiGetStiProtectionProceduresSortBy.Gender,
-  status: ApiGetStiProtectionProceduresSortBy.Status,
-  concern: ApiGetStiProtectionProceduresSortBy.Concern,
   createdAt: ApiGetStiProtectionProceduresSortBy.CreatedAt,
+  sampleBarCode: ApiGetStiProtectionProceduresSortBy.SampleBarcode,
+  appointmentStart: ApiGetStiProtectionProceduresSortBy.Appointment,
 } as const satisfies Partial<
   Record<ColumnNames, ApiGetStiProtectionProceduresSortBy>
 >;
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/textTemplates.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/textTemplates.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5175b6d648a3d1eba2795b0edbb7a28210a4cdee
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/textTemplates.ts
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiTextTemplateContext } from "@eshg/sti-protection-api";
+import {
+  keepPreviousData,
+  queryOptions,
+  useSuspenseQuery,
+} from "@tanstack/react-query";
+
+import { useTextTemplateApi } from "@/lib/businessModules/stiProtection/api/clients";
+import { textTemplateApiQueryKey } from "@/lib/businessModules/stiProtection/api/queries/apiQueryKeys";
+
+export function useTextTemplatesQuery(contexts?: ApiTextTemplateContext[]) {
+  const textTemplateApi = useTextTemplateApi();
+  return queryOptions({
+    queryKey: textTemplateApiQueryKey(["list", ...(contexts ?? [])]),
+    queryFn: () => textTemplateApi.getTextTemplates(new Set(contexts)),
+    select: (response) => response.textTemplates,
+    placeholderData: keepPreviousData,
+  });
+}
+
+export function useTextTemplates(contexts?: ApiTextTemplateContext[]) {
+  return useSuspenseQuery(useTextTemplatesQuery(contexts));
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/api/queries/waitingRoomApi.ts b/employee-portal/src/lib/businessModules/stiProtection/api/queries/waitingRoomApi.ts
index 95beed7bed1479e63333a2ed1bfe36fa24199473..bec5144a50c2a702e011a90ba400a2f52b291efc 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/api/queries/waitingRoomApi.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/api/queries/waitingRoomApi.ts
@@ -6,7 +6,7 @@
 import {
   ApiGetWaitingRoomProceduresResponse,
   GetWaitingRoomProceduresRequest,
-} from "@eshg/employee-portal-api/stiProtection";
+} from "@eshg/sti-protection-api";
 import { useSuspenseQuery } from "@tanstack/react-query";
 
 import { useWaitingRoomApi } from "@/lib/businessModules/stiProtection/api/clients";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/AppointmentBlockGroupForm.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/AppointmentBlockGroupForm.tsx
index 32c9dcae496dbcece97f53817057f51b4e358a4b..9fbc8d3b1366679e73e561fb70c44fd38824a412 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/AppointmentBlockGroupForm.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/AppointmentBlockGroupForm.tsx
@@ -3,13 +3,12 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
 import {
   ApiAppointmentType,
   ApiAppointmentTypeConfig,
   ApiUser,
-} from "@eshg/employee-portal-api/stiProtection";
-import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
-import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+} from "@eshg/sti-protection-api";
 import { Divider, Stack } from "@mui/joy";
 import { Formik, FormikErrors } from "formik";
 import { isDefined, isEmpty, mapToObj } from "remeda";
@@ -20,12 +19,12 @@ import { routes } from "@/lib/businessModules/stiProtection/shared/routes";
 import { AppointmentBlockGroupValuesWithDays } from "@/lib/shared/components/appointmentBlocks/AppointmentBlockFormWithDays";
 import { AppointmentBlockGroupFields } from "@/lib/shared/components/appointmentBlocks/AppointmentBlockGroupFields";
 import { AppointmentCountWithDays } from "@/lib/shared/components/appointmentBlocks/AppointmentCountWithDays";
+import { StaffUser } from "@/lib/shared/components/appointmentBlocks/AppointmentStaffField";
 import { AppointmentStaffSelection } from "@/lib/shared/components/appointmentBlocks/AppointmentStaffSelection";
 import { validateAppointmentBlock } from "@/lib/shared/components/appointmentBlocks/validateAppointmentBlock";
 import { ConfirmLeaveDirtyFormEffect } from "@/lib/shared/components/form/ConfirmLeaveDirtyFormEffect";
 import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
 import { FormSheet } from "@/lib/shared/components/form/FormSheet";
-import { fullName } from "@/lib/shared/components/users/userFormatter";
 import { validateFieldArray } from "@/lib/shared/helpers/validators";
 
 import { mapFormValues } from "./CreateAppointmentBlockGroupForm";
@@ -87,10 +86,11 @@ function validateForm(
   return errors;
 }
 
-function userToOption(user: ApiUser): SelectOption {
+function userToOption(user: ApiUser): StaffUser {
   return {
-    value: user.userId,
-    label: fullName(user),
+    userId: user.userId,
+    firstName: user.firstName,
+    lastName: user.lastName,
   };
 }
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/AppointmentBlockGroupsTable.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/AppointmentBlockGroupsTable.tsx
index 30f3e9674dd22ef96b2ec7d3c77072525c6e789f..7eda2793d76e5b447fd0303547a9d63db0ee5900 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/AppointmentBlockGroupsTable.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/AppointmentBlockGroupsTable.tsx
@@ -5,11 +5,11 @@
 
 "use client";
 
+import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import {
   ApiAppointmentBlockSortKey,
   ApiAppointmentType,
-} from "@eshg/employee-portal-api/stiProtection";
-import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+} from "@eshg/sti-protection-api";
 import { Chip } from "@mui/joy";
 import { ColumnSort, Row, createColumnHelper } from "@tanstack/react-table";
 import { ReactNode } from "react";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/CreateAppointmentBlockGroupForm.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/CreateAppointmentBlockGroupForm.tsx
index 1d8ca29b7f7da80e944f4fd72b44bd72c173a2ab..a37b9cb1231ca58a66a5031e8bd9c23e2a0c545a 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/CreateAppointmentBlockGroupForm.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/CreateAppointmentBlockGroupForm.tsx
@@ -5,13 +5,13 @@
 
 "use client";
 
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { mapRequiredValue } from "@eshg/lib-portal/helpers/form";
 import {
   ApiAppointmentType,
   ApiCreateDailyAppointmentBlock,
   ApiCreateDailyAppointmentBlockGroupRequest,
-} from "@eshg/employee-portal-api/stiProtection";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
-import { mapRequiredValue } from "@eshg/lib-portal/helpers/form";
+} from "@eshg/sti-protection-api";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { useRouter } from "next/navigation";
 import { useEffect, useMemo, useState } from "react";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/options.ts b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/options.ts
index 1de62f852a5d49bb228481c4e9d8c9460fe87492..c12e28360f10042862ea8d267e31b3b1a7f31cb3 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/options.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentBlocks/options.ts
@@ -3,12 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiAppointmentType,
-  ApiConcern,
-} from "@eshg/employee-portal-api/stiProtection";
 import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
+import { ApiAppointmentType, ApiConcern } from "@eshg/sti-protection-api";
 
 import { APPOINTMENT_TYPES } from "@/lib/businessModules/stiProtection/shared/constants";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/AppointmentTypeEditForm.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/AppointmentTypeEditForm.tsx
index 176f49a57e44b482e896ca0c5c366bdbedf9cb6e..eed6931f80a0b2e5813210c4a2f88a7a61887568 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/AppointmentTypeEditForm.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/AppointmentTypeEditForm.tsx
@@ -5,9 +5,9 @@
 
 "use client";
 
-import { ApiAppointmentType } from "@eshg/employee-portal-api/stiProtection";
 import { BaseField } from "@eshg/lib-portal/components/formFields/BaseField";
 import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/autocomplete/SingleAutocompleteField";
+import { ApiAppointmentType } from "@eshg/sti-protection-api";
 import { FormLabel, Input, Stack, Typography } from "@mui/joy";
 import { Formik } from "formik";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/AppointmentTypeOverviewTable.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/AppointmentTypeOverviewTable.tsx
index d329c005920de1909c49760d82675a8e9cdd7f49..2515e4959c963830d830de2cbd5119540f0d9a45 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/AppointmentTypeOverviewTable.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/AppointmentTypeOverviewTable.tsx
@@ -5,8 +5,8 @@
 
 "use client";
 
-import { ApiAppointmentTypeConfig } from "@eshg/employee-portal-api/stiProtection";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { ApiAppointmentTypeConfig } from "@eshg/sti-protection-api";
 import { FormikProps } from "formik";
 import { useRef, useState } from "react";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/columns.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/columns.tsx
index 3e8d5e0d340531f39b11293bb7a5b9b9aa66c01f..d5dc6ec47cb79e7fc4e34fd398f9643143fc09ce 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/columns.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/appointmentTypes/columns.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiAppointmentTypeConfig } from "@eshg/employee-portal-api/stiProtection";
+import { ApiAppointmentTypeConfig } from "@eshg/sti-protection-api";
 import { Edit } from "@mui/icons-material";
 import { ColumnHelper, createColumnHelper } from "@tanstack/react-table";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/procedures/proceduresTable/StiProtectionProceduresTable.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/procedures/proceduresTable/StiProtectionProceduresTable.tsx
index 6e0dc14d3a09731c9406ba6cfae9fa0c954f4918..0d659968e7c918c25ee5e71c293969a4a4ccccb0 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/procedures/proceduresTable/StiProtectionProceduresTable.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/procedures/proceduresTable/StiProtectionProceduresTable.tsx
@@ -5,10 +5,13 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
-import { ApiStiProtectionProcedureOverview } from "@eshg/employee-portal-api/stiProtection";
 import { Row } from "@eshg/lib-portal/components/Row";
-import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import {
+  formatDate,
+  formatDateTime,
+} from "@eshg/lib-portal/formatters/dateTime";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
+import { ApiStiProtectionProcedureOverview } from "@eshg/sti-protection-api";
 import { EditOutlined, ToggleOffOutlined } from "@mui/icons-material";
 import { useSuspenseQueries } from "@tanstack/react-query";
 import { ColumnSort, createColumnHelper } from "@tanstack/react-table";
@@ -22,6 +25,7 @@ import {
 import {
   CONCERN_VALUES,
   GENDER_VALUES,
+  LAB_STATUS_VALUES,
   PROCEDURE_STATUS_VALUES,
 } from "@/lib/businessModules/stiProtection/shared/constants";
 import { isProcedureOpen } from "@/lib/businessModules/stiProtection/shared/helpers";
@@ -54,10 +58,20 @@ function getProceduresColumns({
   reopenDialog: UseCloseAndReopenConfirmationDialog;
 }) {
   return [
+    columnHelper.accessor("accessCode", {
+      header: "Anmeldecode",
+      cell: ({ getValue }) => getValue(),
+      enableSorting: false,
+      meta: {
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
     columnHelper.accessor("yearOfBirth", {
       header: "Geburtsjahr",
       cell: ({ getValue }) => getValue(),
-      enableSorting: true,
+      enableSorting: false,
       meta: {
         canNavigate: {
           parentRow: true,
@@ -67,7 +81,7 @@ function getProceduresColumns({
     columnHelper.accessor("gender", {
       header: "Geschlecht",
       cell: ({ getValue }) => GENDER_VALUES[getValue()],
-      enableSorting: true,
+      enableSorting: false,
       meta: {
         canNavigate: {
           parentRow: true,
@@ -77,6 +91,16 @@ function getProceduresColumns({
     columnHelper.accessor("status", {
       header: "Status",
       cell: ({ getValue }) => PROCEDURE_STATUS_VALUES[getValue()],
+      enableSorting: false,
+      meta: {
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("appointmentStart", {
+      header: "Termin",
+      cell: ({ getValue }) => formatDateTime(getValue()),
       enableSorting: true,
       meta: {
         canNavigate: {
@@ -87,7 +111,7 @@ function getProceduresColumns({
     columnHelper.accessor("concern", {
       header: "Anliegen",
       cell: ({ getValue }) => CONCERN_VALUES[getValue()],
-      enableSorting: true,
+      enableSorting: false,
       meta: {
         canNavigate: {
           parentRow: true,
@@ -95,7 +119,7 @@ function getProceduresColumns({
       },
     }),
     columnHelper.accessor("createdAt", {
-      header: "Erstell.",
+      header: "Erstellt",
       cell: ({ getValue }) => formatDate(getValue()),
       enableSorting: true,
       meta: {
@@ -104,6 +128,26 @@ function getProceduresColumns({
         },
       },
     }),
+    columnHelper.accessor("sampleBarCode", {
+      header: "Labor-Barcode",
+      cell: ({ getValue }) => getValue(),
+      enableSorting: true,
+      meta: {
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("labStatus", {
+      header: "Laborstatus",
+      cell: ({ getValue }) => LAB_STATUS_VALUES[getValue()],
+      enableSorting: false,
+      meta: {
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
     columnHelper.display({
       id: "actions",
       header: "Aktionen",
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateAccordion.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateAccordion.tsx
index ebf2ffa174b02502133953d6387028046c495d95..e9e22b96324c6082161d913342b2b2a8a5e9ec8f 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateAccordion.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateAccordion.tsx
@@ -17,16 +17,18 @@ import { useTransition } from "react";
 
 import { AddTextTemplate } from "@/lib/shared/components/icons/AddTextTemplate";
 
-import { useTextTemplatesSidebar } from "./TextTemplatesSidebarProvider";
+import { AppendText } from "./TextTemplatesSidebar";
 
 export function TextTemplateAccordion({
   name,
-  text,
+  content,
   index,
+  appendText,
 }: {
   name: string;
-  text: string;
+  content: string;
   index: number;
+  appendText: AppendText;
 }) {
   return (
     <Accordion
@@ -45,10 +47,14 @@ export function TextTemplateAccordion({
         >
           {name}
         </AccordionSummary>
-        <AddTextTemplateButton text={text} index={index} />
+        <AddTextTemplateButton
+          text={content}
+          appendText={appendText}
+          index={index}
+        />
       </Row>
       <AccordionDetails>
-        <Typography padding={2}>{text}</Typography>
+        <Typography padding={2}>{content}</Typography>
       </AccordionDetails>
     </Accordion>
   );
@@ -57,7 +63,7 @@ export function TextTemplateAccordion({
 const AnimatedIconButton = styled(IconButton)(({ theme }) => ({
   transition: "all 300ms",
   "&[aria-disabled=true]": {
-    "background-color": theme.palette.success.plainActiveBg,
+    backgroundColor: theme.palette.success.plainActiveBg,
     borderColor: "transparent",
     cursor: "default",
     ".MuiSvgIcon-root": { color: theme.palette.success.outlinedColor },
@@ -67,12 +73,14 @@ const AnimatedIconButton = styled(IconButton)(({ theme }) => ({
 function AddTextTemplateButton({
   text,
   index,
+  appendText,
 }: {
   text: string;
   index: number;
+  appendText: AppendText;
 }) {
   const [isAppending, startAppending] = useTransition();
-  const { appendText } = useTextTemplatesSidebar();
+  // const { appendText } = useTextTemplatesSidebar();
 
   function onClick() {
     if (isAppending) {
@@ -87,6 +95,7 @@ function AddTextTemplateButton({
   return (
     <AnimatedIconButton
       aria-keyshortcuts={`${shortcut}`}
+      color={"primary"}
       variant={"outlined"}
       aria-disabled={isAppending}
       title={`Vorlage einfügen${shortcut ? ` (${shortcut})` : ""}`}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateEditSidebar.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateEditSidebar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..102c0e87958e3621c1a51f467e13860ebb96359b
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateEditSidebar.tsx
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
+import {
+  ApiCreateTextTemplateRequest,
+  ApiTextTemplate,
+  ApiTextTemplateContext,
+} from "@eshg/sti-protection-api";
+import { Button } from "@mui/joy";
+import { Formik } from "formik";
+import { ReactNode } from "react";
+
+import { ButtonBar } from "@/lib/shared/components/buttons/ButtonBar";
+import { SidebarForm } from "@/lib/shared/components/form/SidebarForm";
+import { Sidebar } from "@/lib/shared/components/sidebar/Sidebar";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+
+import { TextTemplateFields } from "./TextTemplateFields";
+
+interface TextTemplateEditSidebarProps {
+  title: string;
+  isOpen: boolean;
+  onClose: () => void;
+}
+
+interface TextTemplateEditSidebarCreateProps
+  extends TextTemplateEditSidebarProps {
+  onCreate: (values: ApiCreateTextTemplateRequest) => Promise<void>;
+}
+
+interface TextTemplateEditSidebarEditProps
+  extends TextTemplateEditSidebarProps {
+  onUpdate: (values: ApiTextTemplate) => Promise<void>;
+  initialValues: ApiTextTemplate | undefined;
+}
+
+interface InitialFormData {
+  content: string;
+  context: ApiTextTemplateContext | null;
+  name: string;
+}
+const defaultValues: InitialFormData = {
+  context: null,
+  content: "",
+  name: "",
+};
+
+export function TextTemplateEditSidebar(
+  props: TextTemplateEditSidebarCreateProps,
+): ReactNode;
+export function TextTemplateEditSidebar(
+  props: TextTemplateEditSidebarEditProps,
+): ReactNode;
+export function TextTemplateEditSidebar({
+  title,
+  isOpen,
+  onClose,
+  ...props
+}:
+  | TextTemplateEditSidebarCreateProps
+  | TextTemplateEditSidebarEditProps): ReactNode {
+  const initialValues =
+    "initialValues" in props ? props.initialValues : defaultValues;
+
+  if (initialValues == null) {
+    return null;
+  }
+
+  return (
+    <Sidebar open={isOpen} onClose={onClose}>
+      <Formik
+        enableReinitialize
+        initialValues={initialValues}
+        onSubmit={async (values, helpers) => {
+          await ("onUpdate" in props
+            ? props.onUpdate(values as ApiTextTemplate)
+            : props.onCreate(values as ApiCreateTextTemplateRequest));
+          helpers.resetForm();
+        }}
+      >
+        <SidebarForm>
+          <SidebarContent title={title}>
+            <TextTemplateFields />
+          </SidebarContent>
+          <SidebarActions>
+            <ButtonBar
+              left={
+                <Button variant="plain" onClick={onClose}>
+                  Abbrechen
+                </Button>
+              }
+              right={<SubmitButton submitting={false}>Speichern</SubmitButton>}
+            />
+          </SidebarActions>
+        </SidebarForm>
+      </Formik>
+    </Sidebar>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateFields.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateFields.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..5578f323a15fda5d86357eb8690385eb407d9585
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplateFields.tsx
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Alert } from "@eshg/lib-portal/components/Alert";
+import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
+import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
+import { Stack } from "@mui/joy";
+
+import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
+
+import { TextTemplateContextOptions } from "./constants";
+
+export function TextTemplateFields() {
+  return (
+    <Stack gap={2}>
+      <InputField
+        label="Name"
+        name="name"
+        required="Bitte einen Namen angeben"
+      />
+      <SelectField
+        label="Kontext"
+        name="context"
+        options={TextTemplateContextOptions}
+        required="Bitte einen Kontext auswählen"
+      />
+      <TextareaField
+        label="Inhalt"
+        name="content"
+        required="Bitte Text eingeben"
+        placeholder="z.B. Wert-Name: $Eingabe"
+      />
+      <Alert
+        color="primary"
+        message={
+          <>
+            Das <strong>$</strong>-Zeichen kann als Platzhalter verwendet
+            werden. Nach dem Einfügen kann man zwischen den Platzhalter mit{" "}
+            <strong>Strg+Leertaste</strong> oder <strong>Strg+Eingabe</strong>{" "}
+            springen.
+          </>
+        }
+      />
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesOverviewTable.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesOverviewTable.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..991b72864018b10545df98134725140ea19b6a1e
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesOverviewTable.tsx
@@ -0,0 +1,128 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+"use client";
+
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import {
+  ApiCreateTextTemplateRequest,
+  ApiTextTemplate,
+} from "@eshg/sti-protection-api";
+import { Add } from "@mui/icons-material";
+import { Button, Stack } from "@mui/joy";
+import { useState } from "react";
+
+import {
+  useCreateTextTemplate,
+  useDeleteTextTemplate,
+  useUpdateTextTemplate,
+} from "@/lib/businessModules/stiProtection/api/mutations/textTemplates";
+import { useTextTemplates } from "@/lib/businessModules/stiProtection/api/queries/textTemplates";
+import { EmployeePortalConfirmationDialog } from "@/lib/shared/components/confirmationDialog/EmployeePortalConfirmationDialog";
+import { DataTable } from "@/lib/shared/components/table/DataTable";
+import { TableSheet } from "@/lib/shared/components/table/TableSheet";
+import { useSearchParam } from "@/lib/shared/hooks/searchParams/useSearchParam";
+
+import { TextTemplateEditSidebar } from "./TextTemplateEditSidebar";
+import { textTemplateColumns } from "./TextTemplatesOverviewTableColumns";
+
+export function TextTemplatesOverviewTable() {
+  const [sidebarOpenId, setSidebarOpenId] = useSearchParam("edit", "string");
+  const [isNewSidebarOpen, setNewSidebarOpen] = useSearchParam(
+    "new",
+    "boolean",
+  );
+  const [confirmingDelete, setConfirmingDelete] = useState<
+    string | undefined
+  >();
+  const snackbar = useSnackbar();
+
+  const addMutation = useCreateTextTemplate({
+    onSuccess: () => {
+      snackbar.confirmation("Die Vorlage wurde erzeugt.");
+    },
+  });
+  const updateMutation = useUpdateTextTemplate({
+    onSuccess: () => {
+      snackbar.confirmation("Der Vorlage wurde aktualisiert.");
+    },
+  });
+  const deleteMutation = useDeleteTextTemplate({
+    onSuccess: () => {
+      snackbar.confirmation("Die Vorlage wurde gelöscht.");
+    },
+  });
+
+  const { data: textTemplates } = useTextTemplates();
+  const selectedTemplate = textTemplates.find(
+    (t) => t.externalId === sidebarOpenId,
+  );
+
+  async function onUpdate(data: ApiTextTemplate) {
+    await updateMutation.mutateAsync(data);
+    setSidebarOpenId(null);
+  }
+
+  async function onCreate(data: ApiCreateTextTemplateRequest) {
+    await addMutation.mutateAsync(data);
+    setNewSidebarOpen(false);
+  }
+
+  async function deleteTemplate() {
+    if (confirmingDelete == null) {
+      return;
+    }
+    await deleteMutation.mutateAsync(confirmingDelete);
+    setConfirmingDelete(undefined);
+  }
+
+  return (
+    <Stack gap={3}>
+      <Button
+        sx={{ alignSelf: "end" }}
+        startDecorator={<Add />}
+        onClick={() => setNewSidebarOpen(true)}
+      >
+        Vorlage hinzufügen
+      </Button>
+      <TableSheet aria-label="Tabelle der Textvorlagen">
+        <DataTable
+          data={textTemplates}
+          columns={textTemplateColumns({
+            onEdit: ({ externalId }) => setSidebarOpenId(externalId),
+            onDelete: ({ externalId }) => setConfirmingDelete(externalId),
+          })}
+        />
+      </TableSheet>
+      <EmployeePortalConfirmationDialog
+        open={confirmingDelete != null}
+        title="Vorlage löschen?"
+        description="Möchten Sie die Vorlage “Rechtliche Grundlage” wirklich löschen? Die Aktion kann nicht rückgängig gemacht werden."
+        confirmLabel="Löschen"
+        color="danger"
+        onCancel={() => {
+          setConfirmingDelete(undefined);
+        }}
+        onClose={() => {
+          setConfirmingDelete(undefined);
+        }}
+        onConfirm={deleteTemplate}
+      />
+      <TextTemplateEditSidebar
+        title={"Vorlage bearbeiten"}
+        isOpen={sidebarOpenId != null}
+        initialValues={selectedTemplate}
+        onClose={() => setSidebarOpenId(null)}
+        onUpdate={onUpdate}
+      />
+      <TextTemplateEditSidebar
+        title={"Vorlage hinzufügen"}
+        isOpen={isNewSidebarOpen}
+        onCreate={onCreate}
+        onClose={() => setNewSidebarOpen(false)}
+      />
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesOverviewTableColumns.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesOverviewTableColumns.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..79438716610e9d54f25adb81e7e7fa22524c8be6
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesOverviewTableColumns.tsx
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiTextTemplate } from "@eshg/sti-protection-api";
+import { Delete, Edit } from "@mui/icons-material";
+import { createColumnHelper } from "@tanstack/react-table";
+
+import { ActionsMenu } from "@/lib/shared/components/buttons/ActionsMenu";
+
+import { TextTemplateContextLabels } from "./constants";
+
+interface RowActions {
+  onEdit: (t: ApiTextTemplate) => void;
+  onDelete: (t: ApiTextTemplate) => void;
+}
+export function textTemplateColumns({ onEdit, onDelete }: RowActions) {
+  const columnHelper = createColumnHelper<ApiTextTemplate>();
+  return [
+    columnHelper.accessor("name", {
+      header: "Name",
+      cell: (props) => props.getValue(),
+      meta: {
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("context", {
+      header: "Kontext",
+      sortingFn: (a, b) =>
+        TextTemplateContextLabels[a.original.context].localeCompare(
+          TextTemplateContextLabels[b.original.context],
+        ),
+      cell: (props) => TextTemplateContextLabels[props.getValue()],
+      meta: {
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.accessor("content", {
+      header: "Inhalt",
+      cell: (props) => props.getValue(),
+      meta: {
+        canNavigate: {
+          parentRow: true,
+        },
+      },
+    }),
+    columnHelper.display({
+      header: "Aktionen",
+      id: "navigationControl",
+      cell: (props) => (
+        <ActionsMenu
+          actionItems={[
+            {
+              label: "Bearbeiten",
+              startDecorator: <Edit />,
+              onClick: () => onEdit(props.row.original),
+            },
+            {
+              label: "Löschen",
+              startDecorator: <Delete />,
+              onClick: () => onDelete(props.row.original),
+              color: "danger",
+            },
+          ]}
+        />
+      ),
+      meta: {
+        width: 96,
+        cellStyle: "button",
+      },
+    }),
+  ];
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesSidebar.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesSidebar.tsx
index d6c692d7e6744acef8153404306cfa731eebcc9c..6827017b4a65331668f9746fe3257db0a5f7bc00 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesSidebar.tsx
@@ -4,6 +4,7 @@
  */
 
 import { InternalLinkButton } from "@eshg/lib-portal/components/navigation/InternalLinkButton";
+import { ApiTextTemplateContext } from "@eshg/sti-protection-api";
 import { OpenInNew } from "@mui/icons-material";
 import {
   AccordionGroup,
@@ -13,26 +14,38 @@ import {
   Select,
   Stack,
 } from "@mui/joy";
-import { KeyboardEvent, useId, useRef } from "react";
+import {
+  MutableRefObject,
+  useCallback,
+  useEffect,
+  useId,
+  useRef,
+  useState,
+} from "react";
 
+import { useTextTemplates } from "@/lib/businessModules/stiProtection/api/queries/textTemplates";
 import { routes } from "@/lib/businessModules/stiProtection/shared/routes";
-import { Sidebar } from "@/lib/shared/components/sidebar/Sidebar";
 import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
 import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
 
 import { TextTemplateAccordion } from "./TextTemplateAccordion";
-import { useTextTemplatesSidebar } from "./TextTemplatesSidebarProvider";
-import { ExampleTextTemplates, TextTemplateContextOptions } from "./constants";
+import { TextTemplateContextOptions } from "./constants";
 
-export function TextTemplatesSidebar() {
-  const { isOpen, close, context } = useTextTemplatesSidebar();
-  const accordionsRef = useRef<HTMLDivElement | null>(null);
+export type AppendText = (text: string) => Promise<void> | undefined;
+interface TextTemplatesSidebarProps {
+  onClose: () => void;
+  context: ApiTextTemplateContext;
+  appendTextRef: MutableRefObject<AppendText | null>;
+}
 
-  const textTemplates = ExampleTextTemplates.filter(
-    (k) => k.context === context,
-  );
+export function TextTemplatesSidebar({
+  onClose,
+  context,
+  appendTextRef,
+}: TextTemplatesSidebarProps) {
+  const accordionsRef = useRef<HTMLDivElement | null>(null);
 
-  function onKeyDown(e: KeyboardEvent) {
+  const onKeyDown = useCallback((e: KeyboardEvent) => {
     const index = parseInt(e.key);
     if (isNaN(index)) {
       return;
@@ -41,47 +54,84 @@ export function TextTemplatesSidebar() {
       `button[aria-keyshortcuts="${index}"]`,
     ) as HTMLElement | undefined;
     button?.click();
+  }, []);
+
+  function appendText(text: string) {
+    if (appendTextRef.current == null) {
+      return;
+    }
+    return appendTextRef.current(text);
   }
 
+  useEffect(() => {
+    window.addEventListener("keydown", onKeyDown);
+    return () => window.removeEventListener("keydown", onKeyDown);
+  }, [onKeyDown]);
+
   return (
-    <div onKeyDown={onKeyDown}>
-      <Sidebar open={isOpen} onClose={close}>
-        <SidebarContent title={"Textvorlage einfügen"}>
-          <Stack gap={2}>
-            <ContextSelect />
-            <AccordionGroup sx={{ gap: 1 }} ref={accordionsRef}>
-              <Divider />
-              {textTemplates.map(({ name, text }, index) => (
-                <TextTemplateAccordion
-                  key={name}
-                  name={name}
-                  text={text}
-                  index={index}
-                />
-              ))}
-            </AccordionGroup>
-            <InternalLinkButton
-              href={routes.textTemplates}
-              sx={{ alignSelf: "start" }}
-              variant="plain"
-              endDecorator={<OpenInNew />}
-            >
-              Textvorlagen verwalten
-            </InternalLinkButton>
-          </Stack>
-        </SidebarContent>
-        <SidebarActions>
-          <Button onClick={close} sx={{ alignSelf: "end" }}>
-            Schließen
-          </Button>
-        </SidebarActions>
-      </Sidebar>
-    </div>
+    <>
+      <SidebarContent title={"Textvorlage einfügen"}>
+        <TextTemplatesSidebarContent
+          context={context}
+          appendText={appendText}
+          accordionsRef={accordionsRef}
+        />
+      </SidebarContent>
+      <SidebarActions>
+        <Button onClick={onClose} sx={{ alignSelf: "end" }}>
+          Schließen
+        </Button>
+      </SidebarActions>
+    </>
+  );
+}
+interface TextTemplatesSidebarContentProps
+  extends Pick<TextTemplatesSidebarProps, "context"> {
+  appendText: AppendText;
+  accordionsRef: MutableRefObject<HTMLDivElement | null>;
+}
+export function TextTemplatesSidebarContent({
+  context: givenContext,
+  appendText,
+  accordionsRef,
+}: TextTemplatesSidebarContentProps) {
+  const [context, setContext] = useState<ApiTextTemplateContext | null>(
+    givenContext,
+  );
+  const filterContexts = context == null ? undefined : [context];
+  const { data: textTemplates } = useTextTemplates(filterContexts);
+  return (
+    <Stack gap={2}>
+      <ContextSelect context={context} setContext={setContext} />
+      <AccordionGroup sx={{ gap: 1 }} ref={accordionsRef}>
+        <Divider />
+        {textTemplates.map(({ name, content }, index) => (
+          <TextTemplateAccordion
+            key={name}
+            name={name}
+            content={content}
+            index={index}
+            appendText={appendText}
+          />
+        ))}
+      </AccordionGroup>
+      <InternalLinkButton
+        href={routes.textTemplates}
+        sx={{ alignSelf: "start" }}
+        variant="plain"
+        endDecorator={<OpenInNew />}
+      >
+        Textvorlagen verwalten
+      </InternalLinkButton>
+    </Stack>
   );
 }
 
-export function ContextSelect() {
-  const { context, setContext } = useTextTemplatesSidebar();
+interface ContextSelectProps {
+  context: ApiTextTemplateContext | null;
+  setContext: (c: ApiTextTemplateContext | null) => void;
+}
+export function ContextSelect({ context, setContext }: ContextSelectProps) {
   const buttonId = useId();
   const labelId = useId();
   return (
@@ -91,8 +141,13 @@ export function ContextSelect() {
       </label>
       <Select
         slotProps={{ button: { id: buttonId, "aria-labelledby": labelId } }}
-        value={context ?? null}
-        onChange={(_e, newValue) => setContext(newValue)}
+        value={context}
+        onChange={(_e, newValue) => {
+          if (!newValue) {
+            return;
+          }
+          setContext(newValue);
+        }}
       >
         {TextTemplateContextOptions.map((option, index) => (
           <Option key={index} label={option.label} value={option.value}>
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesSidebarProvider.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesSidebarProvider.tsx
deleted file mode 100644
index b37cf5d9dd3e70baf05fc73e7654558b0a9d1aee..0000000000000000000000000000000000000000
--- a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesSidebarProvider.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-
-import {
-  MutableRefObject,
-  PropsWithChildren,
-  createContext,
-  useContext,
-  useState,
-} from "react";
-
-import { TextTemplatesSidebar } from "./TextTemplatesSidebar";
-import { ApiTextTemplateContext } from "./constants";
-import { UseFieldHandle } from "./useFieldHandle";
-
-const TextTemplatesContext = createContext<
-  TextTemplatesSidebarContext | undefined
->(undefined);
-
-export function TextTemplatesSidebarProvider({ children }: PropsWithChildren) {
-  const [context, setContext] = useState<ApiTextTemplateContext | null>(null);
-  const [fieldHandleRef, setFieldHandleRef] = useState<FieldHandleRef>();
-
-  function open(
-    context: ApiTextTemplateContext,
-    setFieldValue: FieldHandleRef,
-  ) {
-    setContext(context);
-    setFieldHandleRef(setFieldValue);
-  }
-  function close() {
-    fieldHandleRef?.current?.finishEditing();
-    setContext(null);
-    setFieldHandleRef(undefined);
-  }
-  async function appendText(text: string) {
-    if (fieldHandleRef?.current == null) {
-      throw Error("No referenced TextArea to append to");
-    }
-    await fieldHandleRef.current.appendText(text);
-  }
-
-  return (
-    <TextTemplatesContext.Provider
-      value={{
-        context,
-        setContext,
-        open,
-        close,
-        isOpen: context != null,
-        appendText,
-      }}
-    >
-      {children}
-      <TextTemplatesSidebar />
-    </TextTemplatesContext.Provider>
-  );
-}
-type FieldSetter = (text: string) => Promise<void>;
-type FieldHandleRef = MutableRefObject<UseFieldHandle | null>;
-export interface TextTemplatesSidebarContext {
-  isOpen: boolean;
-  context: ApiTextTemplateContext | null;
-  setContext: (context: ApiTextTemplateContext | null) => void;
-  open: (
-    context: ApiTextTemplateContext,
-    setFieldValue: FieldHandleRef,
-  ) => void;
-  close: () => void;
-  appendText: FieldSetter;
-}
-
-export function useTextTemplatesSidebar() {
-  const context = useContext(TextTemplatesContext);
-  if (!context) {
-    throw Error("No TextTemplatesProvider found.");
-  }
-  return context;
-}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates.tsx
index a02a67c359f245a8c81e90c13b0a7dc7e5daf68a..8ab1ed2c70156a126b6dac1cf001ad3d8924bfad 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates.tsx
@@ -3,8 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { ApiTextTemplateContext } from "@eshg/sti-protection-api";
 import { Add } from "@mui/icons-material";
-import { Button } from "@mui/joy";
+import { Button, styled } from "@mui/joy";
 import { useFormikContext } from "formik";
 import { KeyboardEvent, useRef } from "react";
 
@@ -14,13 +15,13 @@ import {
   TextareaFieldProps,
 } from "@/lib/shared/components/formFields/TextareaField";
 
-import { useTextTemplatesSidebar } from "./TextTemplatesSidebarProvider";
-import { ApiTextTemplateContext } from "./constants";
+import { AppendText, TextTemplatesSidebar } from "./TextTemplatesSidebar";
 import {
-  UseFieldHandle,
+  appendText,
   nextInsertPoint,
-  useFieldHandle,
-} from "./useFieldHandle";
+  selectFirstPoint,
+} from "./nextInsertPoint";
+import { useSidebarFromSearchParam } from "./useSidebarFromSearchParam";
 
 export interface TextareaWithTextTemplatesProps extends TextareaFieldProps {
   context: ApiTextTemplateContext;
@@ -30,17 +31,28 @@ export function TextareaFieldWithTextTemplates({
   context,
   ...props
 }: TextareaWithTextTemplatesProps) {
-  const { open } = useTextTemplatesSidebar();
-  const { getFieldMeta } = useFormikContext();
+  const { setFieldValue, getFieldMeta } = useFormikContext();
   const { value } = getFieldMeta(props.name);
 
   const ref = useRef<HTMLTextAreaElement | null>(null);
-  const setterRef = useRef<UseFieldHandle | null>(null);
-  setterRef.current = useFieldHandle({ name: props.name, ref });
+  const appendTextRef = useRef<AppendText | null>(null);
+  appendTextRef.current = async (text) => {
+    await setFieldValue(props.name, appendText(text, value));
+  };
 
-  function setOpen() {
-    open(context, setterRef);
-  }
+  const { open } = useSidebarFromSearchParam({
+    component: TextTemplatesSidebar,
+    paramName: "text-template",
+    paramValue: props.name,
+    props: {
+      context,
+      appendTextRef,
+    },
+    afterClose() {
+      selectFirstPoint(ref.current);
+    },
+    fallbackTitle: "Textvorlage einfügen",
+  });
 
   function onKeyDown(e: KeyboardEvent<HTMLTextAreaElement>) {
     if (ref.current == null) {
@@ -50,7 +62,7 @@ export function TextareaFieldWithTextTemplates({
     if (e.code === "Space" && e.ctrlKey) {
       insertionPoint = nextInsertPoint(value, ref.current.selectionEnd ?? 0);
       if (insertionPoint == null) {
-        setOpen();
+        open();
       }
     } else if (e.code === "Enter" && e.ctrlKey) {
       insertionPoint =
@@ -65,10 +77,9 @@ export function TextareaFieldWithTextTemplates({
     ref.current.selectionStart = insertionPoint.start;
     ref.current.selectionEnd = insertionPoint.end;
   }
-
   return (
     <FieldSetColumn gap={1} alignItems="start">
-      <TextareaField
+      <StyledTextarea
         {...props}
         slotProps={{ textarea: { ref, rows: 20, onKeyDownCapture: onKeyDown } }}
       />
@@ -76,11 +87,15 @@ export function TextareaFieldWithTextTemplates({
         startDecorator={<Add />}
         aria-keyshortcuts="Control+Space"
         variant="plain"
-        onClick={setOpen}
-        title="Textvorlage Menü Öffnen (Strg+Leertaste)"
+        onClick={open}
+        title="Menü der Textvorlagen öffnen (Strg+Leertaste)"
       >
         Textvorlage einfügen
       </Button>
     </FieldSetColumn>
   );
 }
+
+const StyledTextarea = styled(TextareaField)(() => ({
+  width: "100%",
+}));
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/constants.ts b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/constants.ts
index 9e6a8f747df885d7bfae5fc3eda74d56d687eff6..1bf10c3d30a338814ac3dfaa160ad05a47fe6bef 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/constants.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/constants.ts
@@ -3,106 +3,20 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-// TODO: Replace with OpenApi type when available
-export enum ApiTextTemplateContext {
-  ConsultationReason = "CONSULTATION_REASON",
-  Consultation = "CONSULTATION",
-  RapidTests = "RAPID_TESTS",
-  Diagnosis = "DIAGNOSIS",
-  LaboratoryTests = "LABORATORY_TESTS",
-}
-export interface ApiTextTemplate {
-  name: string;
-  text: string;
-  context: ApiTextTemplateContext;
-}
+import { ApiTextTemplateContext } from "@eshg/sti-protection-api";
 
 export const TextTemplateContextLabels = {
   [ApiTextTemplateContext.ConsultationReason]: "Konsultationsgrund",
-  [ApiTextTemplateContext.Consultation]: "Konsultation",
-  [ApiTextTemplateContext.RapidTests]: "Schnelltests",
-  [ApiTextTemplateContext.Diagnosis]: "Diagnose",
-  [ApiTextTemplateContext.LaboratoryTests]: "Labortests",
+  [ApiTextTemplateContext.ConsultationRemark]:
+    "Konsultation - Allgemeine Bemerkung",
+  [ApiTextTemplateContext.RapidTestsRemark]:
+    "Schnelltests - Allgemeine Bemerkung",
+  [ApiTextTemplateContext.DiagnosisResult]: "Diagnose - Ergebnisse",
+  [ApiTextTemplateContext.LaboratoryTestsRemark]:
+    "Labortests - Allgemeine Bemerkung",
+  [ApiTextTemplateContext.DiagnosisRemark]: "Diagnose - Allgemeine Bemerkung",
 } as const satisfies Record<ApiTextTemplateContext, string>;
 
 export const TextTemplateContextOptions = Object.entries(
   TextTemplateContextLabels,
-).map(([key, value]) => ({
-  label: value,
-  value: key as ApiTextTemplateContext,
-}));
-
-export const ExampleTextTemplates = [
-  {
-    name: "Genitale Infektionen ",
-    context: ApiTextTemplateContext.ConsultationReason,
-    text: `Nein, Mann! Ich will noch nicht gehen.
-Ich will: $etwas`,
-  },
-  {
-    name: "PAP",
-    context: ApiTextTemplateContext.ConsultationReason,
-    text: `PAP: $`,
-  },
-  {
-    name: "Syphilis-seronarbe Bestätigungstest bei positiv",
-    context: ApiTextTemplateContext.ConsultationReason,
-    text: `Syphilis-werte: $`,
-  },
-  {
-    name: "Gynäkologische Vorsorge",
-    context: ApiTextTemplateContext.Consultation,
-    text: `Vagina: $JaOderNein
-Urinanalyse: $Uneindeutig`,
-  },
-  {
-    name: "Konsultation - Standardvorlage 1",
-    context: ApiTextTemplateContext.RapidTests,
-    text: `Wie heißt du? $NAME
-Was ist dein Quest? $QUEST
-Wie hoch ist die Fluggeschwindigkeit einer unbeladenen Schwalbe? $AHHHHH`,
-  },
-  {
-    name: "HIV-Bestätigungsdiagnostik ",
-    context: ApiTextTemplateContext.Diagnosis,
-    text: `HIV: $Nein`,
-  },
-  {
-    name: "HIV & Syphilis Basis ",
-    context: ApiTextTemplateContext.LaboratoryTests,
-    text: `HIV & Syphilis: $`,
-  },
-  {
-    name: "Genitale Infektionen ",
-    context: ApiTextTemplateContext.Consultation,
-    text: `Nein, Mann! Ich will noch nicht gehen.
-Ich will: $etwas`,
-  },
-  {
-    name: "PAP",
-    context: ApiTextTemplateContext.Consultation,
-    text: `PAP: $`,
-  },
-  {
-    name: "Syphilis-seronarbe Bestätigungstest bei positiv",
-    context: ApiTextTemplateContext.Consultation,
-    text: `Syphilis-werte: $`,
-  },
-  {
-    name: "Konsultation - Standardvorlage 1",
-    context: ApiTextTemplateContext.Consultation,
-    text: `Wer bist du? $NAME
-Was ist dein Quest? $QUEST
-Wie hoch ist die Fluggeschwindigkeit einer unbeladenen Schwalbe? $AHHHHH`,
-  },
-  {
-    name: "HIV-Bestätigungsdiagnostik",
-    context: ApiTextTemplateContext.Consultation,
-    text: `HIV: $Nein`,
-  },
-  {
-    name: "HIV & Syphilis Basis",
-    context: ApiTextTemplateContext.Consultation,
-    text: `HIV & Syphilis: $`,
-  },
-] as const satisfies ApiTextTemplate[];
+).map(([value, label]) => ({ label, value }));
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/nextInsertPoint.ts b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/nextInsertPoint.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cfc9fd0742dfd38ff7e7f698af1494e9ffe04060
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/nextInsertPoint.ts
@@ -0,0 +1,45 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { isString } from "remeda";
+
+const replacementRegex = /\$(\d|\w|_)*/;
+export interface InsertPoint {
+  start: number;
+  end: number;
+}
+export function nextInsertPoint(
+  value: unknown,
+  startSearch: number,
+): InsertPoint | undefined {
+  const currentValue = isString(value) ? value : "";
+  const remainingText = currentValue.slice(startSearch);
+  const match = replacementRegex.exec(remainingText);
+  if (match?.index == null || match[0] == null) {
+    return;
+  }
+  const start = startSearch + match.index;
+  return { start, end: start + match[0].length };
+}
+
+export function selectFirstPoint(textarea: HTMLTextAreaElement | null) {
+  if (textarea == null) {
+    return;
+  }
+  textarea.focus();
+  const firstPoint = nextInsertPoint(textarea.value, 0);
+  if (firstPoint) {
+    textarea.selectionStart = firstPoint.start;
+    textarea.selectionEnd = firstPoint.end;
+  }
+}
+
+export function appendText(text: string, value: unknown) {
+  const currentValue = isString(value) ? value : "";
+  if (currentValue === "") {
+    return text;
+  }
+  return currentValue + `\n` + text;
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/useFieldHandle.tsx b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/useFieldHandle.tsx
deleted file mode 100644
index b7953de16e5a2f61914b1eed13a29cab032dac17..0000000000000000000000000000000000000000
--- a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/useFieldHandle.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-
-import { useFormikContext } from "formik";
-import { MutableRefObject } from "react";
-import { isString } from "remeda";
-
-export interface UseFieldHandle {
-  appendText: (text: string) => Promise<void>;
-  finishEditing: () => void;
-}
-
-export function useFieldHandle({
-  name,
-  ref,
-}: {
-  name: string;
-  ref: MutableRefObject<HTMLTextAreaElement | null>;
-}) {
-  const { setFieldValue, getFieldMeta } = useFormikContext();
-  const { value } = getFieldMeta(name);
-
-  return {
-    async appendText(text: string) {
-      const currentValue = isString(value) ? value : "";
-      const newValue = currentValue + `\n` + text;
-      await setFieldValue(name, newValue.trim());
-    },
-    finishEditing() {
-      if (ref?.current == null) {
-        return;
-      }
-      ref.current.focus();
-      const firstPoint = nextInsertPoint(value, 0);
-      if (firstPoint) {
-        ref.current.selectionStart = firstPoint.start;
-        ref.current.selectionEnd = firstPoint.end;
-      }
-    },
-  };
-}
-
-const replacementRegex = /\$(\d|\w|_)*/;
-export interface InsertPoint {
-  start: number;
-  end: number;
-}
-export function nextInsertPoint(
-  value: unknown,
-  startSearch: number,
-): InsertPoint | undefined {
-  const currentValue = isString(value) ? value : "";
-  const remainingText = currentValue.slice(startSearch);
-  const match = replacementRegex.exec(remainingText);
-  if (match?.index == null || match[0] == null) {
-    return;
-  }
-  const start = startSearch + match.index;
-  return { start, end: start + match[0].length };
-}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/useSidebarFromSearchParam.ts b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/useSidebarFromSearchParam.ts
new file mode 100644
index 0000000000000000000000000000000000000000..62a92b2383ef19b3bb1352800dc31ca8a7598d6c
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/components/textTemplates/useSidebarFromSearchParam.ts
@@ -0,0 +1,98 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { useCallback, useEffect, useRef } from "react";
+
+import {
+  DrawerOpenOptions,
+  DrawerProps,
+} from "@/lib/shared/components/drawer/drawerContext";
+import {
+  UseSidebarResult,
+  useSidebar,
+} from "@/lib/shared/components/drawer/useSidebar";
+import { useSearchParam } from "@/lib/shared/hooks/searchParams/useSearchParam";
+
+interface UseSidebarFromSearchParamOptionsBaseProps<
+  TSidebarProps extends DrawerProps,
+> extends DrawerOpenOptions<TSidebarProps> {
+  paramName: string;
+  paramValue?: string;
+  afterClose?: () => void;
+}
+
+type CustomProps<TSidebarProps extends DrawerProps> =
+  Omit<TSidebarProps, keyof DrawerProps> extends Record<string, never>
+    ? never
+    : Omit<TSidebarProps, keyof DrawerProps>;
+
+interface UseSidebarFromSearchParamOptionsCustomProps<
+  TSidebarProps extends DrawerProps,
+> extends UseSidebarFromSearchParamOptionsBaseProps<TSidebarProps> {
+  props: CustomProps<TSidebarProps>;
+}
+
+interface UseSidebarFromSearchParamResult
+  extends Omit<UseSidebarResult<DrawerProps>, "open"> {
+  open: () => void;
+}
+
+type UseSidebarFromSearchParamOptionsProps<TSidebarProps extends DrawerProps> =
+  Omit<TSidebarProps, keyof DrawerProps> extends Record<string, never>
+    ? UseSidebarFromSearchParamOptionsBaseProps<DrawerProps>
+    : UseSidebarFromSearchParamOptionsCustomProps<TSidebarProps>;
+
+export function useSidebarFromSearchParam<TSidebarProps extends DrawerProps>({
+  paramName,
+  paramValue,
+  afterClose,
+  ...options
+}: UseSidebarFromSearchParamOptionsProps<TSidebarProps>): UseSidebarFromSearchParamResult {
+  const [openName, setOpenName] = useSearchParam(paramName);
+
+  const sidebar = useSidebar(options);
+  // Sidebar is a new object every re-render
+  const sidebarRef = useRef(sidebar);
+  sidebarRef.current = sidebar;
+
+  const isOpen = paramValue ? openName === paramValue : !!openName;
+  const givenProps =
+    "props" in options
+      ? (options.props as CustomProps<TSidebarProps>)
+      : undefined;
+  const propsRef = useRef(givenProps);
+  propsRef.current = givenProps;
+
+  const open = useCallback(() => {
+    setOpenName(paramValue ?? true);
+    if (propsRef.current) {
+      sidebarRef.current.open(propsRef.current);
+    } else {
+      (sidebarRef.current as { open: () => void }).open();
+    }
+  }, [paramValue, setOpenName]);
+
+  useEffect(() => {
+    if (!isOpen) {
+      return;
+    }
+    open();
+  }, [isOpen, open]);
+
+  const afterCloseRef = useRef(afterClose);
+  afterCloseRef.current = afterClose;
+
+  useEffect(() => {
+    if (!sidebar.isOpen) {
+      return;
+    }
+    return () => {
+      setOpenName(null);
+      afterCloseRef.current?.();
+    };
+  }, [sidebar.isOpen, setOpenName]);
+
+  return { ...sidebar, open };
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/TabStickyBottomButtonBar.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/TabStickyBottomButtonBar.tsx
index 831a903eaadca436a7264b66e997a722e41af427..f1358ef9134ccd3bfbb0ed15dbb9f7ab0eedd32d 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/TabStickyBottomButtonBar.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/TabStickyBottomButtonBar.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiStiProtectionProcedure } from "@eshg/employee-portal-api/stiProtection";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
+import { ApiStiProtectionProcedure } from "@eshg/sti-protection-api";
 import { Button } from "@mui/joy";
 import { useFormikContext } from "formik";
 import { useRouter } from "next/navigation";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AddNewProcedureSidebar.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AddNewProcedureSidebar.tsx
index 92f1ac9aea8fb00f3f82f839a552bce2e5a33214..89368245f40cb79aeb138459c4020c7b965b8b32 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AddNewProcedureSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AddNewProcedureSidebar.tsx
@@ -3,34 +3,32 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiAppointment,
   ApiAppointmentBookingType,
   ApiAppointmentType,
   ApiConcern,
   ApiCountryCode,
-  ApiCreateProcedureRequest,
   ApiCreateProcedureResponse,
   ApiGender,
-} from "@eshg/employee-portal-api/stiProtection";
-import { GENDER_OPTIONS } from "@eshg/lib-portal/components/formFields/constants";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
-import { countryOptions } from "@eshg/lib-portal/helpers/countryOption";
-import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
-import { differenceInMinutes } from "date-fns";
-import { Formik, FormikHelpers } from "formik";
+} from "@eshg/sti-protection-api";
+import { Formik } from "formik";
 import { useRouter } from "next/navigation";
-import { useReducer, useState } from "react";
+import { useState } from "react";
 
 import {
   useCreateStiProcedureMutation,
   useCreateStiProcedureOptions,
 } from "@/lib/businessModules/stiProtection/api/mutations/procedures";
-import { CONCERN_VALUES } from "@/lib/businessModules/stiProtection/shared/constants";
 import {
-  deleteUndefined,
-  optionalInt,
-} from "@/lib/businessModules/stiProtection/shared/helpers";
+  AppointmentForm,
+  CreateAppointmentForm,
+} from "@/lib/businessModules/stiProtection/shared/procedure/AppointmentForm";
+import { SharePinModal } from "@/lib/businessModules/stiProtection/shared/procedure/SharePinModal";
+import { CONCERN_OPTIONS } from "@/lib/businessModules/stiProtection/shared/procedure/helpers";
+import { mapProcedureFormToApi } from "@/lib/businessModules/stiProtection/shared/procedure/mappers";
+import { useFormWithSteps } from "@/lib/businessModules/stiProtection/shared/procedure/useFormWithSteps";
 import { routes } from "@/lib/businessModules/stiProtection/shared/routes";
 import { ConfirmLeaveDirtyFormEffect } from "@/lib/shared/components/form/ConfirmLeaveDirtyFormEffect";
 import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
@@ -42,20 +40,15 @@ import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
 import { useSearchParam } from "@/lib/shared/hooks/searchParams/useSearchParam";
 import { useSidebarForm } from "@/lib/shared/hooks/useSidebarForm";
 
-import { AppointmentForm, CombinedAppointmentForm } from "./AppointmentForm";
 import {
   PersonalDataForm,
   personalDataFormValidation,
 } from "./PersonalDataForm";
-import { SharePinModal } from "./SharePinModal";
 import { AppointmentFieldSetProps, SummaryForm } from "./SummaryForm";
 
-export const CONCERN_OPTIONS = Object.entries(CONCERN_VALUES).map(
-  ([value, label]) => ({
-    content: <b>{label}</b>,
-    value: value as ApiConcern,
-  }),
-);
+export type CombinedAppointmentForm = Partial<
+  AddNewProcedureForm & CreateAppointmentForm
+>;
 
 const steps = [
   {
@@ -122,14 +115,6 @@ export function AddNewProcedureSidebar() {
   const [dataToShare, setDataToShare] = useState<
     { pin: string; id: string } | undefined
   >();
-  const lastStepIndex = steps.length - 1;
-  const [stepIndex, changeToStep] = useReducer(
-    (_index: number, newIndex: number) =>
-      Math.max(Math.min(newIndex, lastStepIndex), 0),
-    0,
-  );
-
-  const step = steps[stepIndex]!;
 
   const snackbar = useSnackbar();
   const addNewProcedureOptions = useCreateStiProcedureOptions();
@@ -141,6 +126,21 @@ export function AddNewProcedureSidebar() {
     },
   });
 
+  function onFinalSubmit(newValues: AddNewProcedureForm) {
+    const mappedValues = mapProcedureFormToApi(newValues);
+    return addNewProcedure.mutateAsync(mappedValues);
+  }
+
+  const {
+    Fields,
+    handleNext,
+    handlePrev,
+    changeToStep,
+    step,
+    isOnFirstStep,
+    isOnLastStep,
+  } = useFormWithSteps({ steps, onFinalSubmit });
+
   function pinIsShared() {
     if (dataToShare == null) {
       return;
@@ -156,22 +156,6 @@ export function AddNewProcedureSidebar() {
     },
   });
 
-  const isOnFirstStep = stepIndex === 0;
-  const isOnLastStep = stepIndex === lastStepIndex;
-
-  function handleNext(
-    newValues: AddNewProcedureForm,
-    _helpers: FormikHelpers<AddNewProcedureForm>,
-  ) {
-    if (isOnLastStep) {
-      const mappedValues = mapFormToApi(newValues);
-      return addNewProcedure.mutateAsync(mappedValues);
-    }
-    changeToStep(stepIndex + 1);
-  }
-
-  const Fields = step.fields;
-
   return (
     <>
       <Sidebar open={isOpen} onClose={handleClose}>
@@ -185,7 +169,7 @@ export function AddNewProcedureSidebar() {
               <ConfirmLeaveDirtyFormEffect
                 onSaveMutation={{
                   mutationOptions: addNewProcedureOptions,
-                  variableSupplier: () => mapFormToApi(values),
+                  variableSupplier: () => mapProcedureFormToApi(values),
                 }}
               />
               <SidebarContent title={step.title} subtitle={step.subTitle}>
@@ -202,11 +186,7 @@ export function AddNewProcedureSidebar() {
                 <MultiFormButtonBar
                   submitting={addNewProcedure.isPending}
                   onCancel={handleClose}
-                  onBack={
-                    isOnFirstStep
-                      ? undefined
-                      : () => changeToStep(stepIndex - 1)
-                  }
+                  onBack={isOnFirstStep ? undefined : handlePrev}
                   submitLabel={isOnLastStep ? "Vorgang anlegen" : "Weiter"}
                 />
               </SidebarActions>
@@ -218,55 +198,3 @@ export function AddNewProcedureSidebar() {
     </>
   );
 }
-
-function mapFormToApi(form: AddNewProcedureForm): ApiCreateProcedureRequest {
-  if (!form.yearOfBirth) {
-    throw new Error("Year of birth must be defined");
-  }
-  if (!form.appointmentBookingType) {
-    throw new Error("Appointment booking type must be defined");
-  }
-  const isCustomAppointment =
-    form.appointmentBookingType === ApiAppointmentBookingType.UserDefined;
-
-  const appointmentStart = isCustomAppointment
-    ? new Date(form.customAppointmentDate)
-    : form.blockAppointment?.start;
-
-  if (!appointmentStart) {
-    throw new Error("Appointment start must be defined");
-  }
-
-  const blockAppointmentEnd = form.blockAppointment?.end;
-  if (!isCustomAppointment && blockAppointmentEnd == null) {
-    throw new Error("Appointment end must be defined");
-  }
-
-  return deleteUndefined({
-    appointmentBookingType: form.appointmentBookingType,
-    concern: CONCERN_OPTIONS.find((t) => t.value === form.concern)?.value,
-    countryOfBirth: countryOptions().find(
-      (t) => t.value === form.countryOfBirth,
-    )?.value,
-    gender: GENDER_OPTIONS.find((t) => t.value === form.gender)?.value as
-      | ApiGender
-      | undefined,
-    durationInMinutes: isCustomAppointment
-      ? optionalInt(form.customAppointmentDuration)
-      : differenceInMinutes(blockAppointmentEnd!, appointmentStart),
-    appointmentStart,
-    inGermanySince: optionalInt(form.inGermanySince),
-    yearOfBirth: parseInt(form.yearOfBirth, 10),
-  });
-}
-
-export function getAppointmentDate(form: CombinedAppointmentForm) {
-  const customAppointmentDate = isNonEmptyString(form.customAppointmentDate)
-    ? new Date(form.customAppointmentDate)
-    : undefined;
-  const date =
-    form.appointmentBookingType === ApiAppointmentBookingType.AppointmentBlock
-      ? form.blockAppointment?.start
-      : customAppointmentDate;
-  return date ?? undefined;
-}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/SummaryForm.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/SummaryForm.tsx
index 5403b80f99cdbdf7de92098c52a7ce8f1b7f63e6..133b97bb00803e75b16583c6b523864c2c279699 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/SummaryForm.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/SummaryForm.tsx
@@ -3,14 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiAppointmentType,
-  ApiConcern,
-} from "@eshg/employee-portal-api/stiProtection";
 import { GENDER_VALUES } from "@eshg/lib-portal/components/formFields/constants";
 import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
 import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
 import { ifDefined } from "@eshg/lib-portal/helpers/ifDefined";
+import { ApiAppointmentType, ApiConcern } from "@eshg/sti-protection-api";
 import { EditOutlined } from "@mui/icons-material";
 import { Divider, IconButton, Stack, Typography } from "@mui/joy";
 import { useFormikContext } from "formik";
@@ -18,15 +15,16 @@ import { ReactNode, useId } from "react";
 
 import { APPOINTMENT_TYPES } from "@/lib/businessModules/stiProtection/shared/constants";
 import { concernToAppointmentType } from "@/lib/businessModules/stiProtection/shared/helpers";
+import { getAppointmentDate } from "@/lib/businessModules/stiProtection/shared/procedure/mappers";
 
-import { getAppointmentDate } from "./AddNewProcedureSidebar";
-import { CombinedAppointmentForm } from "./AppointmentForm";
+import { CombinedAppointmentForm } from "./AddNewProcedureSidebar";
 
 const germanDateFormatter = Intl.DateTimeFormat("de-DE", {
   day: "2-digit",
   month: "2-digit",
   year: "numeric",
 });
+
 const germanTimeFormatter = Intl.DateTimeFormat("de-DE", {
   timeStyle: "short",
 });
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/ConsultationForm.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/ConsultationForm.tsx
index 3a7e61994eabbc22735d0b6ea0f7dec77d008439..dd3c64a5713cb07c341e88c52ff477ca7563e423 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/ConsultationForm.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/ConsultationForm.tsx
@@ -5,24 +5,26 @@
 
 "use client";
 
+import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import {
   ApiConsultation,
   ApiStiProtectionProcedure,
-} from "@eshg/employee-portal-api/stiProtection";
-import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
-import { Divider, Sheet, Typography } from "@mui/joy";
+  ApiTextTemplateContext,
+} from "@eshg/sti-protection-api";
+import { Sheet, Typography } from "@mui/joy";
 import { Formik } from "formik";
 
-import { useUpsertConsultation } from "@/lib/businessModules/stiProtection/api/mutations/consultation";
-import { TextTemplatesSidebarProvider } from "@/lib/businessModules/stiProtection/components/textTemplates/TextTemplatesSidebarProvider";
+import {
+  useUpsertConsultation,
+  useUpsertConsultationOptions,
+} from "@/lib/businessModules/stiProtection/api/mutations/consultation";
 import { TextareaFieldWithTextTemplates } from "@/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates";
-import { ApiTextTemplateContext } from "@/lib/businessModules/stiProtection/components/textTemplates/constants";
 import {
   SidecarFormLayout,
   SidecarSheet,
 } from "@/lib/businessModules/stiProtection/features/procedures/SidecarFormLayout";
 import { TabStickyBottomButtonBar } from "@/lib/businessModules/stiProtection/features/procedures/TabStickyBottomButtonBar";
+import { ConfirmLeaveDirtyFormEffect } from "@/lib/shared/components/form/ConfirmLeaveDirtyFormEffect";
 
 import { GeneralSection } from "./GeneralSection";
 import { PregnancySection } from "./PregnancySection";
@@ -39,51 +41,59 @@ export function ConsultationForm({
   procedure: ApiStiProtectionProcedure;
   consultation: ApiConsultation;
 }>) {
-  const snackbar = useSnackbar();
-  const upsertConsultation = useUpsertConsultation(procedure.id, {
-    onSuccess: () => {
-      snackbar.confirmation("Die Konsultation wurde erfolgreich gespeichert.");
-    },
-    onError: () => {
-      snackbar.error("Die Konsultation konnte nicht gespeichert werden.");
-    },
+  const { id: procedureId } = procedure;
+  const upsertConsultationOptions = useUpsertConsultationOptions({
+    procedureId,
   });
+  const upsertConsultation = useUpsertConsultation({ procedureId });
 
   function onSubmit(values: ConsultationFormData) {
     const consultation = mapFormValuesToApi(values);
-    return upsertConsultation.mutateAsync(consultation);
+    return upsertConsultation.mutateAsync({ consultation });
   }
 
   return (
-    <Formik initialValues={mapApiToForm(consultation)} onSubmit={onSubmit}>
-      <FormPlus>
-        <SidecarFormLayout>
-          <Sheet>
-            <Typography level="h2" mb={5}>
-              Konsultation
-            </Typography>
+    <Formik
+      initialValues={mapApiToForm(consultation)}
+      onSubmit={onSubmit}
+      enableReinitialize
+    >
+      {({ values }) => (
+        <FormPlus>
+          <ConfirmLeaveDirtyFormEffect
+            onSaveMutation={{
+              mutationOptions: upsertConsultationOptions,
+              variableSupplier: () => ({
+                procedureId,
+                consultation: mapFormValuesToApi(values),
+              }),
+            }}
+          />
 
-            <GeneralSection />
+          <SidecarFormLayout>
+            <Sheet>
+              <Typography level="h2" mb={5}>
+                Konsultation
+              </Typography>
 
-            <Divider sx={(theme) => ({ my: theme.spacing(5) })} />
+              <GeneralSection />
 
-            <PregnancySection />
-          </Sheet>
-          <SidecarSheet>
-            <Typography level="h3" mb={3}>
-              Zusatzinfos
-            </Typography>
-            <TextTemplatesSidebarProvider>
+              <PregnancySection />
+            </Sheet>
+            <SidecarSheet>
+              <Typography level="h3" mb={3}>
+                Zusatzinfos
+              </Typography>
               <TextareaFieldWithTextTemplates
                 name="general.notes"
                 label="Allgemeine Bemerkungen"
-                context={ApiTextTemplateContext.Consultation}
+                context={ApiTextTemplateContext.ConsultationRemark}
               />
-            </TextTemplatesSidebarProvider>
-          </SidecarSheet>
-        </SidecarFormLayout>
-        <TabStickyBottomButtonBar procedure={procedure} />
-      </FormPlus>
+            </SidecarSheet>
+          </SidecarFormLayout>
+          <TabStickyBottomButtonBar procedure={procedure} />
+        </FormPlus>
+      )}
     </Formik>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/GeneralSection.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/GeneralSection.tsx
index bbb9d8a9f0074744044b8307a9b917349a748892..3510897a8f20c71a3ee5f0887a2036e42072b2f9 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/GeneralSection.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/GeneralSection.tsx
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { ApiTextTemplateContext } from "@eshg/sti-protection-api";
 import { Typography, useTheme } from "@mui/joy";
 
 import { SectionGrid } from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/SectionGrid";
@@ -10,6 +11,7 @@ import {
   YesOrNoFieldData,
   YesOrNoWithFollowUp,
 } from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/YesOrNoWithFollowUp";
+import { TextareaFieldWithTextTemplates } from "@/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates";
 import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
 import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
 
@@ -42,7 +44,11 @@ export function GeneralSection() {
     <SectionGrid defaultColumn={1}>
       <Typography level="h3">Allgemein</Typography>
 
-      <TextareaField name="general.mainReason" label="Konsultationsgrund" />
+      <TextareaFieldWithTextTemplates
+        context={ApiTextTemplateContext.ConsultationReason}
+        name="general.mainReason"
+        label="Konsultationsgrund"
+      />
       <TextareaField
         name="general.furtherGenderInfo"
         label="Weitere Geschlechtsangaben"
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/helpers.ts b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/helpers.ts
index d2a47145438570015b111b665c999e79e84ca70f..8c7014aac54e9694c864397d65e63c74e9850a44 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/helpers.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/consultation/helpers.ts
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiConsultation } from "@eshg/employee-portal-api/stiProtection";
 import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
 import { ifDefined } from "@eshg/lib-portal/helpers/ifDefined";
+import { ApiConsultation } from "@eshg/sti-protection-api";
 
 import {
   mapBoolToYesOrNo,
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AdditionalDataSection.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AdditionalDataSection.tsx
index b3613affc843989bbbea3d17baa008554cedf1d5..61479b739ae6f6922700beaebb737490e6e17032 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AdditionalDataSection.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AdditionalDataSection.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiStiProtectionProcedure } from "@eshg/employee-portal-api/stiProtection";
-import { Sheet } from "@mui/joy";
+import { ApiStiProtectionProcedure } from "@eshg/sti-protection-api";
+import { Chip, Sheet, styled } from "@mui/joy";
 
 import { CONCERN_VALUES } from "@/lib/businessModules/stiProtection/shared/constants";
 import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
@@ -27,6 +27,7 @@ export function AdditionalDataSection({
     <Sheet>
       <DetailsSection title="Zusatzinfos">
         <DetailsColumn>
+          {procedure.isFollowUp ? <FollowUpProcedureChip /> : null}
           <DetailsCell label="Art" value={CONCERN_VALUES[procedure.concern]} />
           <DetailsCell
             label="Nächster Termin"
@@ -38,3 +39,12 @@ export function AdditionalDataSection({
     </Sheet>
   );
 }
+
+const FollowUpChip = styled(Chip)(({ theme }) => ({
+  backgroundColor: theme.palette.primary.softBg,
+  color: theme.palette.text.primary,
+}));
+
+function FollowUpProcedureChip() {
+  return <FollowUpChip>Folgevorgang</FollowUpChip>;
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AnonIdentityDocumentCard.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AnonIdentityDocumentCard.tsx
index c842d64e892b4a951ba3583d9c619fe7e20271a7..53a14c1e2d7d0344e474600966cb5facdcf03292 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AnonIdentityDocumentCard.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AnonIdentityDocumentCard.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiStiProtectionProcedure } from "@eshg/employee-portal-api/stiProtection";
 import { ButtonLink } from "@eshg/lib-portal/components/buttons/ButtonLink";
+import { ApiStiProtectionProcedure } from "@eshg/sti-protection-api";
 import { Sheet, Stack } from "@mui/joy";
 
 import { useAnonymousIdentificationDocumentQuery } from "@/lib/businessModules/stiProtection/api/queries/procedures";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AppointmentDetails.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AppointmentDetails.tsx
index b3318506698617fbd54274bf0a1f62418c83e128..16a23e44274d88554907022eddcd86954f60d842 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AppointmentDetails.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/AppointmentDetails.tsx
@@ -3,12 +3,12 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { Row } from "@eshg/lib-portal/components/Row";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiAppointmentHistoryEntry,
   ApiStiProtectionProcedure,
-} from "@eshg/employee-portal-api/stiProtection";
-import { Row } from "@eshg/lib-portal/components/Row";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+} from "@eshg/sti-protection-api";
 import { EditCalendar, EventBusy } from "@mui/icons-material";
 import { Button, Chip, Sheet, Stack } from "@mui/joy";
 import { ColumnSort, createColumnHelper } from "@tanstack/react-table";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CheckPinSection.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CheckPinSection.tsx
index d8029c565283761d84107a1db8c6b728d36d6f0e..eb06fcf70e3457dcd8829a7549502a49f65de58b 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CheckPinSection.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CheckPinSection.tsx
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiStiProtectionProcedure } from "@eshg/employee-portal-api/stiProtection";
 import { Row } from "@eshg/lib-portal/components/Row";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
+import { ApiStiProtectionProcedure } from "@eshg/sti-protection-api";
 import {
   CheckCircleOutlined,
   ErrorOutlineOutlined,
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CloseAndReopenDialogs.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CloseAndReopenDialogs.tsx
index c5ee4fcd22498aae02d54151eb2d944f4774dba8..4a0c02ee927cc73efe4b496a15f297ceb98af825 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CloseAndReopenDialogs.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CloseAndReopenDialogs.tsx
@@ -3,12 +3,12 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
 import {
   ApiAppointmentHistoryEntry,
   ApiStiProtectionProcedure,
   ApiStiProtectionProcedureOverview,
-} from "@eshg/employee-portal-api/stiProtection";
-import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
+} from "@eshg/sti-protection-api";
 import { Typography, styled } from "@mui/joy";
 import { useState } from "react";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CreateAppointmentSidebar.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CreateAppointmentSidebar.tsx
index db6233983873c21d3e050edbe88d3a1f7c642832..bd7bbe182aadb7e6d6fae42b6a917faeef315aa9 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CreateAppointmentSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CreateAppointmentSidebar.tsx
@@ -3,16 +3,14 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiAppointmentBookingType,
   ApiAppointmentType,
-  ApiConcern,
   ApiCreateAppointmentRequest,
   ApiStiProtectionProcedure,
   ApiUpdateAppointmentRequest,
-} from "@eshg/employee-portal-api/stiProtection";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
-import { ApiAppointment } from "@eshg/measles-protection-api";
+} from "@eshg/sti-protection-api";
 import { differenceInMinutes } from "date-fns";
 import { Formik, FormikHelpers } from "formik";
 import { ReactNode, useMemo, useReducer } from "react";
@@ -21,7 +19,6 @@ import {
   useCreateAppointmentMutation,
   useEditAppointmentMutation,
 } from "@/lib/businessModules/stiProtection/api/mutations/procedures";
-import { AppointmentForm } from "@/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AppointmentForm";
 import {
   AppointmentFieldSetProps,
   SummaryForm,
@@ -31,6 +28,11 @@ import {
   isProcedureOpen,
   optionalInt,
 } from "@/lib/businessModules/stiProtection/shared/helpers";
+import {
+  AppointmentForm,
+  CreateAppointmentForm,
+  initialValues,
+} from "@/lib/businessModules/stiProtection/shared/procedure/AppointmentForm";
 import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
 import { SidebarForm } from "@/lib/shared/components/form/SidebarForm";
 import { Sidebar } from "@/lib/shared/components/sidebar/Sidebar";
@@ -39,24 +41,6 @@ import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
 import { useSearchParam } from "@/lib/shared/hooks/searchParams/useSearchParam";
 import { useSidebarForm } from "@/lib/shared/hooks/useSidebarForm";
 
-export interface CreateAppointmentForm {
-  appointmentType?: ApiAppointmentType | "" | null;
-  appointmentBookingType?: ApiAppointmentBookingType | "";
-  blockAppointment?: null | ApiAppointment;
-  concern?: ApiConcern | "RESULTS_REVIEW" | "";
-  customAppointmentDate: string;
-  customAppointmentDuration: string;
-}
-
-const initialValues: CreateAppointmentForm = {
-  appointmentType: null,
-  appointmentBookingType: "",
-  blockAppointment: null,
-  concern: "",
-  customAppointmentDate: "",
-  customAppointmentDuration: "",
-};
-
 interface CreateAppointmentSidebarProps {
   procedure: ApiStiProtectionProcedure;
 }
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CreateFollowUpProcedureSidebar.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CreateFollowUpProcedureSidebar.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..4855125561e1410d5943cd78409115bcf814e2b0
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CreateFollowUpProcedureSidebar.tsx
@@ -0,0 +1,219 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Alert } from "@eshg/lib-portal/components/Alert";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import {
+  ApiAppointment,
+  ApiAppointmentBookingType,
+  ApiAppointmentType,
+  ApiConcern,
+  ApiCreateFollowUpProcedureResponse,
+  ApiStiProtectionProcedure,
+} from "@eshg/sti-protection-api";
+import { Stack, Typography } from "@mui/joy";
+import { Formik, useFormikContext } from "formik";
+import { useRouter } from "next/navigation";
+import { useState } from "react";
+
+import {
+  useCreateStiFollowUpProcedureMutation,
+  useCreateStiFollowUpProcedureOptions,
+} from "@/lib/businessModules/stiProtection/api/mutations/procedures";
+import { CONCERN_VALUES } from "@/lib/businessModules/stiProtection/shared/constants";
+import { AppointmentForm } from "@/lib/businessModules/stiProtection/shared/procedure/AppointmentForm";
+import { SharePinModal } from "@/lib/businessModules/stiProtection/shared/procedure/SharePinModal";
+import { CONCERN_OPTIONS } from "@/lib/businessModules/stiProtection/shared/procedure/helpers";
+import { mapFollowUpProcedureFormToApi } from "@/lib/businessModules/stiProtection/shared/procedure/mappers";
+import { useFormWithSteps } from "@/lib/businessModules/stiProtection/shared/procedure/useFormWithSteps";
+import { routes } from "@/lib/businessModules/stiProtection/shared/routes";
+import { ConfirmLeaveDirtyFormEffect } from "@/lib/shared/components/form/ConfirmLeaveDirtyFormEffect";
+import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
+import { SidebarForm } from "@/lib/shared/components/form/SidebarForm";
+import { SelectableCardsField } from "@/lib/shared/components/formFields/SelectableCardsField";
+import { Sidebar } from "@/lib/shared/components/sidebar/Sidebar";
+import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
+import { SidebarContent } from "@/lib/shared/components/sidebar/SidebarContent";
+import { useSearchParam } from "@/lib/shared/hooks/searchParams/useSearchParam";
+import { useSidebarForm } from "@/lib/shared/hooks/useSidebarForm";
+
+const steps = [
+  {
+    title: "Folgevorgang anlegen",
+    subTitle: "Schritt 1 von 2",
+    fields: ({
+      procedure,
+    }: Readonly<{ procedure: ApiStiProtectionProcedure }>) => (
+      <CreateFollowUpProcedureTypeAndInfo procedure={procedure} />
+    ),
+  },
+  {
+    title: "Folgevorgang anlegen",
+    subTitle: "Schritt 2 von 2",
+    fields: () => <CreateFollowUpProcedureAppointmentForm />,
+  },
+];
+
+const initialValues: CreateFollowUpProcedureForm = {
+  concern: "",
+
+  appointmentBookingType: "",
+  blockAppointment: null,
+  customAppointmentDate: "",
+  customAppointmentDuration: "",
+};
+
+export interface CreateFollowUpProcedureForm {
+  concern?: ApiConcern | "";
+  appointmentType?: ApiAppointmentType | "" | null;
+
+  appointmentBookingType?: ApiAppointmentBookingType | "";
+  blockAppointment?: null | ApiAppointment;
+  customAppointmentDate: string;
+  customAppointmentDuration: string;
+}
+
+export function CreateFollowUpProcedureSidebar({
+  procedure,
+}: Readonly<{ procedure: ApiStiProtectionProcedure }>) {
+  const router = useRouter();
+  const [isOpen, setIsOpen] = useSearchParam(
+    "create-follow-up-procedure",
+    "boolean",
+  );
+  const [dataToShare, setDataToShare] = useState<
+    { pin: string; id: string } | undefined
+  >();
+
+  const snackbar = useSnackbar();
+  const createFollowUpProcedureOptions = useCreateStiFollowUpProcedureOptions();
+  const createFollowUpProcedure = useCreateStiFollowUpProcedureMutation({
+    onSuccess: (data: ApiCreateFollowUpProcedureResponse) => {
+      setIsOpen(false);
+      snackbar.confirmation("Folgevorgang angelegt");
+      setDataToShare({ pin: data.pin, id: data.procedureId });
+    },
+  });
+
+  function onFinalSubmit(newValues: CreateFollowUpProcedureForm) {
+    const mappedValues = mapFollowUpProcedureFormToApi(newValues);
+    return createFollowUpProcedure.mutateAsync({
+      id: procedure.id,
+      data: mappedValues,
+    });
+  }
+
+  const {
+    Fields,
+    handleNext,
+    handlePrev,
+    changeToStep,
+    step,
+    isOnFirstStep,
+    isOnLastStep,
+  } = useFormWithSteps({ steps, onFinalSubmit });
+
+  function pinIsShared() {
+    if (dataToShare == null) {
+      return;
+    }
+    router.push(routes.procedures.byId(dataToShare.id).details);
+    setDataToShare(undefined);
+  }
+
+  const { sidebarFormRef, handleClose } = useSidebarForm({
+    onClose: () => {
+      setIsOpen(false);
+      changeToStep(0);
+    },
+  });
+
+  return (
+    <>
+      <Sidebar open={isOpen} onClose={handleClose}>
+        <Formik initialValues={initialValues} onSubmit={handleNext}>
+          {({ values }) => (
+            <SidebarForm ref={sidebarFormRef}>
+              <ConfirmLeaveDirtyFormEffect
+                onSaveMutation={{
+                  mutationOptions: createFollowUpProcedureOptions,
+                  variableSupplier: () => mapFollowUpProcedureFormToApi(values),
+                }}
+              />
+              <SidebarContent title={step.title} subtitle={step.subTitle}>
+                <Fields procedure={procedure} />
+              </SidebarContent>
+              <SidebarActions>
+                <MultiFormButtonBar
+                  submitting={createFollowUpProcedure.isPending}
+                  onCancel={handleClose}
+                  onBack={isOnFirstStep ? undefined : handlePrev}
+                  submitLabel={isOnLastStep ? "Folgevorgang anlegen" : "Weiter"}
+                />
+              </SidebarActions>
+            </SidebarForm>
+          )}
+        </Formik>
+      </Sidebar>
+      <SharePinModal pinToShare={dataToShare?.pin} onShared={pinIsShared} />
+    </>
+  );
+}
+
+function CreateFollowUpProcedureTypeAndInfo({
+  procedure,
+}: Readonly<{ procedure: ApiStiProtectionProcedure }>) {
+  const openAppointment = procedure.appointmentHistory.find(
+    (t) => t.appointmentStatus === "OPEN",
+  );
+
+  return (
+    <>
+      <Typography level={"title-md"}>Art der Beratung</Typography>
+      <Stack gap={3}>
+        <SelectableCardsField
+          name="concern"
+          required="Bitte ein Anliegen auswählen"
+          options={CONCERN_OPTIONS}
+        />
+        <Alert
+          color={"primary"}
+          message={
+            <>
+              Ausschließlich folgende Daten werden übernommen:
+              <li>Angaben zur Person</li>
+              <li>Anamnese</li>
+              <li>Konsultation</li>
+              <li>Diagnose</li>
+              <li>Ergebnisse der Untersuchung</li>
+              <br />
+              Der aktuelle Vorgang wird abgeschlossen und Termine werden
+              storniert.
+            </>
+          }
+        />
+        {openAppointment ? (
+          <Alert
+            color={"warning"}
+            message="Es existieren noch offene Termine, welche bei der Anlage eines Folgevorgangs storniert werden."
+          />
+        ) : null}
+      </Stack>
+    </>
+  );
+}
+
+function CreateFollowUpProcedureAppointmentForm() {
+  const { getFieldMeta } = useFormikContext<CreateFollowUpProcedureForm>();
+  const concern = getFieldMeta("concern").value as ApiConcern;
+  const title = `Termin auswählen für ${CONCERN_VALUES[concern]}`;
+
+  return (
+    <Stack gap={1}>
+      <Typography level={"title-md"}>{title}</Typography>
+      <AppointmentForm />
+    </Stack>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/EditPersonalDataSidebar.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/EditPersonalDataSidebar.tsx
index 5a23bf0e59bf4846fb6d7e10a2c866354685eff7..d420116fea74843ddcd48d56c6a495f1f1935a11 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/EditPersonalDataSidebar.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/EditPersonalDataSidebar.tsx
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { GENDER_OPTIONS } from "@eshg/lib-portal/components/formFields/constants";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { countryOptions } from "@eshg/lib-portal/helpers/countryOption";
 import {
   ApiGender,
   ApiStiProtectionProcedure,
   UpdatePersonDetailsRequest,
-} from "@eshg/employee-portal-api/stiProtection";
-import { GENDER_OPTIONS } from "@eshg/lib-portal/components/formFields/constants";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
-import { countryOptions } from "@eshg/lib-portal/helpers/countryOption";
+} from "@eshg/sti-protection-api";
 import { Formik } from "formik";
 
 import { useUpdatePersonDetails } from "@/lib/businessModules/stiProtection/api/mutations/procedures";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CloseProcedurePanel.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/FinalProcedureActionPanel.tsx
similarity index 68%
rename from employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CloseProcedurePanel.tsx
rename to employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/FinalProcedureActionPanel.tsx
index 2218229f80b88bb0e11afea94a9f466599a918cc..ea094e6c5b71f7414c026641fc6cf5ade65c955c 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/CloseProcedurePanel.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/FinalProcedureActionPanel.tsx
@@ -3,20 +3,22 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiStiProtectionProcedure } from "@eshg/employee-portal-api/stiProtection";
+import { ApiStiProtectionProcedure } from "@eshg/sti-protection-api";
 import { Button } from "@mui/joy";
 import { ReactEventHandler } from "react";
 
 import { isProcedureOpen } from "@/lib/businessModules/stiProtection/shared/helpers";
 import { ContentPanel } from "@/lib/shared/components/contentPanel/ContentPanel";
+import { useSearchParam } from "@/lib/shared/hooks/searchParams/useSearchParam";
 
 import {
   CloseConfirmationDialog,
   ReopenConfirmationDialog,
   useCloseAndReopenProcedure,
 } from "./CloseAndReopenDialogs";
+import { CreateFollowUpProcedureSidebar } from "./CreateFollowUpProcedureSidebar";
 
-export function CloseAndReopenProcedurePanel({
+export function FinalProcedureActionPanel({
   procedure,
 }: Readonly<{ procedure: ApiStiProtectionProcedure }>) {
   const {
@@ -33,8 +35,14 @@ export function CloseAndReopenProcedurePanel({
     ? CloseConfirmationDialog
     : ReopenConfirmationDialog;
 
+  const [_isOpen, setIsOpen] = useSearchParam(
+    "create-follow-up-procedure",
+    "boolean",
+  );
+
   return (
     <ContentPanel>
+      <FollowUpButton onClick={() => setIsOpen(true)} />
       <ActionButton onClick={() => requestFinalize(procedure)} />
       <ConfirmationDialog
         open={isRequestingFinalize}
@@ -42,6 +50,7 @@ export function CloseAndReopenProcedurePanel({
         onConfirm={handleFinalizeProcedure}
         procedure={procedure}
       />
+      <CreateFollowUpProcedureSidebar procedure={procedure} />
     </ContentPanel>
   );
 }
@@ -65,3 +74,15 @@ function ReopenButton({
     </Button>
   );
 }
+
+function FollowUpButton({
+  onClick,
+}: {
+  onClick: ReactEventHandler<HTMLButtonElement>;
+}) {
+  return (
+    <Button onClick={onClick} variant="soft">
+      Folgevorgang anlegen
+    </Button>
+  );
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/PersonDetails.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/PersonDetails.tsx
index 3b8749b76001c04c141f85eca406051a38fe0436..400cd832026ae42de33a20980fd9c53146f58831 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/PersonDetails.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/PersonDetails.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiStiProtectionProcedure } from "@eshg/employee-portal-api/stiProtection";
 import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
+import { ApiStiProtectionProcedure } from "@eshg/sti-protection-api";
 import { Sheet, Stack } from "@mui/joy";
 
 import { GENDER_VALUES } from "@/lib/businessModules/stiProtection/shared/constants";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/ProcedureDetails.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/ProcedureDetails.tsx
index bbe605f0130c165d9267f246c502c3cf8c9ec234..e3edb70d8d800835447f1e08245fcdcb2a0f6637 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/ProcedureDetails.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/ProcedureDetails.tsx
@@ -5,16 +5,16 @@
 
 "use client";
 
-import { ApiStiProtectionProcedure } from "@eshg/employee-portal-api/stiProtection";
+import { ApiStiProtectionProcedure } from "@eshg/sti-protection-api";
 import { Grid, Stack } from "@mui/joy";
 
 import { AdditionalDataSection } from "./AdditionalDataSection";
 import { AnonIdentityDocumentCard } from "./AnonIdentityDocumentCard";
 import { AppointmentDetails } from "./AppointmentDetails";
 import { CheckPinSection } from "./CheckPinSection";
-import { CloseAndReopenProcedurePanel } from "./CloseProcedurePanel";
 import { CreateAppointmentSidebar } from "./CreateAppointmentSidebar";
 import { EditPersonalDataSidebar } from "./EditPersonalDataSidebar";
+import { FinalProcedureActionPanel } from "./FinalProcedureActionPanel";
 import { PersonDetails } from "./PersonDetails";
 import { WaitingRoomSection } from "./WaitingRoomSection";
 
@@ -40,7 +40,7 @@ export function ProcedureDetails({
             <AdditionalDataSection procedure={procedure} />
             <CheckPinSection procedure={procedure} />
             <WaitingRoomSection procedure={procedure} />
-            <CloseAndReopenProcedurePanel procedure={procedure} />
+            <FinalProcedureActionPanel procedure={procedure} />
           </Stack>
         </Grid>
       </Grid>
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/WaitingRoomSection.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/WaitingRoomSection.tsx
index cdda8a173608db48bb04d3e3c45872df46f6f011..6e2296090ce48b90d4027d6e84c2f9ccc7ffa86c 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/WaitingRoomSection.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/details/WaitingRoomSection.tsx
@@ -3,18 +3,18 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiStiProtectionProcedure,
-  ApiWaitingRoom,
-  ApiWaitingStatus,
-  UpdateWaitingRoomDetailsRequest,
-} from "@eshg/employee-portal-api/stiProtection";
 import { Row } from "@eshg/lib-portal/components/Row";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import {
+  ApiStiProtectionProcedure,
+  ApiWaitingRoom,
+  ApiWaitingStatus,
+  UpdateWaitingRoomDetailsRequest,
+} from "@eshg/sti-protection-api";
 import { Button, Sheet } from "@mui/joy";
 import { Formik, useFormikContext } from "formik";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/diagnosis/DiagnosisForm.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/diagnosis/DiagnosisForm.tsx
index a7a9d38e0f1f49905b959bdb7807314dec442057..ff9b6cbbe07bd997bae1e48ac77f945d265c4b25 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/diagnosis/DiagnosisForm.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/diagnosis/DiagnosisForm.tsx
@@ -5,17 +5,17 @@
 
 "use client";
 
-import {
-  ApiDiagnosis,
-  ApiStiProtectionProcedure,
-  ApiTestType,
-} from "@eshg/employee-portal-api/stiProtection";
 import { Row } from "@eshg/lib-portal/components/Row";
 import { useIsFormDisabled } from "@eshg/lib-portal/components/form/DisabledFormContext";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import {
+  ApiDiagnosis,
+  ApiStiProtectionProcedure,
+  ApiTestType,
+  ApiTextTemplateContext,
+} from "@eshg/sti-protection-api";
 import { Add, Delete, Edit } from "@mui/icons-material";
 import { Button, IconButton, Sheet, Stack, Typography } from "@mui/joy";
 import {
@@ -27,17 +27,21 @@ import {
 } from "formik";
 import { PropsWithChildren } from "react";
 
-import { useUpsertDiagnosis } from "@/lib/businessModules/stiProtection/api/mutations/diagnosis";
+import {
+  useUpsertDiagnosis,
+  useUpsertDiagnosisOptions,
+} from "@/lib/businessModules/stiProtection/api/mutations/diagnosis";
 import { SectionGrid } from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/SectionGrid";
+import { TextareaFieldWithTextTemplates } from "@/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates";
 import {
   SidecarFormLayout,
   SidecarSheet,
 } from "@/lib/businessModules/stiProtection/features/procedures/SidecarFormLayout";
 import { TabStickyBottomButtonBar } from "@/lib/businessModules/stiProtection/features/procedures/TabStickyBottomButtonBar";
 import { useOnCancelForm } from "@/lib/businessModules/stiProtection/shared/helpers";
+import { ConfirmLeaveDirtyFormEffect } from "@/lib/shared/components/form/ConfirmLeaveDirtyFormEffect";
 import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
 import { CheckboxGroupField } from "@/lib/shared/components/formFields/CheckboxGroupField";
-import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
 
 import { useIcd10Sidebar } from "./Icd10Sidebar";
 import {
@@ -57,19 +61,17 @@ export function DiagnosisForm({
   procedure: ApiStiProtectionProcedure;
   diagnosis: ApiDiagnosis;
 }>) {
-  const snackbar = useSnackbar();
-  const upsertDiagnosis = useUpsertDiagnosis(procedure.id, {
-    onSuccess: () => {
-      snackbar.confirmation("Die Diagnose wurde erfolgreich gespeichert.");
-    },
-    onError: () => {
-      snackbar.error("Die Diagnose konnte nicht gespeichert werden.");
-    },
+  const { id: procedureId } = procedure;
+  const upsertDiagnosisOptions = useUpsertDiagnosisOptions({
+    procedureId,
   });
-
+  const upsertDiagnosis = useUpsertDiagnosis({ procedureId });
   const onCancelForm = useOnCancelForm<DiagnosisFormData>();
 
-  function handleCancel({ dirty, resetForm }: FormikProps<DiagnosisFormData>) {
+  function handleCancel({
+    dirty,
+    resetForm,
+  }: Pick<FormikProps<DiagnosisFormData>, "dirty" | "resetForm">) {
     onCancelForm({
       dirty,
       reset: resetForm,
@@ -78,19 +80,38 @@ export function DiagnosisForm({
 
   function onSubmit(values: DiagnosisFormData) {
     const diagnosis = mapFormToApi(values);
-    return upsertDiagnosis.mutateAsync(diagnosis);
+    return upsertDiagnosis.mutateAsync({
+      diagnosis,
+    });
   }
 
   return (
-    <Formik initialValues={mapApiToForm(diagnosis)} onSubmit={onSubmit}>
-      {(formikProps) => (
+    <Formik
+      initialValues={mapApiToForm(diagnosis)}
+      onSubmit={onSubmit}
+      enableReinitialize
+    >
+      {({ resetForm, dirty, values }) => (
         <FormPlus sx={{ height: "100%" }}>
+          <ConfirmLeaveDirtyFormEffect
+            onSaveMutation={{
+              mutationOptions: upsertDiagnosisOptions,
+              variableSupplier: () => ({
+                procedureId,
+                diagnosis: mapFormToApi(values),
+              }),
+            }}
+          />
           <SidecarFormLayout>
             <Sheet>
               <Stack gap={5}>
                 <Typography level="h2">Diagnose</Typography>
                 <SectionGrid defaultColumn={1}>
-                  <TextareaField name="results" label="Ergebnisse" />
+                  <TextareaFieldWithTextTemplates
+                    name="results"
+                    label="Ergebnisse"
+                    context={ApiTextTemplateContext.DiagnosisResult}
+                  />
                 </SectionGrid>
                 <FieldArray name="medications" render={MedicationsSection} />
                 <FindingsSection />
@@ -103,7 +124,11 @@ export function DiagnosisForm({
                 Zusatzinfos
               </Typography>
               <Stack rowGap={5}>
-                <TextareaField name="notes" label="Allgemeine Bemerkungen" />
+                <TextareaFieldWithTextTemplates
+                  name="notes"
+                  label="Allgemeine Bemerkungen"
+                  context={ApiTextTemplateContext.DiagnosisRemark}
+                />
                 <CheckboxField
                   name="resultsShared"
                   label="Ergebnis mitgeteilt"
@@ -113,7 +138,7 @@ export function DiagnosisForm({
           </SidecarFormLayout>
           <TabStickyBottomButtonBar
             procedure={procedure}
-            onCancel={() => handleCancel(formikProps)}
+            onCancel={() => handleCancel({ dirty, resetForm })}
           />
         </FormPlus>
       )}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/diagnosis/helpers.ts b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/diagnosis/helpers.ts
index 216bae9c8014207e7c608086a4b0d94272ef202d..8e3a2e0d55151724989d8473f9f0209321af2995 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/diagnosis/helpers.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/diagnosis/helpers.ts
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
+import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
+import { ifDefined } from "@eshg/lib-portal/helpers/ifDefined";
 import {
   ApiDiagnosis,
   ApiIcd10Code,
   ApiTestType,
-} from "@eshg/employee-portal-api/stiProtection";
-import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
-import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
-import { ifDefined } from "@eshg/lib-portal/helpers/ifDefined";
+} from "@eshg/sti-protection-api";
 
 import { formatDateTypeToISODate } from "@/lib/shared/helpers/dateTime";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/LaboratoryTestExamination.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/LaboratoryTestExamination.tsx
index 538bdd499e152e4df1f649e13fa3b30ec2745a6c..cebaf74f027d7a9730451a3fdec47c8cbd8bccb2 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/LaboratoryTestExamination.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/LaboratoryTestExamination.tsx
@@ -3,253 +3,40 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiLaboratoryTestExamination } from "@eshg/employee-portal-api/stiProtection";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
+import {
+  ApiLaboratoryTestExamination,
+  ApiTextTemplateContext,
+} from "@eshg/sti-protection-api";
 import { Box, Divider, Grid, Sheet, Stack, Typography } from "@mui/joy";
-import { Formik, FormikState } from "formik";
+import { Formik } from "formik";
 
-import { useUpsertLaboratoryTest } from "@/lib/businessModules/stiProtection/api/mutations/examination";
+import {
+  useUpsertLaboratoryTest,
+  useUpsertLaboratoryTestOptions,
+} from "@/lib/businessModules/stiProtection/api/mutations/examination";
+import { TextareaFieldWithTextTemplates } from "@/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates";
 import { ExaminationStickyBottomButtonBar } from "@/lib/businessModules/stiProtection/features/procedures/examination/ExaminationStickyBottomButtonBar";
 import { ExaminationTabNavPanel } from "@/lib/businessModules/stiProtection/features/procedures/examination/ExaminationTabNavPanel";
-import {
-  guardValue,
-  mapOptionalString,
-} from "@/lib/businessModules/stiProtection/shared/helpers";
+import { useOnCancelForm } from "@/lib/businessModules/stiProtection/shared/helpers";
+import { ConfirmLeaveDirtyFormEffect } from "@/lib/shared/components/form/ConfirmLeaveDirtyFormEffect";
 import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
-import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
 import { SidePanel } from "@/lib/shared/components/sidePanel/SidePanel";
 import { SidePanelTitle } from "@/lib/shared/components/sidePanel/SidePanelTitle";
-import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
 
 import {
   HepatitisLaboratoryTest,
-  HepatitisLaboratoryTestData,
-  LaboratoryTestData,
   LaboratoryTestSamples,
-  LaboratoryTestSamplesData,
   LaboratoryTestWithBooleanResult,
-  defaultHepatitisLaboratoryTestFormData,
-  defaultLaboratoryTestFormData,
-  defaultLaboratoryTestSamplesFormData,
-  mapApiHepatitisLaboratoryTestToFormData,
-  mapApiLaboratoryTestSamplesToFormData,
-  mapApiLaboratoryTestToFormData,
-  mapHepatitisLaboratoryTestFormDataToApi,
-  mapLaboratoryTestFormDataToApi,
-  mapLaboratoryTestSamplesFormDataToApi,
 } from "./LaboratoryTestTemplates";
-
-export interface LaboratoryTestExaminationData {
-  sampleBarcode?: string;
-  generalRemarks?: string;
-  testsConducted?: boolean;
-  testsPayed?: boolean;
-  //Requested Tests
-  hivTestRequested?: boolean;
-  syphilisTestRequested?: boolean;
-  hepATestRequested?: boolean;
-  hepBTestRequested?: boolean;
-  hepCTestRequested?: boolean;
-  chlamydiaTestRequested?: boolean;
-  gonorrheaTestRequested?: boolean;
-  mycoplasmaTestRequested?: boolean;
-  cancerScreeningTestRequested?: boolean;
-  hpvTestRequested?: boolean;
-  mpoxTestRequested?: boolean;
-  otherTestRequested?: boolean;
-  //Data of Tests
-  hivTestData: LaboratoryTestData | null;
-  syphilisTestData: LaboratoryTestData | null;
-  hadSyphilis?: boolean;
-  hepATestData: HepatitisLaboratoryTestData | null;
-  hepBTestData: HepatitisLaboratoryTestData | null;
-  hepCTestData: LaboratoryTestData | null;
-  chlamydiaTestData: LaboratoryTestSamplesData | null;
-  gonorrheaTestData: LaboratoryTestSamplesData | null;
-  mycoplasmaTestData: LaboratoryTestSamplesData | null;
-  cancerScreeningTestData: LaboratoryTestData | null;
-  hpvTestData: LaboratoryTestData | null;
-  mpoxTestData: LaboratoryTestData | null;
-  otherTestName?: string;
-  otherTestData: LaboratoryTestData | null;
-}
-
-function mapToFormValues(
-  responseData: ApiLaboratoryTestExamination,
-): LaboratoryTestExaminationData {
-  return {
-    sampleBarcode: responseData.sampleBarcode ?? "",
-    generalRemarks: responseData.generalRemarks ?? "",
-    testsConducted: responseData.testsConducted ?? false,
-    testsPayed: responseData.testsPayed ?? false,
-    //Requested Tests
-    hivTestRequested: responseData.hivTestRequested ?? false,
-    syphilisTestRequested: responseData.syphilisTestRequested ?? false,
-    hepATestRequested: responseData.hepATestRequested ?? false,
-    hepBTestRequested: responseData.hepBTestRequested ?? false,
-    hepCTestRequested: responseData.hepCTestRequested ?? false,
-    chlamydiaTestRequested: responseData.chlamydiaTestRequested ?? false,
-    gonorrheaTestRequested: responseData.gonorrheaTestRequested ?? false,
-    mycoplasmaTestRequested: responseData.mycoplasmaTestRequested ?? false,
-    cancerScreeningTestRequested:
-      responseData.cancerScreeningTestRequested ?? false,
-    hpvTestRequested: responseData.hpvTestRequested ?? false,
-    mpoxTestRequested: responseData.mpoxTestRequested ?? false,
-    otherTestRequested: responseData.otherTestRequested ?? false,
-    //Data of Tests
-    hivTestData: mapApiLaboratoryTestToFormData(responseData.hivTestData),
-    syphilisTestData: mapApiLaboratoryTestToFormData(
-      responseData.syphilisTestData,
-    ),
-    hadSyphilis: responseData.hadSyphilis ?? false,
-    hepATestData: mapApiHepatitisLaboratoryTestToFormData(
-      responseData.hepATestData,
-    ),
-    hepBTestData: mapApiHepatitisLaboratoryTestToFormData(
-      responseData.hepBTestData,
-    ),
-    hepCTestData: mapApiLaboratoryTestToFormData(responseData.hepCTestData),
-    chlamydiaTestData: mapApiLaboratoryTestSamplesToFormData(
-      responseData.chlamydiaTestSamples,
-    ),
-    gonorrheaTestData: mapApiLaboratoryTestSamplesToFormData(
-      responseData.gonorrheaTestSamples,
-    ),
-    mycoplasmaTestData: mapApiLaboratoryTestSamplesToFormData(
-      responseData.mycoplasmaTestSamples,
-    ),
-    cancerScreeningTestData: mapApiLaboratoryTestToFormData(
-      responseData.cancerScreeningTestData,
-    ),
-    hpvTestData: mapApiLaboratoryTestToFormData(responseData.hpvTestData),
-    mpoxTestData: mapApiLaboratoryTestToFormData(responseData.mpoxTestData),
-    otherTestName: responseData.otherTestRequested
-      ? (responseData.otherTestName ?? "")
-      : "",
-    otherTestData: mapApiLaboratoryTestToFormData(responseData.otherTestData),
-  };
-}
-
-function defaultLaboratoryTestExaminationFormValues(): LaboratoryTestExaminationData {
-  return {
-    sampleBarcode: "",
-    generalRemarks: "",
-    testsConducted: false,
-    testsPayed: false,
-    //Requested Tests
-    hivTestRequested: false,
-    syphilisTestRequested: false,
-    hepATestRequested: false,
-    hepBTestRequested: false,
-    hepCTestRequested: false,
-    chlamydiaTestRequested: false,
-    gonorrheaTestRequested: false,
-    mycoplasmaTestRequested: false,
-    cancerScreeningTestRequested: false,
-    hpvTestRequested: false,
-    mpoxTestRequested: false,
-    otherTestRequested: false,
-    //Data of Tests
-    hivTestData: defaultLaboratoryTestFormData,
-    syphilisTestData: defaultLaboratoryTestFormData,
-    hadSyphilis: false,
-    hepATestData: defaultHepatitisLaboratoryTestFormData,
-    hepBTestData: defaultHepatitisLaboratoryTestFormData,
-    hepCTestData: defaultLaboratoryTestFormData,
-    chlamydiaTestData: defaultLaboratoryTestSamplesFormData,
-    gonorrheaTestData: defaultLaboratoryTestSamplesFormData,
-    mycoplasmaTestData: defaultLaboratoryTestSamplesFormData,
-    cancerScreeningTestData: defaultLaboratoryTestFormData,
-    hpvTestData: defaultLaboratoryTestFormData,
-    mpoxTestData: defaultLaboratoryTestFormData,
-    otherTestName: "",
-    otherTestData: defaultLaboratoryTestFormData,
-  };
-}
-
-function mapFormValuesToApi(
-  formData: LaboratoryTestExaminationData,
-): ApiLaboratoryTestExamination {
-  return {
-    sampleBarcode: mapOptionalString(formData.sampleBarcode),
-    generalRemarks: mapOptionalString(formData.generalRemarks),
-    testsConducted: formData.testsConducted ?? false,
-    testsPayed: formData.testsPayed ?? false,
-    //Requested Tests
-    hivTestRequested: formData.hivTestRequested ?? false,
-    syphilisTestRequested: formData.syphilisTestRequested ?? false,
-    hepATestRequested: formData.hepATestRequested ?? false,
-    hepBTestRequested: formData.hepBTestRequested ?? false,
-    hepCTestRequested: formData.hepCTestRequested ?? false,
-    chlamydiaTestRequested: formData.chlamydiaTestRequested ?? false,
-    gonorrheaTestRequested: formData.gonorrheaTestRequested ?? false,
-    mycoplasmaTestRequested: formData.mycoplasmaTestRequested ?? false,
-    cancerScreeningTestRequested:
-      formData.cancerScreeningTestRequested ?? false,
-    hpvTestRequested: formData.hpvTestRequested ?? false,
-    mpoxTestRequested: formData.mpoxTestRequested ?? false,
-    otherTestRequested: formData.otherTestRequested ?? false,
-    //Data of Tests
-    hivTestData: guardValue(
-      formData.hivTestRequested,
-      mapLaboratoryTestFormDataToApi(formData.hivTestData),
-    ),
-    syphilisTestData: guardValue(
-      formData.syphilisTestRequested,
-      mapLaboratoryTestFormDataToApi(formData.syphilisTestData),
-    ),
-    hadSyphilis: guardValue(
-      formData.syphilisTestRequested,
-      formData.hadSyphilis,
-    ),
-    hepATestData: guardValue(
-      formData.hepATestRequested,
-      mapHepatitisLaboratoryTestFormDataToApi(formData.hepATestData),
-    ),
-    hepBTestData: guardValue(
-      formData.hepBTestRequested,
-      mapHepatitisLaboratoryTestFormDataToApi(formData.hepBTestData),
-    ),
-    hepCTestData: guardValue(
-      formData.hepCTestRequested,
-      mapLaboratoryTestFormDataToApi(formData.hepCTestData),
-    ),
-    chlamydiaTestSamples: guardValue(
-      formData.chlamydiaTestRequested,
-      mapLaboratoryTestSamplesFormDataToApi(formData.chlamydiaTestData),
-    ),
-    gonorrheaTestSamples: guardValue(
-      formData.gonorrheaTestRequested,
-      mapLaboratoryTestSamplesFormDataToApi(formData.gonorrheaTestData),
-    ),
-    mycoplasmaTestSamples: guardValue(
-      formData.mycoplasmaTestRequested,
-      mapLaboratoryTestSamplesFormDataToApi(formData.mycoplasmaTestData),
-    ),
-    cancerScreeningTestData: guardValue(
-      formData.cancerScreeningTestRequested,
-      mapLaboratoryTestFormDataToApi(formData.cancerScreeningTestData),
-    ),
-    hpvTestData: guardValue(
-      formData.hpvTestRequested,
-      mapLaboratoryTestFormDataToApi(formData.hpvTestData),
-    ),
-    mpoxTestData: guardValue(
-      formData.mpoxTestRequested,
-      mapLaboratoryTestFormDataToApi(formData.mpoxTestData),
-    ),
-    otherTestName: guardValue(
-      formData.otherTestRequested,
-      mapOptionalString(formData.otherTestName),
-    ),
-    otherTestData: guardValue(
-      formData.otherTestRequested,
-      mapLaboratoryTestFormDataToApi(formData.otherTestData),
-    ),
-  };
-}
+import {
+  LaboratoryTestExaminationData,
+  defaultLaboratoryTestExaminationFormValues,
+  mapFormValuesToApi,
+  mapToFormValues,
+} from "./helpers";
 
 interface LaboratoryTestExaminationProps {
   procedureId: string;
@@ -260,7 +47,11 @@ export function LaboratoryTestExamination(
   props: LaboratoryTestExaminationProps,
 ) {
   const { procedureId, laboratoryTestExamination: laboratoryTests } = props;
-  const upsertLaboratoryTests = useUpsertLaboratoryTest(procedureId);
+  const upsertLaboratoryTestOptions = useUpsertLaboratoryTestOptions({
+    procedureId,
+  });
+  const upsertLaboratoryTests = useUpsertLaboratoryTest({ procedureId });
+  const onCancel = useOnCancelForm<LaboratoryTestExaminationData>();
 
   function onSubmit(values: LaboratoryTestExaminationData) {
     return upsertLaboratoryTests.mutateAsync({
@@ -268,24 +59,6 @@ export function LaboratoryTestExamination(
     });
   }
 
-  const { openCancelDialog } = useConfirmationDialog();
-
-  function onCancel(
-    dirty: boolean,
-    reset: (
-      state?: Partial<FormikState<LaboratoryTestExaminationData>>,
-    ) => void,
-  ) {
-    if (!dirty) {
-      return;
-    }
-    openCancelDialog({
-      onConfirm: () => {
-        reset();
-      },
-    });
-  }
-
   return (
     <Formik
       initialValues={
@@ -296,8 +69,17 @@ export function LaboratoryTestExamination(
       onSubmit={onSubmit}
       enableReinitialize
     >
-      {({ dirty, resetForm, isSubmitting }) => (
+      {({ resetForm, dirty, isSubmitting, values }) => (
         <FormPlus sx={{ height: "100%", overflow: "hidden" }}>
+          <ConfirmLeaveDirtyFormEffect
+            onSaveMutation={{
+              mutationOptions: upsertLaboratoryTestOptions,
+              variableSupplier: () => ({
+                procedureId,
+                laboratoryTests: mapFormValuesToApi(values),
+              }),
+            }}
+          />
           <Box
             sx={{
               pt: 3,
@@ -425,7 +207,7 @@ export function LaboratoryTestExamination(
           </Box>
           <ExaminationStickyBottomButtonBar
             isSubmitting={isSubmitting}
-            onClick={() => onCancel(dirty, resetForm)}
+            onClick={() => onCancel({ dirty, reset: resetForm })}
           />
         </FormPlus>
       )}
@@ -446,7 +228,11 @@ function ExaminationTabInfo() {
       >
         <Stack paddingTop={1}>
           <Typography>Allgemeine Bemerkung</Typography>
-          <TextareaField name="generalRemarks" minRows={4} />
+          <TextareaFieldWithTextTemplates
+            name="generalRemarks"
+            minRows={4}
+            context={ApiTextTemplateContext.LaboratoryTestsRemark}
+          />
         </Stack>
         <CheckboxField name="testsConducted" label={"Tests durchgeführt"} />
         <CheckboxField name="testsPayed" label={"Tests bezahlt"} />
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/LaboratoryTestTemplates.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/LaboratoryTestTemplates.tsx
index ba3f34124aa49a47ff809e6007e05e889adf1b79..66d6adf9cd4f7e836eeb4d4e104ab249bd0c5359 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/LaboratoryTestTemplates.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/LaboratoryTestTemplates.tsx
@@ -3,201 +3,21 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiHepatitisLaboratoryTest,
-  ApiLaboratoryTest,
-  ApiLaboratoryTestSamples,
-} from "@eshg/employee-portal-api/stiProtection";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { Divider, Grid, Stack } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 import { useFormikContext } from "formik";
 import { PropsWithChildren, ReactNode } from "react";
 
-import {
-  YesOrNoFieldData,
-  YesOrNoWithFollowUp,
-  mapBoolToYesOrNo,
-  mapYesOrNoToBool,
-} from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/YesOrNoWithFollowUp";
+import { YesOrNoWithFollowUp } from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/YesOrNoWithFollowUp";
 import {
   SectionGrid,
   SubRow,
 } from "@/lib/businessModules/stiProtection/features/procedures/medicalHistory/SectionGrid";
-import {
-  areAllValuesUndefined,
-  guardValue,
-  mapOptionalBool,
-  mapOptionalString,
-} from "@/lib/businessModules/stiProtection/shared/helpers";
 import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
 import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
 
-import { LaboratoryTestExaminationData } from "./LaboratoryTestExamination";
-
-export interface LaboratoryTestData {
-  value: string;
-  result: YesOrNoFieldData;
-  remark: string;
-}
-
-export const defaultLaboratoryTestFormData = {
-  value: "",
-  result: null,
-  remark: "",
-};
-
-export function mapApiLaboratoryTestToFormData(
-  responseData: ApiLaboratoryTest | undefined,
-): LaboratoryTestData {
-  if (responseData === undefined) {
-    return defaultLaboratoryTestFormData;
-  }
-  return {
-    value: responseData.value ?? "",
-    result: mapBoolToYesOrNo(responseData.result),
-    remark: responseData.remark ?? "",
-  };
-}
-
-export function mapLaboratoryTestFormDataToApi(
-  formData: LaboratoryTestData | null,
-): ApiLaboratoryTest | undefined {
-  if (formData === null) {
-    return undefined;
-  }
-
-  const mappedValues = {
-    value: mapOptionalString(formData.value),
-    result: mapYesOrNoToBool(formData.result ?? ""),
-    remark: mapOptionalString(formData.remark),
-  };
-
-  if (areAllValuesUndefined(mappedValues)) {
-    return undefined;
-  } else {
-    return mappedValues;
-  }
-}
-
-export interface HepatitisLaboratoryTestData extends LaboratoryTestData {
-  infection?: boolean;
-  vaccineTitre?: boolean;
-}
-
-export const defaultHepatitisLaboratoryTestFormData = {
-  infection: false,
-  vaccineTitre: false,
-  value: "",
-  result: null,
-  remark: "",
-};
-
-export function mapApiHepatitisLaboratoryTestToFormData(
-  responseData: ApiHepatitisLaboratoryTest | undefined,
-): HepatitisLaboratoryTestData {
-  if (responseData === undefined) {
-    return defaultHepatitisLaboratoryTestFormData;
-  }
-  return {
-    infection: responseData.infection ?? false,
-    vaccineTitre: responseData.vaccineTitre ?? false,
-    value: responseData.value ?? "",
-    result: mapBoolToYesOrNo(responseData.result),
-    remark: responseData.remark ?? "",
-  };
-}
-
-export function mapHepatitisLaboratoryTestFormDataToApi(
-  formData: HepatitisLaboratoryTestData | null,
-): ApiHepatitisLaboratoryTest | undefined {
-  if (formData === null) {
-    return undefined;
-  }
-
-  const mappedValues = {
-    infection: mapOptionalBool(formData.infection),
-    vaccineTitre: mapOptionalBool(formData.vaccineTitre),
-    value: mapOptionalString(formData.value),
-    result: mapYesOrNoToBool(formData.result ?? ""),
-    remark: mapOptionalString(formData.remark),
-  };
-
-  if (areAllValuesUndefined(mappedValues)) {
-    return undefined;
-  } else {
-    return mappedValues;
-  }
-}
-
-export interface LaboratoryTestSamplesData {
-  oralSampleRequested: boolean;
-  oralSampleData: LaboratoryTestData;
-  urethralSampleRequested: boolean;
-  urethralSampleData: LaboratoryTestData;
-  analSampleRequested: boolean;
-  analSampleData: LaboratoryTestData;
-}
-
-export const defaultLaboratoryTestSamplesFormData = {
-  oralSampleRequested: false,
-  oralSampleData: defaultLaboratoryTestFormData,
-  urethralSampleRequested: false,
-  urethralSampleData: defaultLaboratoryTestFormData,
-  analSampleRequested: false,
-  analSampleData: defaultLaboratoryTestFormData,
-};
-
-export function mapApiLaboratoryTestSamplesToFormData(
-  responseData: ApiLaboratoryTestSamples | undefined,
-): LaboratoryTestSamplesData {
-  if (responseData === undefined) {
-    return defaultLaboratoryTestSamplesFormData;
-  }
-
-  return {
-    oralSampleRequested: responseData.oralSampleRequested ?? false,
-    oralSampleData: mapApiLaboratoryTestToFormData(responseData.oralSampleData),
-    urethralSampleRequested: responseData.urethralSampleRequested ?? false,
-    urethralSampleData: mapApiLaboratoryTestToFormData(
-      responseData.urethralSampleData,
-    ),
-    analSampleRequested: responseData.analSampleRequested ?? false,
-    analSampleData: mapApiLaboratoryTestToFormData(responseData.analSampleData),
-  };
-}
-
-export function mapLaboratoryTestSamplesFormDataToApi(
-  formData: LaboratoryTestSamplesData | null,
-): ApiLaboratoryTestSamples | undefined {
-  if (formData === null) {
-    return undefined;
-  }
-
-  const mappedValues = {
-    oralSampleRequested: mapOptionalBool(formData.oralSampleRequested),
-    oralSampleData: guardValue(
-      formData.oralSampleRequested,
-      mapLaboratoryTestFormDataToApi(formData.oralSampleData),
-    ),
-    urethralSampleRequested: mapOptionalBool(formData.urethralSampleRequested),
-    urethralSampleData: guardValue(
-      formData.urethralSampleRequested,
-      mapLaboratoryTestFormDataToApi(formData.urethralSampleData),
-    ),
-    analSampleRequested: mapOptionalBool(formData.analSampleRequested),
-    analSampleData: guardValue(
-      formData.analSampleRequested,
-      mapLaboratoryTestFormDataToApi(formData.analSampleData),
-    ),
-  };
-
-  if (areAllValuesUndefined(mappedValues)) {
-    return undefined;
-  } else {
-    return mappedValues;
-  }
-}
+import { LaboratoryTestExaminationData } from "./helpers";
 
 export interface LaboratoryTestProps extends PropsWithChildren {
   testRequestedPath: string;
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/helpers.ts b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/helpers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..22a34dc957d2a88eea1091a445f3435ab52b9aad
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/laboratoryTest/helpers.ts
@@ -0,0 +1,397 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  ApiHepatitisLaboratoryTest,
+  ApiLaboratoryTest,
+  ApiLaboratoryTestExamination,
+  ApiLaboratoryTestSamples,
+} from "@eshg/sti-protection-api";
+
+import {
+  YesOrNoFieldData,
+  mapBoolToYesOrNo,
+  mapYesOrNoToBool,
+} from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/YesOrNoWithFollowUp";
+import {
+  areAllValuesUndefined,
+  guardValue,
+  mapOptionalBool,
+  mapOptionalString,
+} from "@/lib/businessModules/stiProtection/shared/helpers";
+
+export interface LaboratoryTestData {
+  value: string;
+  result: YesOrNoFieldData;
+  remark: string;
+}
+
+export const defaultLaboratoryTestFormData = {
+  value: "",
+  result: null,
+  remark: "",
+};
+
+export function mapApiLaboratoryTestToFormData(
+  responseData: ApiLaboratoryTest | undefined,
+): LaboratoryTestData {
+  if (responseData === undefined) {
+    return defaultLaboratoryTestFormData;
+  }
+  return {
+    value: responseData.value ?? "",
+    result: mapBoolToYesOrNo(responseData.result),
+    remark: responseData.remark ?? "",
+  };
+}
+
+export function mapLaboratoryTestFormDataToApi(
+  formData: LaboratoryTestData | null,
+): ApiLaboratoryTest | undefined {
+  if (formData === null) {
+    return undefined;
+  }
+
+  const mappedValues = {
+    value: mapOptionalString(formData.value),
+    result: mapYesOrNoToBool(formData.result ?? ""),
+    remark: mapOptionalString(formData.remark),
+  };
+
+  if (areAllValuesUndefined(mappedValues)) {
+    return undefined;
+  } else {
+    return mappedValues;
+  }
+}
+
+export interface HepatitisLaboratoryTestData extends LaboratoryTestData {
+  infection?: boolean;
+  vaccineTitre?: boolean;
+}
+
+export const defaultHepatitisLaboratoryTestFormData = {
+  infection: false,
+  vaccineTitre: false,
+  value: "",
+  result: null,
+  remark: "",
+};
+
+export function mapApiHepatitisLaboratoryTestToFormData(
+  responseData: ApiHepatitisLaboratoryTest | undefined,
+): HepatitisLaboratoryTestData {
+  if (responseData === undefined) {
+    return defaultHepatitisLaboratoryTestFormData;
+  }
+  return {
+    infection: responseData.infection ?? false,
+    vaccineTitre: responseData.vaccineTitre ?? false,
+    value: responseData.value ?? "",
+    result: mapBoolToYesOrNo(responseData.result),
+    remark: responseData.remark ?? "",
+  };
+}
+
+export function mapHepatitisLaboratoryTestFormDataToApi(
+  formData: HepatitisLaboratoryTestData | null,
+): ApiHepatitisLaboratoryTest | undefined {
+  if (formData === null) {
+    return undefined;
+  }
+
+  const mappedValues = {
+    infection: mapOptionalBool(formData.infection),
+    vaccineTitre: mapOptionalBool(formData.vaccineTitre),
+    value: mapOptionalString(formData.value),
+    result: mapYesOrNoToBool(formData.result ?? ""),
+    remark: mapOptionalString(formData.remark),
+  };
+
+  if (areAllValuesUndefined(mappedValues)) {
+    return undefined;
+  } else {
+    return mappedValues;
+  }
+}
+
+export interface LaboratoryTestSamplesData {
+  oralSampleRequested: boolean;
+  oralSampleData: LaboratoryTestData;
+  urethralSampleRequested: boolean;
+  urethralSampleData: LaboratoryTestData;
+  analSampleRequested: boolean;
+  analSampleData: LaboratoryTestData;
+}
+
+export const defaultLaboratoryTestSamplesFormData = {
+  oralSampleRequested: false,
+  oralSampleData: defaultLaboratoryTestFormData,
+  urethralSampleRequested: false,
+  urethralSampleData: defaultLaboratoryTestFormData,
+  analSampleRequested: false,
+  analSampleData: defaultLaboratoryTestFormData,
+};
+
+export function mapApiLaboratoryTestSamplesToFormData(
+  responseData: ApiLaboratoryTestSamples | undefined,
+): LaboratoryTestSamplesData {
+  if (responseData === undefined) {
+    return defaultLaboratoryTestSamplesFormData;
+  }
+
+  return {
+    oralSampleRequested: responseData.oralSampleRequested ?? false,
+    oralSampleData: mapApiLaboratoryTestToFormData(responseData.oralSampleData),
+    urethralSampleRequested: responseData.urethralSampleRequested ?? false,
+    urethralSampleData: mapApiLaboratoryTestToFormData(
+      responseData.urethralSampleData,
+    ),
+    analSampleRequested: responseData.analSampleRequested ?? false,
+    analSampleData: mapApiLaboratoryTestToFormData(responseData.analSampleData),
+  };
+}
+
+export function mapLaboratoryTestSamplesFormDataToApi(
+  formData: LaboratoryTestSamplesData | null,
+): ApiLaboratoryTestSamples | undefined {
+  if (formData === null) {
+    return undefined;
+  }
+
+  const mappedValues = {
+    oralSampleRequested: mapOptionalBool(formData.oralSampleRequested),
+    oralSampleData: guardValue(
+      formData.oralSampleRequested,
+      mapLaboratoryTestFormDataToApi(formData.oralSampleData),
+    ),
+    urethralSampleRequested: mapOptionalBool(formData.urethralSampleRequested),
+    urethralSampleData: guardValue(
+      formData.urethralSampleRequested,
+      mapLaboratoryTestFormDataToApi(formData.urethralSampleData),
+    ),
+    analSampleRequested: mapOptionalBool(formData.analSampleRequested),
+    analSampleData: guardValue(
+      formData.analSampleRequested,
+      mapLaboratoryTestFormDataToApi(formData.analSampleData),
+    ),
+  };
+
+  if (areAllValuesUndefined(mappedValues)) {
+    return undefined;
+  } else {
+    return mappedValues;
+  }
+}
+
+export interface LaboratoryTestExaminationData {
+  sampleBarcode?: string;
+  generalRemarks?: string;
+  testsConducted?: boolean;
+  testsPayed?: boolean;
+  //Requested Tests
+  hivTestRequested?: boolean;
+  syphilisTestRequested?: boolean;
+  hepATestRequested?: boolean;
+  hepBTestRequested?: boolean;
+  hepCTestRequested?: boolean;
+  chlamydiaTestRequested?: boolean;
+  gonorrheaTestRequested?: boolean;
+  mycoplasmaTestRequested?: boolean;
+  cancerScreeningTestRequested?: boolean;
+  hpvTestRequested?: boolean;
+  mpoxTestRequested?: boolean;
+  otherTestRequested?: boolean;
+  //Data of Tests
+  hivTestData: LaboratoryTestData | null;
+  syphilisTestData: LaboratoryTestData | null;
+  hadSyphilis?: boolean;
+  hepATestData: HepatitisLaboratoryTestData | null;
+  hepBTestData: HepatitisLaboratoryTestData | null;
+  hepCTestData: LaboratoryTestData | null;
+  chlamydiaTestData: LaboratoryTestSamplesData | null;
+  gonorrheaTestData: LaboratoryTestSamplesData | null;
+  mycoplasmaTestData: LaboratoryTestSamplesData | null;
+  cancerScreeningTestData: LaboratoryTestData | null;
+  hpvTestData: LaboratoryTestData | null;
+  mpoxTestData: LaboratoryTestData | null;
+  otherTestName?: string;
+  otherTestData: LaboratoryTestData | null;
+}
+
+export function mapToFormValues(
+  responseData: ApiLaboratoryTestExamination,
+): LaboratoryTestExaminationData {
+  return {
+    sampleBarcode: responseData.sampleBarcode ?? "",
+    generalRemarks: responseData.generalRemarks ?? "",
+    testsConducted: responseData.testsConducted ?? false,
+    testsPayed: responseData.testsPayed ?? false,
+    //Requested Tests
+    hivTestRequested: responseData.hivTestRequested ?? false,
+    syphilisTestRequested: responseData.syphilisTestRequested ?? false,
+    hepATestRequested: responseData.hepATestRequested ?? false,
+    hepBTestRequested: responseData.hepBTestRequested ?? false,
+    hepCTestRequested: responseData.hepCTestRequested ?? false,
+    chlamydiaTestRequested: responseData.chlamydiaTestRequested ?? false,
+    gonorrheaTestRequested: responseData.gonorrheaTestRequested ?? false,
+    mycoplasmaTestRequested: responseData.mycoplasmaTestRequested ?? false,
+    cancerScreeningTestRequested:
+      responseData.cancerScreeningTestRequested ?? false,
+    hpvTestRequested: responseData.hpvTestRequested ?? false,
+    mpoxTestRequested: responseData.mpoxTestRequested ?? false,
+    otherTestRequested: responseData.otherTestRequested ?? false,
+    //Data of Tests
+    hivTestData: mapApiLaboratoryTestToFormData(responseData.hivTestData),
+    syphilisTestData: mapApiLaboratoryTestToFormData(
+      responseData.syphilisTestData,
+    ),
+    hadSyphilis: responseData.hadSyphilis ?? false,
+    hepATestData: mapApiHepatitisLaboratoryTestToFormData(
+      responseData.hepATestData,
+    ),
+    hepBTestData: mapApiHepatitisLaboratoryTestToFormData(
+      responseData.hepBTestData,
+    ),
+    hepCTestData: mapApiLaboratoryTestToFormData(responseData.hepCTestData),
+    chlamydiaTestData: mapApiLaboratoryTestSamplesToFormData(
+      responseData.chlamydiaTestSamples,
+    ),
+    gonorrheaTestData: mapApiLaboratoryTestSamplesToFormData(
+      responseData.gonorrheaTestSamples,
+    ),
+    mycoplasmaTestData: mapApiLaboratoryTestSamplesToFormData(
+      responseData.mycoplasmaTestSamples,
+    ),
+    cancerScreeningTestData: mapApiLaboratoryTestToFormData(
+      responseData.cancerScreeningTestData,
+    ),
+    hpvTestData: mapApiLaboratoryTestToFormData(responseData.hpvTestData),
+    mpoxTestData: mapApiLaboratoryTestToFormData(responseData.mpoxTestData),
+    otherTestName: responseData.otherTestRequested
+      ? (responseData.otherTestName ?? "")
+      : "",
+    otherTestData: mapApiLaboratoryTestToFormData(responseData.otherTestData),
+  };
+}
+
+export function defaultLaboratoryTestExaminationFormValues(): LaboratoryTestExaminationData {
+  return {
+    sampleBarcode: "",
+    generalRemarks: "",
+    testsConducted: false,
+    testsPayed: false,
+    //Requested Tests
+    hivTestRequested: false,
+    syphilisTestRequested: false,
+    hepATestRequested: false,
+    hepBTestRequested: false,
+    hepCTestRequested: false,
+    chlamydiaTestRequested: false,
+    gonorrheaTestRequested: false,
+    mycoplasmaTestRequested: false,
+    cancerScreeningTestRequested: false,
+    hpvTestRequested: false,
+    mpoxTestRequested: false,
+    otherTestRequested: false,
+    //Data of Tests
+    hivTestData: defaultLaboratoryTestFormData,
+    syphilisTestData: defaultLaboratoryTestFormData,
+    hadSyphilis: false,
+    hepATestData: defaultHepatitisLaboratoryTestFormData,
+    hepBTestData: defaultHepatitisLaboratoryTestFormData,
+    hepCTestData: defaultLaboratoryTestFormData,
+    chlamydiaTestData: defaultLaboratoryTestSamplesFormData,
+    gonorrheaTestData: defaultLaboratoryTestSamplesFormData,
+    mycoplasmaTestData: defaultLaboratoryTestSamplesFormData,
+    cancerScreeningTestData: defaultLaboratoryTestFormData,
+    hpvTestData: defaultLaboratoryTestFormData,
+    mpoxTestData: defaultLaboratoryTestFormData,
+    otherTestName: "",
+    otherTestData: defaultLaboratoryTestFormData,
+  };
+}
+
+export function mapFormValuesToApi(
+  formData: LaboratoryTestExaminationData,
+): ApiLaboratoryTestExamination {
+  return {
+    sampleBarcode: mapOptionalString(formData.sampleBarcode),
+    generalRemarks: mapOptionalString(formData.generalRemarks),
+    testsConducted: formData.testsConducted ?? false,
+    testsPayed: formData.testsPayed ?? false,
+    //Requested Tests
+    hivTestRequested: formData.hivTestRequested ?? false,
+    syphilisTestRequested: formData.syphilisTestRequested ?? false,
+    hepATestRequested: formData.hepATestRequested ?? false,
+    hepBTestRequested: formData.hepBTestRequested ?? false,
+    hepCTestRequested: formData.hepCTestRequested ?? false,
+    chlamydiaTestRequested: formData.chlamydiaTestRequested ?? false,
+    gonorrheaTestRequested: formData.gonorrheaTestRequested ?? false,
+    mycoplasmaTestRequested: formData.mycoplasmaTestRequested ?? false,
+    cancerScreeningTestRequested:
+      formData.cancerScreeningTestRequested ?? false,
+    hpvTestRequested: formData.hpvTestRequested ?? false,
+    mpoxTestRequested: formData.mpoxTestRequested ?? false,
+    otherTestRequested: formData.otherTestRequested ?? false,
+    //Data of Tests
+    hivTestData: guardValue(
+      formData.hivTestRequested,
+      mapLaboratoryTestFormDataToApi(formData.hivTestData),
+    ),
+    syphilisTestData: guardValue(
+      formData.syphilisTestRequested,
+      mapLaboratoryTestFormDataToApi(formData.syphilisTestData),
+    ),
+    hadSyphilis: guardValue(
+      formData.syphilisTestRequested,
+      formData.hadSyphilis,
+    ),
+    hepATestData: guardValue(
+      formData.hepATestRequested,
+      mapHepatitisLaboratoryTestFormDataToApi(formData.hepATestData),
+    ),
+    hepBTestData: guardValue(
+      formData.hepBTestRequested,
+      mapHepatitisLaboratoryTestFormDataToApi(formData.hepBTestData),
+    ),
+    hepCTestData: guardValue(
+      formData.hepCTestRequested,
+      mapLaboratoryTestFormDataToApi(formData.hepCTestData),
+    ),
+    chlamydiaTestSamples: guardValue(
+      formData.chlamydiaTestRequested,
+      mapLaboratoryTestSamplesFormDataToApi(formData.chlamydiaTestData),
+    ),
+    gonorrheaTestSamples: guardValue(
+      formData.gonorrheaTestRequested,
+      mapLaboratoryTestSamplesFormDataToApi(formData.gonorrheaTestData),
+    ),
+    mycoplasmaTestSamples: guardValue(
+      formData.mycoplasmaTestRequested,
+      mapLaboratoryTestSamplesFormDataToApi(formData.mycoplasmaTestData),
+    ),
+    cancerScreeningTestData: guardValue(
+      formData.cancerScreeningTestRequested,
+      mapLaboratoryTestFormDataToApi(formData.cancerScreeningTestData),
+    ),
+    hpvTestData: guardValue(
+      formData.hpvTestRequested,
+      mapLaboratoryTestFormDataToApi(formData.hpvTestData),
+    ),
+    mpoxTestData: guardValue(
+      formData.mpoxTestRequested,
+      mapLaboratoryTestFormDataToApi(formData.mpoxTestData),
+    ),
+    otherTestName: guardValue(
+      formData.otherTestRequested,
+      mapOptionalString(formData.otherTestName),
+    ),
+    otherTestData: guardValue(
+      formData.otherTestRequested,
+      mapLaboratoryTestFormDataToApi(formData.otherTestData),
+    ),
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/RapidTestExamination.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/RapidTestExamination.tsx
index 88c5ab7eef6dc7aad98d3062dbedac70e479b1e4..c62b38b01ff777d8806111611c2dfc9606e0b499 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/RapidTestExamination.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/RapidTestExamination.tsx
@@ -3,126 +3,38 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiRapidTestExamination } from "@eshg/employee-portal-api/stiProtection";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
+import {
+  ApiRapidTestExamination,
+  ApiTextTemplateContext,
+} from "@eshg/sti-protection-api";
 import { Box, Divider, Grid, Sheet, Stack, Typography } from "@mui/joy";
 import { Formik } from "formik";
 
-import { useUpsertRapidTest } from "@/lib/businessModules/stiProtection/api/mutations/examination";
+import {
+  useUpsertRapidTestOptions,
+  useUpsertRapidTests,
+} from "@/lib/businessModules/stiProtection/api/mutations/examination";
+import { TextareaFieldWithTextTemplates } from "@/lib/businessModules/stiProtection/components/textTemplates/TextareaFieldWithTextTemplates";
 import { ExaminationStickyBottomButtonBar } from "@/lib/businessModules/stiProtection/features/procedures/examination/ExaminationStickyBottomButtonBar";
 import { ExaminationTabNavPanel } from "@/lib/businessModules/stiProtection/features/procedures/examination/ExaminationTabNavPanel";
 import { useOnCancelForm } from "@/lib/businessModules/stiProtection/shared/helpers";
+import { ConfirmLeaveDirtyFormEffect } from "@/lib/shared/components/form/ConfirmLeaveDirtyFormEffect";
 import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
-import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
 import { SidePanel } from "@/lib/shared/components/sidePanel/SidePanel";
 import { SidePanelTitle } from "@/lib/shared/components/sidePanel/SidePanelTitle";
 
 import {
-  RapidTestData,
   RapidTestWithBooleanResult,
   RapidTestWithTextResult,
   RapidTestWithUnitStringResult,
-  mapRapidTestToApi,
-  mapRapidTestToForm,
 } from "./RapidTestTemplates";
-
-export interface RapidTestExaminationData {
-  hivTestRequested: boolean;
-  hivTestData: RapidTestData | null;
-  syphilisTestRequested: boolean;
-  syphilisTestData: RapidTestData | null;
-  ultrasoundTestRequested: boolean;
-  ultrasoundTestResult: string;
-  pregnancyTestRequested: boolean;
-  pregnancyTestData: RapidTestData | null;
-  bloodPressureTestRequested: boolean;
-  bloodPressureTestResult: string;
-  pulseTestRequested: boolean;
-  pulseTestResult: string;
-  urineTestRequested: boolean;
-  urineTestResult: string;
-  generalRemarks: string;
-  testsPayed: boolean;
-}
-
-function mapToFormValues(
-  responseData: ApiRapidTestExamination,
-): RapidTestExaminationData {
-  return {
-    hivTestRequested: responseData.hivRequested,
-    hivTestData: mapRapidTestToForm(responseData.hivData),
-    syphilisTestRequested: responseData.syphilisRequested,
-    syphilisTestData: mapRapidTestToForm(responseData.syphilisData),
-    ultrasoundTestRequested: responseData.ultrasoundRequested,
-    ultrasoundTestResult: responseData.ultrasoundData ?? "",
-    pregnancyTestRequested: responseData.pregnancyTestRequested,
-    pregnancyTestData: mapRapidTestToForm(responseData.pregnancyTestData),
-    bloodPressureTestRequested: responseData.bloodPressureRequested,
-    bloodPressureTestResult: responseData.bloodPressureData ?? "",
-    pulseTestRequested: responseData.pulseRequested,
-    pulseTestResult: responseData.pulseData ?? "",
-    urineTestRequested: responseData.urinalysisRequested,
-    urineTestResult: responseData.urinalysisData ?? "",
-    generalRemarks: responseData.generalComments ?? "",
-    testsPayed: responseData.testsPayed,
-  };
-}
-
-function defaultRapidTestExaminationFormValues(): RapidTestExaminationData {
-  return {
-    hivTestRequested: false,
-    hivTestData: mapRapidTestToForm(),
-    syphilisTestRequested: false,
-    syphilisTestData: mapRapidTestToForm(),
-    ultrasoundTestRequested: false,
-    ultrasoundTestResult: "",
-    pregnancyTestRequested: false,
-    pregnancyTestData: mapRapidTestToForm(),
-    bloodPressureTestRequested: false,
-    bloodPressureTestResult: "",
-    pulseTestRequested: false,
-    pulseTestResult: "",
-    urineTestRequested: false,
-    urineTestResult: "",
-    generalRemarks: "",
-    testsPayed: false,
-  };
-}
-
-function mapFormValuesToApi(
-  values: RapidTestExaminationData,
-): ApiRapidTestExamination {
-  return {
-    generalComments: values.generalRemarks ?? undefined,
-    testsPayed: values.testsPayed,
-    hivRequested: values.hivTestRequested,
-    syphilisRequested: values.syphilisTestRequested,
-    pregnancyTestRequested: values.pregnancyTestRequested,
-    ultrasoundRequested: values.ultrasoundTestRequested,
-    bloodPressureRequested: values.bloodPressureTestRequested,
-    pulseRequested: values.pulseTestRequested,
-    urinalysisRequested: values.urineTestRequested,
-    hivData: values.hivTestRequested
-      ? mapRapidTestToApi(values.hivTestData)
-      : undefined,
-    syphilisData: values.syphilisTestRequested
-      ? mapRapidTestToApi(values.syphilisTestData)
-      : undefined,
-    pregnancyTestData: values.pregnancyTestRequested
-      ? mapRapidTestToApi(values.pregnancyTestData)
-      : undefined,
-    ultrasoundData: values.ultrasoundTestRequested
-      ? values.ultrasoundTestResult
-      : undefined,
-    bloodPressureData: values.bloodPressureTestRequested
-      ? values.bloodPressureTestResult
-      : undefined,
-    pulseData: values.pulseTestRequested ? values.pulseTestResult : undefined,
-    urinalysisData: values.urineTestRequested
-      ? values.urineTestResult
-      : undefined,
-  };
-}
+import {
+  RapidTestExaminationData,
+  defaultRapidTestExaminationFormValues,
+  mapFormValuesToApi,
+  mapToFormValues,
+} from "./helpers";
 
 interface RapidTestExaminationProps {
   procedureId: string;
@@ -131,7 +43,9 @@ interface RapidTestExaminationProps {
 
 export function RapidTestExamination(props: RapidTestExaminationProps) {
   const { procedureId, rapidTestExamination: rapidTests } = props;
-  const upsertRapidTests = useUpsertRapidTest(procedureId);
+  const upsertRapidTestOptions = useUpsertRapidTestOptions({ procedureId });
+  const upsertRapidTests = useUpsertRapidTests({ procedureId });
+  const onCancel = useOnCancelForm<RapidTestExaminationData>();
 
   function onSubmit(values: RapidTestExaminationData) {
     return upsertRapidTests.mutateAsync({
@@ -139,8 +53,6 @@ export function RapidTestExamination(props: RapidTestExaminationProps) {
     });
   }
 
-  const onCancel = useOnCancelForm<RapidTestExaminationData>();
-
   return (
     <Formik
       initialValues={
@@ -151,8 +63,17 @@ export function RapidTestExamination(props: RapidTestExaminationProps) {
       onSubmit={onSubmit}
       enableReinitialize
     >
-      {({ dirty, resetForm, isSubmitting }) => (
+      {({ dirty, resetForm, isSubmitting, values }) => (
         <FormPlus sx={{ height: "100%", overflow: "hidden" }}>
+          <ConfirmLeaveDirtyFormEffect
+            onSaveMutation={{
+              mutationOptions: upsertRapidTestOptions,
+              variableSupplier: () => ({
+                procedureId,
+                rapidTests: mapFormValuesToApi(values),
+              }),
+            }}
+          />
           <Box
             sx={{
               pt: 3,
@@ -254,7 +175,11 @@ function ExaminationTabInfo() {
       >
         <Stack paddingTop={1}>
           <Typography>Allgemeine Bemerkung</Typography>
-          <TextareaField name="generalRemarks" minRows={4} />
+          <TextareaFieldWithTextTemplates
+            name="generalRemarks"
+            minRows={4}
+            context={ApiTextTemplateContext.RapidTestsRemark}
+          />
         </Stack>
         <CheckboxField name="testsPayed" label="Tests bezahlt" />
       </Stack>
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/RapidTestTemplates.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/RapidTestTemplates.tsx
index 593ed00c0a1d6eaa0fc8fe458d989df08bf3cc5e..cd5a37e915091cb11a223512e5abb0b5809acebd 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/RapidTestTemplates.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/RapidTestTemplates.tsx
@@ -3,61 +3,18 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiRapidTestData } from "@eshg/employee-portal-api/stiProtection";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
-import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
 import { isEmptyString } from "@eshg/lib-portal/helpers/guards";
 import { Grid, Stack } from "@mui/joy";
 import { useFormikContext } from "formik";
 import { PropsWithChildren } from "react";
 
-import {
-  YesOrNoFieldData,
-  YesOrNoWithFollowUp,
-  mapBoolToYesOrNo,
-  mapYesOrNoToBool,
-} from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/YesOrNoWithFollowUp";
+import { YesOrNoWithFollowUp } from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/YesOrNoWithFollowUp";
 import { FormGroupGrid } from "@/lib/shared/components/form/FormGroupGrid";
 import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
 import { TextareaField } from "@/lib/shared/components/formFields/TextareaField";
 
-import { RapidTestExaminationData } from "./RapidTestExamination";
-
-export interface RapidTestData {
-  number?: string;
-  result: YesOrNoFieldData;
-}
-
-export function mapRapidTestToForm(testData?: ApiRapidTestData): RapidTestData {
-  if (testData == undefined) {
-    return {
-      number: "",
-      result: null,
-    };
-  }
-  return {
-    number: testData.number,
-    result: mapBoolToYesOrNo(testData.result),
-  };
-}
-
-export function mapRapidTestToApi(
-  formData: RapidTestData | null,
-): ApiRapidTestData | undefined {
-  if (formData === null) {
-    return undefined;
-  }
-
-  const resultValue = mapYesOrNoToBool(formData.result);
-  if (resultValue === undefined) {
-    return undefined;
-  }
-
-  return {
-    number: mapOptionalValue(formData.number?.trim()),
-    result: !!resultValue,
-  };
-}
+import { RapidTestExaminationData } from "./helpers";
 
 export interface RapidTestProps extends PropsWithChildren {
   name: string;
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/helpers.ts b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/helpers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2eff53305e174a97ea9df172211e5a632c92e0b6
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/examination/rapidTest/helpers.ts
@@ -0,0 +1,150 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
+import {
+  ApiRapidTestData,
+  ApiRapidTestExamination,
+} from "@eshg/sti-protection-api";
+
+import {
+  YesOrNoFieldData,
+  mapBoolToYesOrNo,
+  mapYesOrNoToBool,
+} from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/YesOrNoWithFollowUp";
+
+export interface RapidTestData {
+  number?: string;
+  result: YesOrNoFieldData;
+}
+
+export interface RapidTestExaminationData {
+  hivTestRequested: boolean;
+  hivTestData: RapidTestData | null;
+  syphilisTestRequested: boolean;
+  syphilisTestData: RapidTestData | null;
+  ultrasoundTestRequested: boolean;
+  ultrasoundTestResult: string;
+  pregnancyTestRequested: boolean;
+  pregnancyTestData: RapidTestData | null;
+  bloodPressureTestRequested: boolean;
+  bloodPressureTestResult: string;
+  pulseTestRequested: boolean;
+  pulseTestResult: string;
+  urineTestRequested: boolean;
+  urineTestResult: string;
+  generalRemarks: string;
+  testsPayed: boolean;
+}
+
+export function mapRapidTestToForm(testData?: ApiRapidTestData): RapidTestData {
+  if (testData == undefined) {
+    return {
+      number: "",
+      result: null,
+    };
+  }
+  return {
+    number: testData.number,
+    result: mapBoolToYesOrNo(testData.result),
+  };
+}
+
+export function mapRapidTestToApi(
+  formData: RapidTestData | null,
+): ApiRapidTestData | undefined {
+  if (formData === null) {
+    return undefined;
+  }
+
+  const resultValue = mapYesOrNoToBool(formData.result);
+  if (resultValue === undefined) {
+    return undefined;
+  }
+
+  return {
+    number: mapOptionalValue(formData.number?.trim()),
+    result: resultValue,
+  };
+}
+
+export function mapToFormValues(
+  responseData: ApiRapidTestExamination,
+): RapidTestExaminationData {
+  return {
+    hivTestRequested: responseData.hivRequested,
+    hivTestData: mapRapidTestToForm(responseData.hivData),
+    syphilisTestRequested: responseData.syphilisRequested,
+    syphilisTestData: mapRapidTestToForm(responseData.syphilisData),
+    ultrasoundTestRequested: responseData.ultrasoundRequested,
+    ultrasoundTestResult: responseData.ultrasoundData ?? "",
+    pregnancyTestRequested: responseData.pregnancyTestRequested,
+    pregnancyTestData: mapRapidTestToForm(responseData.pregnancyTestData),
+    bloodPressureTestRequested: responseData.bloodPressureRequested,
+    bloodPressureTestResult: responseData.bloodPressureData ?? "",
+    pulseTestRequested: responseData.pulseRequested,
+    pulseTestResult: responseData.pulseData ?? "",
+    urineTestRequested: responseData.urinalysisRequested,
+    urineTestResult: responseData.urinalysisData ?? "",
+    generalRemarks: responseData.generalComments ?? "",
+    testsPayed: responseData.testsPayed,
+  };
+}
+
+export function defaultRapidTestExaminationFormValues(): RapidTestExaminationData {
+  return {
+    hivTestRequested: false,
+    hivTestData: mapRapidTestToForm(),
+    syphilisTestRequested: false,
+    syphilisTestData: mapRapidTestToForm(),
+    ultrasoundTestRequested: false,
+    ultrasoundTestResult: "",
+    pregnancyTestRequested: false,
+    pregnancyTestData: mapRapidTestToForm(),
+    bloodPressureTestRequested: false,
+    bloodPressureTestResult: "",
+    pulseTestRequested: false,
+    pulseTestResult: "",
+    urineTestRequested: false,
+    urineTestResult: "",
+    generalRemarks: "",
+    testsPayed: false,
+  };
+}
+
+export function mapFormValuesToApi(
+  values: RapidTestExaminationData,
+): ApiRapidTestExamination {
+  return {
+    generalComments: values.generalRemarks ?? undefined,
+    testsPayed: values.testsPayed,
+    hivRequested: values.hivTestRequested,
+    syphilisRequested: values.syphilisTestRequested,
+    pregnancyTestRequested: values.pregnancyTestRequested,
+    ultrasoundRequested: values.ultrasoundTestRequested,
+    bloodPressureRequested: values.bloodPressureTestRequested,
+    pulseRequested: values.pulseTestRequested,
+    urinalysisRequested: values.urineTestRequested,
+    hivData: values.hivTestRequested
+      ? mapRapidTestToApi(values.hivTestData)
+      : undefined,
+    syphilisData: values.syphilisTestRequested
+      ? mapRapidTestToApi(values.syphilisTestData)
+      : undefined,
+    pregnancyTestData: values.pregnancyTestRequested
+      ? mapRapidTestToApi(values.pregnancyTestData)
+      : undefined,
+    ultrasoundData: values.ultrasoundTestRequested
+      ? values.ultrasoundTestResult
+      : undefined,
+    bloodPressureData: values.bloodPressureTestRequested
+      ? values.bloodPressureTestResult
+      : undefined,
+    pulseData: values.pulseTestRequested ? values.pulseTestResult : undefined,
+    urinalysisData: values.urineTestRequested
+      ? values.urineTestResult
+      : undefined,
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/MedicalHistoryForm.config.ts b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/MedicalHistoryForm.config.ts
index 2657b8b32d1e7ce9641382f7c03353166f7f6fe9..6add93d8432d8ba4287ce348021830c035b19a0f 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/MedicalHistoryForm.config.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/MedicalHistoryForm.config.ts
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { MonthAndYear } from "@eshg/lib-portal/components/formFields/MonthAndYearFields";
 import {
   ApiConcern,
   ApiCreateMedicalHistoryRequest,
@@ -16,8 +17,7 @@ import {
   ApiSexWorkLocation,
   ApiSexualOrientation,
   ApiVaccination,
-} from "@eshg/employee-portal-api/stiProtection";
-import { MonthAndYear } from "@eshg/lib-portal/components/formFields/MonthAndYearFields";
+} from "@eshg/sti-protection-api";
 
 import { YesOrNoFieldData } from "@/lib/businessModules/stiProtection/components/procedures/procedureDetails/YesOrNoWithFollowUp";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/MedicalHistoryForm.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/MedicalHistoryForm.tsx
index ebb156ae1ab8f6a1132a8f3e58e574f8e4786c69..dc34fd52c458ef503375b1c26dbee68c435a4e26 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/MedicalHistoryForm.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/MedicalHistoryForm.tsx
@@ -5,15 +5,15 @@
 
 "use client";
 
-import {
-  ApiConcern,
-  ApiGetMedicalHistory200Response,
-  ApiStiProtectionProcedure,
-} from "@eshg/employee-portal-api/stiProtection";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { HorizontalField } from "@eshg/lib-portal/components/formFields/HorizontalField";
 import { InternalLinkButton } from "@eshg/lib-portal/components/navigation/InternalLinkButton";
+import {
+  ApiConcern,
+  ApiGetMedicalHistory200Response,
+  ApiStiProtectionProcedure,
+} from "@eshg/sti-protection-api";
 import Print from "@mui/icons-material/Print";
 import { Button, Divider, Sheet, Typography, styled } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
@@ -108,7 +108,7 @@ export function MedicalHistoryForm({
     setOpenFile(true);
   }
 
-  function onSubmit(values: MedicalHistoryFormData) {
+  async function onSubmit(values: MedicalHistoryFormData) {
     return upsertMedicalHistory.mutateAsync(
       mapFormValuesToApi(stiProcedure, values),
     );
@@ -122,6 +122,7 @@ export function MedicalHistoryForm({
           : defaultMedicalHistoryFormValues()
       }
       onSubmit={onSubmit}
+      enableReinitialize
     >
       {({ isSubmitting, values }) => (
         <FormPlus>
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/helpers.ts b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/helpers.ts
index c3949a03372cd75f78647487502e3e99878a687b..80779c9a840940e58164557379ec47245da7bafa 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/helpers.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/helpers.ts
@@ -3,6 +3,11 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import {
+  MonthAndYear,
+  mapMonthAndYear,
+} from "@eshg/lib-portal/components/formFields/MonthAndYearFields";
+import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
 import {
   ApiCreateMedicalHistoryRequest,
   ApiExamination,
@@ -14,12 +19,7 @@ import {
   ApiSexWorkMedicalHistory,
   ApiSexWorkRiskContact,
   ApiStiProtectionProcedure,
-} from "@eshg/employee-portal-api/stiProtection";
-import {
-  MonthAndYear,
-  mapMonthAndYear,
-} from "@eshg/lib-portal/components/formFields/MonthAndYearFields";
-import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
+} from "@eshg/sti-protection-api";
 
 import {
   mapBoolToYesOrNo,
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/options.ts b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/options.ts
index 5d89153391f2bed4b30bf6f1e83c1661989bb990..bccc076fa2ab1d99d11cc952a905c7b203dd7c1c 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/options.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/medicalHistory/options.ts
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 import {
   ApiGender,
   ApiPartnerRiskFactors,
@@ -12,8 +13,7 @@ import {
   ApiSexWorkLocation,
   ApiSexualOrientation,
   ApiVaccination,
-} from "@eshg/employee-portal-api/stiProtection";
-import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
+} from "@eshg/sti-protection-api";
 
 import {
   sexualContactNames as sexualContactGenderNames,
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/translations.ts b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/translations.ts
index 14465e885a9dc7ac847e7a77b803023fab1b2a99..500b75b740c7b08201baf48d12236ce0a5273cf9 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/translations.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/procedures/translations.ts
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiWaitingStatus } from "@eshg/employee-portal-api/stiProtection";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 import { EnumMap } from "@eshg/lib-portal/types/helpers";
+import { ApiWaitingStatus } from "@eshg/sti-protection-api";
 
 export const WAITING_STATUS_VALUES: EnumMap<ApiWaitingStatus> = {
   [ApiWaitingStatus.WaitingForConsultation]: "Wartet auf Beratung",
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/waitingRoom/StatusChip.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/waitingRoom/StatusChip.tsx
index 65af32d73b2bc64815141925a570c3bec62eb26f..cbe72ca59505b2959da7eed2955f3cef519ead92 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/waitingRoom/StatusChip.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/waitingRoom/StatusChip.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiWaitingStatus } from "@eshg/employee-portal-api/stiProtection";
+import { ApiWaitingStatus } from "@eshg/sti-protection-api";
 import { Chip, ChipProps } from "@mui/joy";
 
 import { WAITING_STATUS_VALUES } from "@/lib/businessModules/stiProtection/features/procedures/translations";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/waitingRoom/WaitingRoomTable.tsx b/employee-portal/src/lib/businessModules/stiProtection/features/waitingRoom/WaitingRoomTable.tsx
index 7101d7a5e811ff5afdefa00fedad1e15844e4c81..4615807f9575ad5a60712cd399f912c477d9c925 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/waitingRoom/WaitingRoomTable.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/features/waitingRoom/WaitingRoomTable.tsx
@@ -5,11 +5,11 @@
 
 "use client";
 
+import { ifDefined } from "@eshg/lib-portal/helpers/ifDefined";
 import {
   ApiWaitingRoomProcedure,
   ApiWaitingRoomSortKey,
-} from "@eshg/employee-portal-api/stiProtection";
-import { ifDefined } from "@eshg/lib-portal/helpers/ifDefined";
+} from "@eshg/sti-protection-api";
 import { ColumnSort, createColumnHelper } from "@tanstack/react-table";
 import { differenceInMinutes } from "date-fns";
 
diff --git a/employee-portal/src/lib/businessModules/stiProtection/shared/constants.ts b/employee-portal/src/lib/businessModules/stiProtection/shared/constants.ts
index 19d7f01c22751ca3c3666f700b137a3e48ea3336..1bb9ce0c4f30e462995e65a8c77077632d1b985d 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/shared/constants.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/shared/constants.ts
@@ -3,18 +3,19 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { EnumMap } from "@eshg/lib-portal/types/helpers";
 import {
   ApiAppointmentStatus,
   ApiAppointmentType,
   ApiConcern,
   ApiExamination,
   ApiGender,
+  ApiLabStatus,
   ApiProcedureStatus,
   ApiProcedureType,
   ApiSexualOrientation,
   ApiTaskType,
-} from "@eshg/employee-portal-api/stiProtection";
-import { EnumMap } from "@eshg/lib-portal/types/helpers";
+} from "@eshg/sti-protection-api";
 import { DefaultColorPalette } from "@mui/joy/styles/types";
 
 export const procedureTypes = [ApiProcedureType.StiProtection];
@@ -112,3 +113,9 @@ export const examinableIllnessNames = {
   hiv: "HIV",
   syphilis: "Syphilis (Lues)",
 } as const satisfies Record<ExaminableIllnesses, string>;
+
+export const LAB_STATUS_VALUES: EnumMap<ApiLabStatus> = {
+  [ApiLabStatus.Open]: "Offen",
+  [ApiLabStatus.InProgress]: "In Bearbeitung",
+  [ApiLabStatus.Closed]: "Geschlossen",
+};
diff --git a/employee-portal/src/lib/businessModules/stiProtection/shared/helpers.ts b/employee-portal/src/lib/businessModules/stiProtection/shared/helpers.ts
index 5639a3ce6267a1f2bf0dfc033e1cf41887ac8775..40551378b242a20d43fd4a9f565ca026feb99c1c 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/shared/helpers.ts
+++ b/employee-portal/src/lib/businessModules/stiProtection/shared/helpers.ts
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
 import {
   ApiAppointmentHistoryEntry,
   ApiAppointmentType,
   ApiConcern,
   ApiStiProtectionProcedure,
   ApiStiProtectionProcedureOverview,
-} from "@eshg/employee-portal-api/stiProtection";
-import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
+} from "@eshg/sti-protection-api";
 import { FormikState } from "formik";
 
 import { useConfirmationDialog } from "@/lib/shared/hooks/useConfirmationDialog";
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AppointmentForm.tsx b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/AppointmentForm.tsx
similarity index 87%
rename from employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AppointmentForm.tsx
rename to employee-portal/src/lib/businessModules/stiProtection/shared/procedure/AppointmentForm.tsx
index 62541b25aba42cc424153e225b89203b80151187..cf1e60281b6f570eccdf2cea2044d2361f8f8432 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AppointmentForm.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/AppointmentForm.tsx
@@ -3,11 +3,6 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiAppointmentBookingType,
-  ApiAppointmentType,
-  ApiConcern,
-} from "@eshg/employee-portal-api/stiProtection";
 import { Row } from "@eshg/lib-portal/components/Row";
 import { NumberField } from "@eshg/lib-portal/components/formFields/NumberField";
 import {
@@ -17,6 +12,12 @@ import {
 import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/autocomplete/SingleAutocompleteField";
 import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
 import { ifDefined } from "@eshg/lib-portal/helpers/ifDefined";
+import {
+  ApiAppointment,
+  ApiAppointmentBookingType,
+  ApiAppointmentType,
+  ApiConcern,
+} from "@eshg/sti-protection-api";
 import { UnfoldMore } from "@mui/icons-material";
 import { Box, Button, FormLabel, Stack, Typography } from "@mui/joy";
 import { addMinutes, startOfHour } from "date-fns";
@@ -29,7 +30,6 @@ import {
   RadioSheets,
 } from "@/lib/businessModules/stiProtection/components/RadioSheets";
 import { appointmentOptionsByConcern } from "@/lib/businessModules/stiProtection/components/appointmentBlocks/options";
-import { CreateAppointmentForm } from "@/lib/businessModules/stiProtection/features/procedures/details/CreateAppointmentSidebar";
 import { concernToAppointmentType } from "@/lib/businessModules/stiProtection/shared/helpers";
 import { DateTimeField } from "@/lib/shared/components/formFields/DateTimeField";
 import {
@@ -37,13 +37,25 @@ import {
   validateTodayOrFutureDate,
 } from "@/lib/shared/helpers/validators";
 
-import { AddNewProcedureForm } from "./AddNewProcedureSidebar";
+export interface CreateAppointmentForm {
+  appointmentType?: ApiAppointmentType | "" | null;
+  appointmentBookingType?: ApiAppointmentBookingType | "";
+  blockAppointment?: null | ApiAppointment;
+  concern?: ApiConcern | "RESULTS_REVIEW" | "";
+  customAppointmentDate: string;
+  customAppointmentDuration: string;
+}
 
-export type CombinedAppointmentForm = Partial<
-  AddNewProcedureForm & CreateAppointmentForm
->;
+export const initialValues: CreateAppointmentForm = {
+  appointmentType: null,
+  appointmentBookingType: "",
+  blockAppointment: null,
+  concern: "",
+  customAppointmentDate: "",
+  customAppointmentDuration: "",
+};
 
-function ConnectedAppointmentPicker({
+function ConnectedAppointmentPicker<TForm extends CreateAppointmentForm>({
   name,
   appointmentType,
 }: {
@@ -52,7 +64,7 @@ function ConnectedAppointmentPicker({
 }) {
   const {
     values: { blockAppointment },
-  } = useFormikContext<CombinedAppointmentForm>();
+  } = useFormikContext<TForm>();
 
   const initialMonth = blockAppointment?.start ?? null;
   const [currentMonth, setCurrentMonth] = useState(initialMonth ?? new Date());
@@ -85,14 +97,14 @@ function ConnectedAppointmentPicker({
   );
 }
 
-export function AppointmentForm({
+export function AppointmentForm<TForm extends CreateAppointmentForm>({
   startingConcern,
   editAppointmentType,
 }: Readonly<{
   startingConcern?: ApiConcern;
   editAppointmentType?: ApiAppointmentType;
 }>) {
-  const { values } = useFormikContext<CombinedAppointmentForm>();
+  const { values } = useFormikContext<TForm>();
 
   const customSectionSelected =
     values.appointmentBookingType === ApiAppointmentBookingType.UserDefined;
@@ -160,8 +172,8 @@ export function AppointmentForm({
   );
 }
 
-function CustomAppointmentQuickButtons() {
-  const { setFieldValue } = useFormikContext<AddNewProcedureForm>();
+function CustomAppointmentQuickButtons<TForm>() {
+  const { setFieldValue } = useFormikContext<TForm>();
   function setCustomAppointment(inMinutes: number) {
     const now = new Date();
     const roundTo = 5;
diff --git a/employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/SharePinModal.tsx b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/SharePinModal.tsx
similarity index 100%
rename from employee-portal/src/lib/businessModules/stiProtection/features/procedures/addNewProcedure/SharePinModal.tsx
rename to employee-portal/src/lib/businessModules/stiProtection/shared/procedure/SharePinModal.tsx
diff --git a/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/helpers.tsx b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/helpers.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..df8cd048bb6b6d3637504c026e6571893e4df7df
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/helpers.tsx
@@ -0,0 +1,15 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { ApiConcern } from "@eshg/sti-protection-api";
+
+import { CONCERN_VALUES } from "@/lib/businessModules/stiProtection/shared/constants";
+
+export const CONCERN_OPTIONS = Object.entries(CONCERN_VALUES).map(
+  ([value, label]) => ({
+    content: <b>{label}</b>,
+    value: value as ApiConcern,
+  }),
+);
diff --git a/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/mappers.ts b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/mappers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fd923559078d87094ec4cfe6b797e3d841b137b6
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/mappers.ts
@@ -0,0 +1,94 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { GENDER_OPTIONS } from "@eshg/lib-portal/components/formFields/constants";
+import { countryOptions } from "@eshg/lib-portal/helpers/countryOption";
+import { isNonEmptyString } from "@eshg/lib-portal/helpers/guards";
+import {
+  ApiAppointmentBookingType,
+  ApiCreateFollowUpProcedureRequest,
+  ApiCreateProcedureRequest,
+  ApiGender,
+} from "@eshg/sti-protection-api";
+import { differenceInMinutes } from "date-fns/differenceInMinutes";
+
+import {
+  AddNewProcedureForm,
+  CombinedAppointmentForm,
+} from "@/lib/businessModules/stiProtection/features/procedures/addNewProcedure/AddNewProcedureSidebar";
+import { CreateFollowUpProcedureForm } from "@/lib/businessModules/stiProtection/features/procedures/details/CreateFollowUpProcedureSidebar";
+import {
+  deleteUndefined,
+  optionalInt,
+} from "@/lib/businessModules/stiProtection/shared/helpers";
+
+import { CONCERN_OPTIONS } from "./helpers";
+
+export function mapFollowUpProcedureFormToApi(
+  form: CreateFollowUpProcedureForm,
+): ApiCreateFollowUpProcedureRequest {
+  if (!form.appointmentBookingType) {
+    throw new Error("Appointment booking type must be defined");
+  }
+
+  const isCustomAppointment =
+    form.appointmentBookingType === ApiAppointmentBookingType.UserDefined;
+
+  const appointmentStart = isCustomAppointment
+    ? new Date(form.customAppointmentDate)
+    : form.blockAppointment?.start;
+
+  if (!appointmentStart) {
+    throw new Error("Appointment start must be defined");
+  }
+
+  const blockAppointmentEnd = form.blockAppointment?.end;
+  if (!isCustomAppointment && blockAppointmentEnd == null) {
+    throw new Error("Appointment end must be defined");
+  }
+
+  return deleteUndefined({
+    appointmentBookingType: form.appointmentBookingType,
+    concern: CONCERN_OPTIONS.find((t) => t.value === form.concern)?.value,
+    durationInMinutes: isCustomAppointment
+      ? optionalInt(form.customAppointmentDuration)
+      : differenceInMinutes(blockAppointmentEnd!, appointmentStart),
+    appointmentStart,
+  });
+}
+
+export function mapProcedureFormToApi(
+  form: AddNewProcedureForm,
+): ApiCreateProcedureRequest {
+  if (!form.yearOfBirth) {
+    throw new Error("Year of birth must be defined");
+  }
+  if (!form.appointmentBookingType) {
+    throw new Error("Appointment booking type must be defined");
+  }
+
+  return deleteUndefined({
+    ...mapFollowUpProcedureFormToApi(form),
+    countryOfBirth: countryOptions().find(
+      (t) => t.value === form.countryOfBirth,
+    )?.value,
+    gender: GENDER_OPTIONS.find((t) => t.value === form.gender)?.value as
+      | ApiGender
+      | undefined,
+    inGermanySince: optionalInt(form.inGermanySince),
+    yearOfBirth: parseInt(form.yearOfBirth, 10),
+  });
+}
+
+export function getAppointmentDate(form: CombinedAppointmentForm) {
+  const customAppointmentDate = isNonEmptyString(form.customAppointmentDate)
+    ? new Date(form.customAppointmentDate)
+    : undefined;
+  const date =
+    form.appointmentBookingType === ApiAppointmentBookingType.AppointmentBlock
+      ? form.blockAppointment?.start
+      : customAppointmentDate;
+  return date ?? undefined;
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/useFormWithSteps.ts b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/useFormWithSteps.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f5d9779872766f01b3dcea9b38c5816d1f285678
--- /dev/null
+++ b/employee-portal/src/lib/businessModules/stiProtection/shared/procedure/useFormWithSteps.ts
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { useReducer } from "react";
+
+export interface Step<TProps, TForm> {
+  title: string;
+  subTitle: string;
+  fields: (props: TProps) => JSX.Element;
+  validate?: (form: TForm) => Partial<Record<keyof TForm, string>> | undefined;
+}
+
+export interface useFormWithStepsArgs<TForm, TStep> {
+  steps: Step<TStep, TForm>[];
+  onFinalSubmit: (form: TForm) => Promise<unknown>;
+}
+
+export function useFormWithSteps<TForm, TStep>(
+  args: useFormWithStepsArgs<TForm, TStep>,
+) {
+  const { steps, onFinalSubmit } = args;
+
+  const lastStepIndex = steps.length - 1;
+  const [stepIndex, changeToStep] = useReducer(
+    (_index: number, newIndex: number) =>
+      Math.max(Math.min(newIndex, lastStepIndex), 0),
+    0,
+  );
+
+  const step = steps[stepIndex]!;
+
+  const isOnFirstStep = stepIndex === 0;
+  const isOnLastStep = stepIndex === lastStepIndex;
+
+  function handleNext(newValues: TForm) {
+    if (isOnLastStep) {
+      return onFinalSubmit(newValues);
+    }
+    changeToStep(stepIndex + 1);
+  }
+
+  function handlePrev() {
+    changeToStep(stepIndex - 1);
+  }
+
+  const Fields = step.fields;
+
+  return {
+    Fields,
+    handleNext,
+    handlePrev,
+    changeToStep,
+    step,
+    isOnFirstStep,
+    isOnLastStep,
+  };
+}
diff --git a/employee-portal/src/lib/businessModules/stiProtection/shared/sideNavigationItem.tsx b/employee-portal/src/lib/businessModules/stiProtection/shared/sideNavigationItem.tsx
index a53edb9016ec02413da95a69cf08f82fe085a68b..b50b99f69955b4bbeb9455dd83773440aa4c28e8 100644
--- a/employee-portal/src/lib/businessModules/stiProtection/shared/sideNavigationItem.tsx
+++ b/employee-portal/src/lib/businessModules/stiProtection/shared/sideNavigationItem.tsx
@@ -41,6 +41,11 @@ const defaultSubItems: SideNavigationSubItem[] = [
     href: routes.appointmentDefinition,
     accessCheck: hasUserRole(ApiUserRole.StiProtectionUser),
   },
+  {
+    name: "Textvorlagen",
+    href: routes.textTemplates,
+    accessCheck: hasUserRole(ApiUserRole.StiProtectionUser),
+  },
 ];
 
 export function useSideNavigationItems(
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/api/queries/archiving.ts b/employee-portal/src/lib/businessModules/travelMedicine/api/queries/archiving.ts
index 43dc08ccd650048c4681986833cd89c4e0e7c15b..4fe72d51cfb878a95de57e02741d1cd03fc8475e 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/api/queries/archiving.ts
+++ b/employee-portal/src/lib/businessModules/travelMedicine/api/queries/archiving.ts
@@ -6,7 +6,7 @@
 import {
   GetArchivableProceduresRequest,
   GetRelevantArchivableProceduresRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 
 import { useArchivingApi } from "@/lib/businessModules/travelMedicine/api/clients";
 import { archivingApiQueryKey } from "@/lib/businessModules/travelMedicine/api/queries/queryKeys";
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
index 00315b1348fcac800fc2e16af71275982a15d623..7a05f3316779061cda37fd9ea214638ce5170a8a 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/appointmentBlocks/appointmentBlocksGroupForm/AppointmentBlockGroupForm.tsx
@@ -24,7 +24,6 @@ import { AppointmentStaffSelection } from "@/lib/shared/components/appointmentBl
 import { validateAppointmentBlock } from "@/lib/shared/components/appointmentBlocks/validateAppointmentBlock";
 import { FormButtonBar } from "@/lib/shared/components/form/FormButtonBar";
 import { FormSheet } from "@/lib/shared/components/form/FormSheet";
-import { fullName } from "@/lib/shared/components/users/userFormatter";
 import { validateFieldArray } from "@/lib/shared/helpers/validators";
 
 const DEFAULT_PARALLEL_EXAMINATIONS = 1;
@@ -93,13 +92,15 @@ export function AppointmentBlockGroupForm(
 ) {
   const snackbar = useSnackbar();
   const physicianOptions = props.allPhysicians.map((option) => ({
-    value: option.userId,
-    label: fullName(option),
+    userId: option.userId,
+    firstName: option.firstName,
+    lastName: option.lastName,
   }));
 
   const medicalAssistantsOptions = props.allMedicalAssistants.map((option) => ({
-    value: option.userId,
-    label: fullName(option),
+    userId: option.userId,
+    firstName: option.firstName,
+    lastName: option.lastName,
   }));
 
   return (
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/VaccinationConsultationsOverviewTable.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/VaccinationConsultationsOverviewTable.tsx
index be5e23576eb13475c76a5a97579b71e34639ad77..81926acb5b0238489456e19e35d0662e57be47b8 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/VaccinationConsultationsOverviewTable.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/VaccinationConsultationsOverviewTable.tsx
@@ -5,13 +5,13 @@
 
 "use client";
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
 import { SelectOptions } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import {
   isDateString,
   toDateString,
   toUtcDate,
 } from "@eshg/lib-portal/helpers/dateTime";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 import { ApiProcedureStatus } from "@eshg/travel-medicine-api";
 import {
   KeyboardArrowLeftOutlined,
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/PatientDetails.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/PatientDetails.tsx
index 4c006782aa6ae9507a78f7a40466c6c0606250a9..5e89164075d4980a946a5be89bce552bc521a466 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/PatientDetails.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/PatientDetails.tsx
@@ -11,7 +11,6 @@ import {
 } from "@eshg/lib-portal/components/formFields/constants";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
-import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import {
   ApiGender,
   ApiPatient,
@@ -23,8 +22,8 @@ import { isDefined } from "remeda";
 
 import { instanceOfApiGetReferencePersonResponse } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/AcceptProcedureSidebar";
 import { BaseAddressDetails } from "@/lib/shared/components/address/BaseAddressDetails";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsRow } from "@/lib/shared/components/detailsSection/DetailsRow";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
 import { SidebarForm } from "@/lib/shared/components/form/SidebarForm";
 import { SidebarActions } from "@/lib/shared/components/sidebar/SidebarActions";
@@ -44,9 +43,6 @@ export interface PatientDetailsProps {
 }
 
 export function PatientDetails(props: Readonly<PatientDetailsProps>) {
-  const fieldName = createFieldNameMapper<
-    ApiGetReferencePersonResponse | ApiPatient
-  >();
   const person = instanceOfApiGetReferencePersonResponse(props.person)
     ? props.person
     : {
@@ -96,61 +92,39 @@ export function PatientDetails(props: Readonly<PatientDetailsProps>) {
           <SidebarContent title={props.title} subtitle="Ausgewählte Person">
             <Stack gap={2}>
               <DetailsRow>
-                <DetailsCell
-                  name={fieldName("salutation")}
+                <DetailsItem
                   label={"Anrede"}
                   value={SALUTATION_VALUES[person.salutation]}
-                  flexGrow
                 />
-                <DetailsCell
-                  name={fieldName("title")}
+                <DetailsItem
                   label={"Titel"}
                   value={getOptionalTitle(person.title)}
-                  flexGrow
                   avoidWrap
                 />
               </DetailsRow>
               <DetailsRow>
-                <DetailsCell
-                  name={fieldName("firstName")}
-                  label={"Vorname"}
-                  value={person.firstName}
-                  flexGrow
-                />
-                <DetailsCell
-                  name={fieldName("lastName")}
-                  label={"Name"}
-                  value={person.lastName}
-                  flexGrow
-                  avoidWrap
-                />
+                <DetailsItem label={"Vorname"} value={person.firstName} />
+                <DetailsItem label={"Name"} value={person.lastName} avoidWrap />
               </DetailsRow>
               <DetailsRow>
-                <DetailsCell
-                  name={fieldName("dateOfBirth")}
+                <DetailsItem
                   label={"Geburtsdatum"}
                   value={formatDate(person.dateOfBirth)}
-                  flexGrow
                 />
-                <DetailsCell
-                  name={fieldName("gender")}
+                <DetailsItem
                   label={"Geschlecht"}
                   value={GENDER_VALUES[person.gender]}
-                  flexGrow
                 />
               </DetailsRow>
-              <DetailsCell
-                name={fieldName("nameAtBirth")}
+              <DetailsItem
                 label={"Geburtsname"}
                 value={props.person.nameAtBirth}
               />
-              <DetailsCell
-                name={fieldName("placeOfBirth")}
+              <DetailsItem
                 label={"Geburtsort"}
                 value={props.person.placeOfBirth}
               />
-              <DetailsCell
-                name={fieldName("countryOfBirth")}
+              <DetailsItem
                 label={"Geburtsland"}
                 value={
                   isDefined(props.person.countryOfBirth)
@@ -170,17 +144,15 @@ export function PatientDetails(props: Readonly<PatientDetailsProps>) {
                 <>
                   <Divider />
                   {person.emailAddresses.map((email, index) => (
-                    <DetailsCell
+                    <DetailsItem
                       key={`${email}-${index}`}
-                      name={fieldName("emailAddresses") + "." + index}
                       label={"E-Mail-Adresse"}
                       value={email}
                     />
                   ))}
                   {person.phoneNumbers.map((phoneNumber, index) => (
-                    <DetailsCell
+                    <DetailsItem
                       key={`${phoneNumber}-${index}`}
-                      name={fieldName("phoneNumbers") + "." + index}
                       label={"Telefonnummer"}
                       value={phoneNumber}
                     />
@@ -197,9 +169,8 @@ export function PatientDetails(props: Readonly<PatientDetailsProps>) {
                   </Divider>
                   {isDefined(props.initialPatient.emailAddresses) &&
                     props.initialPatient.emailAddresses.map((email, index) => (
-                      <DetailsCell
+                      <DetailsItem
                         key={`initialPatient-${email}-${index}`}
-                        name={fieldName("emailAddresses") + "." + index}
                         label={"E-Mail-Adresse"}
                         value={email}
                       />
@@ -207,9 +178,8 @@ export function PatientDetails(props: Readonly<PatientDetailsProps>) {
                   {isDefined(props.initialPatient.phoneNumbers) &&
                     props.initialPatient.phoneNumbers.map(
                       (phoneNumber, index) => (
-                        <DetailsCell
+                        <DetailsItem
                           key={`initialPatient-${phoneNumber}-${index}`}
-                          name={fieldName("phoneNumbers") + "." + index}
                           label={"Telefonnummer"}
                           value={phoneNumber}
                         />
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/ProcedureCreatedByTile.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/ProcedureCreatedByTile.tsx
index 1b06ab9414cdc56bd36142d088bc6b7366b85aa7..6e1ef546c67ed56cc0d3b03abbd73b017705853b 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/ProcedureCreatedByTile.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/ProcedureCreatedByTile.tsx
@@ -3,13 +3,12 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import "@eshg/travel-medicine-api";
 import { ApiCreatedByUserType } from "@eshg/travel-medicine-api";
 import { Grid } from "@mui/joy";
 
 import { translateCreatedByUserType } from "@/lib/businessModules/travelMedicine/components/appointmentTypes/translations";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsSection } from "@/lib/shared/components/detailsSection/DetailsSection";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 
 interface ProcedureOriginProps {
   initialValues: ProcedureOriginValues;
@@ -21,22 +20,19 @@ interface ProcedureOriginValues {
 
 export function ProcedureCreatedByTile(props: Readonly<ProcedureOriginProps>) {
   return (
-    <>
-      <DetailsSection
-        data-testid="procedure"
-        title="Vorgangsdaten"
-        canEdit={false}
-      >
-        <Grid xs={12} pl={0} py={0}>
-          <DetailsCell
-            name="createdBy"
-            label={"Vorgang erstellt von:"}
-            value={translateCreatedByUserType(
-              props.initialValues.createdByUserType,
-            )}
-          />
-        </Grid>
-      </DetailsSection>
-    </>
+    <DetailsSection
+      data-testid="procedure"
+      title="Vorgangsdaten"
+      canEdit={false}
+    >
+      <Grid xs={12} pl={0} py={0}>
+        <DetailsItem
+          label={"Vorgang erstellt von:"}
+          value={translateCreatedByUserType(
+            props.initialValues.createdByUserType,
+          )}
+        />
+      </Grid>
+    </DetailsSection>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/TravelDataTile.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/TravelDataTile.tsx
index 4a0b37104a7c64c1cbe23465e1373ddc3086ea6f..4ab936cbb589b3de293eef2b2fe107fef0160e7c 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/TravelDataTile.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/TravelDataTile.tsx
@@ -17,9 +17,9 @@ import {
   TRAVEL_TIME_UNITS,
   TRAVEL_TYPES,
 } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/shared/translations";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsRow } from "@/lib/shared/components/detailsSection/DetailsRow";
 import { DetailsSection } from "@/lib/shared/components/detailsSection/DetailsSection";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 
 interface TravelDataTileProps {
   initialValues: CreateProcedureValues;
@@ -30,74 +30,67 @@ export function TravelDataTile(procedure: Readonly<TravelDataTileProps>) {
   const travelDataSidebar = useTravelDataSidebar();
 
   return (
-    <>
-      <DetailsSection
-        data-testid="travelData"
-        title="Reisedaten"
-        onEdit={() => travelDataSidebar.open(procedure)}
-        canEdit={!procedure.isProcedureClosed}
-      >
-        <Stack direction={{ xxs: "column", md: "row" }} gap={3}>
-          <Stack sx={{ flexGrow: 1, maxWidth: "calc(100%/2)" }} gap={1}>
+    <DetailsSection
+      data-testid="travelData"
+      title="Reisedaten"
+      onEdit={() => travelDataSidebar.open(procedure)}
+      canEdit={!procedure.isProcedureClosed}
+    >
+      <Stack direction={{ xxs: "column", md: "row" }} gap={3}>
+        <Stack sx={{ flexGrow: 1, maxWidth: "calc(100%/2)" }} gap={1}>
+          <DetailsRow>
+            <DetailsItem
+              label="Reiseart"
+              value={
+                procedure.initialValues.travelType &&
+                TRAVEL_TYPES[procedure.initialValues.travelType]
+              }
+            />
+            {procedure.initialValues.travelType !== ApiTravelType.NoTravel && (
+              <DetailsItem
+                label="Reiseziele"
+                value={
+                  isEmpty(procedure.initialValues.travelDestinations)
+                    ? "-"
+                    : procedure.initialValues.travelDestinations
+                        .map((cc) => translateCountry(cc))
+                        .join(", ")
+                }
+              />
+            )}
+          </DetailsRow>
+        </Stack>
+
+        <Stack sx={{ flexGrow: 1, maxWidth: "calc(100%/2)" }} gap={1}>
+          {procedure.initialValues.travelType !== ApiTravelType.NoTravel ? (
             <DetailsRow>
-              <DetailsCell
-                name="travelType"
-                label="Reiseart"
+              <DetailsItem
+                label="Reisebeginn"
                 value={
-                  procedure.initialValues.travelType &&
-                  TRAVEL_TYPES[procedure.initialValues.travelType]
+                  procedure.initialValues.travelStartDate
+                    ? formatDate(
+                        new Date(procedure.initialValues.travelStartDate),
+                      )
+                    : "-"
+                }
+              />
+              <DetailsItem
+                label="Reisedauer"
+                value={
+                  procedure.initialValues.travelTimeAmount
+                    ? procedure.initialValues.travelTimeAmount +
+                      " " +
+                      (procedure.initialValues.travelTimeUnit &&
+                        TRAVEL_TIME_UNITS[
+                          procedure.initialValues.travelTimeUnit
+                        ])
+                    : "-"
                 }
               />
-              {procedure.initialValues.travelType !==
-                ApiTravelType.NoTravel && (
-                <DetailsCell
-                  name="travelDestinations"
-                  label="Reiseziele"
-                  value={
-                    isEmpty(procedure.initialValues.travelDestinations)
-                      ? "-"
-                      : procedure.initialValues.travelDestinations
-                          .map((cc) => translateCountry(cc))
-                          .join(", ")
-                  }
-                />
-              )}
             </DetailsRow>
-          </Stack>
-
-          <Stack sx={{ flexGrow: 1, maxWidth: "calc(100%/2)" }} gap={1}>
-            {procedure.initialValues.travelType !== ApiTravelType.NoTravel ? (
-              <DetailsRow>
-                <DetailsCell
-                  name="travelStartDate"
-                  label="Reisebeginn"
-                  value={
-                    procedure.initialValues.travelStartDate
-                      ? formatDate(
-                          new Date(procedure.initialValues.travelStartDate),
-                        )
-                      : "-"
-                  }
-                />
-                <DetailsCell
-                  name="travelTimeAmount"
-                  label="Reisedauer"
-                  value={
-                    procedure.initialValues.travelTimeAmount
-                      ? procedure.initialValues.travelTimeAmount +
-                        " " +
-                        (procedure.initialValues.travelTimeUnit &&
-                          TRAVEL_TIME_UNITS[
-                            procedure.initialValues.travelTimeUnit
-                          ])
-                      : "-"
-                  }
-                />
-              </DetailsRow>
-            ) : null}
-          </Stack>
+          ) : null}
         </Stack>
-      </DetailsSection>
-    </>
+      </Stack>
+    </DetailsSection>
   );
 }
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/InformationStatementForm.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/InformationStatementForm.tsx
index 030f00f88535b5e7262ffea9a6fd453ab96949c4..c6410d397f9758e260b5ef74f13227f9a388653f 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/InformationStatementForm.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/InformationStatementForm.tsx
@@ -20,7 +20,6 @@ import {
   createDiseaseOptions,
   createInformationStatementTemplateOptions,
 } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/shared/helpers";
-import { SelectionOption } from "@/lib/shared/components/appointmentBlocks/AppointmentStaffSelection";
 import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
 import {
   SidebarForm,
@@ -46,6 +45,11 @@ interface InformationStatementFormProps {
   submitLabel: string;
 }
 
+export interface SelectionOption {
+  label: string;
+  value: string;
+}
+
 export function InformationStatementForm(
   props: Readonly<InformationStatementFormProps>,
 ) {
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/OtherServiceAppliedForm.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/OtherServiceAppliedForm.tsx
index c8a6c212a5c8b4c0eecbf43699d50d7ab000d3ce..07cad58e854b639c2b38d0fb0ecb2a1bdfa93247 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/OtherServiceAppliedForm.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/OtherServiceAppliedForm.tsx
@@ -9,7 +9,7 @@ import { Formik } from "formik";
 import { Ref } from "react";
 
 import { AppliedByFields } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/AppliedByFields";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
 import {
   SidebarForm,
@@ -51,8 +51,7 @@ export function OtherServiceAppliedForm(
             <Stack direction="column" gap={2} data-testid="otherServiceApplied">
               <Sheet>
                 <Stack direction="column" gap={2}>
-                  <DetailsCell
-                    name="serviceTypeDescription"
+                  <DetailsItem
                     label="Leistungsart"
                     value={props.initialValues.serviceTypeDescription}
                   />
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/OtherServicesFields.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/OtherServicesFields.tsx
index 59f5bb194f0cc25aedd5f1759c677f0e9ef87c63..de89d61b95707f3498843c1763d0bdd0e94d4247 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/OtherServicesFields.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/OtherServicesFields.tsx
@@ -12,7 +12,7 @@ import {
   ServicesRequest,
 } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/AddServicePlanForm";
 import { createOtherServicesTemplateOptions } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/shared/helpers";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { LOCALE_OPTION, formatCurrency } from "@/lib/shared/helpers/numbers";
 
 interface OtherServicesFieldsProps {
@@ -82,8 +82,7 @@ export function OtherServicesFields({
           await getFeeForTemplate(index, templateId, setFieldValue);
         }}
       />
-      <DetailsCell
-        name={`services.${index}.fee`}
+      <DetailsItem
         label="Preis"
         value={formatCurrency(val.fee, {
           localOption: LOCALE_OPTION.manual,
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/ServiceAppliedForm.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/ServiceAppliedForm.tsx
index 922f670e7b8db1364272dc1e17e22991f8a9da6f..0d8b819a8d5390111e29bf581e581f6da823c578 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/ServiceAppliedForm.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/ServiceAppliedForm.tsx
@@ -10,7 +10,7 @@ import { Formik } from "formik";
 import { Ref } from "react";
 
 import { AppliedByFields } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/AppliedByFields";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { MultiFormButtonBar } from "@/lib/shared/components/form/MultiFormButtonBar";
 import {
   SidebarForm,
@@ -53,13 +53,11 @@ export function ServiceAppliedForm(props: Readonly<ServiceAppliedFormProps>) {
             <Stack direction="column" gap={2} data-testid="serviceApplied">
               <Sheet>
                 <Stack direction="column" gap={2}>
-                  <DetailsCell
-                    name="vaccinationInfo"
+                  <DetailsItem
                     label="Impfung"
                     value={props.initialValues.vaccinationInfo}
                   />
-                  <DetailsCell
-                    name="vaccineName"
+                  <DetailsItem
                     label="Impfstoff"
                     value={props.initialValues.vaccineName}
                   />
diff --git a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/VaccinationFields.tsx b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/VaccinationFields.tsx
index 01ac3b347f966724d5569c9067b272b81d99f70c..2bc05ae69c26c30513de8ee4dfb9cd9a167198f9 100644
--- a/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/VaccinationFields.tsx
+++ b/employee-portal/src/lib/businessModules/travelMedicine/components/vaccinationConsultations/baseData/sidebars/sidebarForms/VaccinationFields.tsx
@@ -23,7 +23,7 @@ import {
   createVaccinesOptions,
 } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/shared/helpers";
 import { VACCINATION_TYPE } from "@/lib/businessModules/travelMedicine/components/vaccinationConsultations/shared/options";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import { CheckboxField } from "@/lib/shared/components/formFields/CheckboxField";
 import { LOCALE_OPTION, formatCurrency } from "@/lib/shared/helpers/numbers";
 import { validatePositiveInteger } from "@/lib/shared/helpers/validators";
@@ -108,8 +108,7 @@ export function VaccinationFields({
           setOffset(getVaccineOffsets(vaccineId));
         }}
       />
-      <DetailsCell
-        name={`services.${index}.fee`}
+      <DetailsItem
         label="Preis"
         value={formatCurrency(val.fee, {
           localOption: LOCALE_OPTION.manual,
diff --git a/employee-portal/src/lib/opendata/api/clients.ts b/employee-portal/src/lib/opendata/api/clients.ts
index f6016fe7660b0af7a6f1dfdc7cfe8414a7e2e3f0..40407f7ab951eaede140f21871f9cf0ee5f0d11c 100644
--- a/employee-portal/src/lib/opendata/api/clients.ts
+++ b/employee-portal/src/lib/opendata/api/clients.ts
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { Configuration, OpenDataApi } from "@eshg/employee-portal-api/opendata";
 import { useApiConfiguration } from "@eshg/lib-portal/api/ApiProvider";
+import { Configuration, OpenDataApi } from "@eshg/opendata-api";
 
 function useConfiguration() {
   const configurationParameters = useApiConfiguration(
diff --git a/employee-portal/src/lib/opendata/components/EditEntrySidebarContent.tsx b/employee-portal/src/lib/opendata/components/EditEntrySidebarContent.tsx
index 0813bdf4c84c6ce2cea063c78a5329b49a2d482a..a6ba044fc51dc84bab846fd815477774c902a189 100644
--- a/employee-portal/src/lib/opendata/components/EditEntrySidebarContent.tsx
+++ b/employee-portal/src/lib/opendata/components/EditEntrySidebarContent.tsx
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiVersion } from "@eshg/employee-portal-api/opendata";
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { toDateString } from "@eshg/lib-portal/helpers/dateTime";
+import { ApiVersion } from "@eshg/opendata-api";
 import { Button } from "@mui/joy";
 import { Formik } from "formik";
 
diff --git a/employee-portal/src/lib/opendata/components/EntryDetailsSidebar.tsx b/employee-portal/src/lib/opendata/components/EntryDetailsSidebar.tsx
index 864bc2d16962f610ac0ded3788a513ef05cd0186..91328da0556f7c31978a250d52dd06a707a19add 100644
--- a/employee-portal/src/lib/opendata/components/EntryDetailsSidebar.tsx
+++ b/employee-portal/src/lib/opendata/components/EntryDetailsSidebar.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiVersion } from "@eshg/employee-portal-api/opendata";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiVersion } from "@eshg/opendata-api";
 import { Button, Chip, Divider, Stack, Typography } from "@mui/joy";
 import { useState } from "react";
 import { isEmpty } from "remeda";
diff --git a/employee-portal/src/lib/opendata/components/OpenDataTable.tsx b/employee-portal/src/lib/opendata/components/OpenDataTable.tsx
index d930fbf73fe9dd313995da6eb35121d51b11e418..b7bea8b11e7987269b450af8922164252b64d6f8 100644
--- a/employee-portal/src/lib/opendata/components/OpenDataTable.tsx
+++ b/employee-portal/src/lib/opendata/components/OpenDataTable.tsx
@@ -5,11 +5,11 @@
 
 "use client";
 
-import { ApiResource, ApiVersion } from "@eshg/employee-portal-api/opendata";
 import {
   parseOptionalString,
   parseReadonlyPageParams,
 } from "@eshg/lib-portal/helpers/searchParams";
+import { ApiResource, ApiVersion } from "@eshg/opendata-api";
 import Add from "@mui/icons-material/Add";
 import { Button, Stack } from "@mui/joy";
 import { useSearchParams } from "next/navigation";
diff --git a/employee-portal/src/lib/opendata/components/VersionFileCard.tsx b/employee-portal/src/lib/opendata/components/VersionFileCard.tsx
index fc866e1744d5f950886c67d969cd539279ee2528..5649db33ba89c6daf04fe8d8122c3e46a631e778 100644
--- a/employee-portal/src/lib/opendata/components/VersionFileCard.tsx
+++ b/employee-portal/src/lib/opendata/components/VersionFileCard.tsx
@@ -5,8 +5,8 @@
 
 "use client";
 
-import { ApiVersion } from "@eshg/employee-portal-api/opendata";
 import { useFileDownload } from "@eshg/lib-portal/api/files/download";
+import { ApiVersion } from "@eshg/opendata-api";
 import FileDownloadOutlined from "@mui/icons-material/FileDownloadOutlined";
 
 import { useOpenDataApi } from "@/lib/opendata/api/clients";
diff --git a/employee-portal/src/lib/opendata/components/openDataColumns.tsx b/employee-portal/src/lib/opendata/components/openDataColumns.tsx
index bd42b94ad466ee96ab4a05cddcaf9265d5f593d1..2bd48e4dc24e6cde6e5b3da177f6b45a687b0fea 100644
--- a/employee-portal/src/lib/opendata/components/openDataColumns.tsx
+++ b/employee-portal/src/lib/opendata/components/openDataColumns.tsx
@@ -5,8 +5,8 @@
 
 "use client";
 
-import { ApiResource, ApiVersion } from "@eshg/employee-portal-api/opendata";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiResource, ApiVersion } from "@eshg/opendata-api";
 import Add from "@mui/icons-material/Add";
 import DeleteOutlined from "@mui/icons-material/DeleteOutlined";
 import { IconButton, Stack } from "@mui/joy";
diff --git a/employee-portal/src/lib/opendata/helper.ts b/employee-portal/src/lib/opendata/helper.ts
index 294610363a090a51c686ebe11828e4dddccc2323..df4fa4dc4bd816f195399cad483f043a7b378d41 100644
--- a/employee-portal/src/lib/opendata/helper.ts
+++ b/employee-portal/src/lib/opendata/helper.ts
@@ -3,11 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiBusinessModule,
-  ApiVersion,
-} from "@eshg/employee-portal-api/opendata";
 import { ConfirmationDialogOptions } from "@eshg/lib-portal/components/confirmationDialog/ConfirmationDialogProvider";
+import { ApiBusinessModule, ApiVersion } from "@eshg/opendata-api";
 
 import { buildOptionsFromBusinessModules } from "@/lib/shared/components/procedures/helper";
 
diff --git a/employee-portal/src/lib/opendata/hooks/useOpenDataFilterSettings.ts b/employee-portal/src/lib/opendata/hooks/useOpenDataFilterSettings.ts
index f00307821c0d50e245f0f10eaf13943343f1019f..6ae51e529783e8e28e187fcc36ee498fa33be3cf 100644
--- a/employee-portal/src/lib/opendata/hooks/useOpenDataFilterSettings.ts
+++ b/employee-portal/src/lib/opendata/hooks/useOpenDataFilterSettings.ts
@@ -7,7 +7,7 @@ import { ApiBusinessModule } from "@eshg/base-api";
 import {
   ApiOpenDataFileType,
   GetOpenDocumentsRequest,
-} from "@eshg/employee-portal-api/opendata";
+} from "@eshg/opendata-api";
 
 import { openDataFileTypes } from "@/lib/opendata/constants";
 import { buildOpenDataBusinessModuleOptions } from "@/lib/opendata/helper";
diff --git a/employee-portal/src/lib/opendata/mutations/opendata.ts b/employee-portal/src/lib/opendata/mutations/opendata.ts
index 7bb020e29d2efc1dc3da6d9f799d3ef196561676..e6c2f67f4f33d6b8cf42d7f5f4eeca4839f31b0b 100644
--- a/employee-portal/src/lib/opendata/mutations/opendata.ts
+++ b/employee-portal/src/lib/opendata/mutations/opendata.ts
@@ -3,12 +3,12 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiUpdateVersionMetaDataRequest,
   CreateOpenDocumentRequest,
-} from "@eshg/employee-portal-api/opendata";
-import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+} from "@eshg/opendata-api";
 
 import { useOpenDataApi } from "@/lib/opendata/api/clients";
 
diff --git a/employee-portal/src/lib/opendata/queries/opendata.ts b/employee-portal/src/lib/opendata/queries/opendata.ts
index 067da64454c49f2f64a3559e0b91650d3ddfb74b..4dcd3cc62c6809224b14094ae0746fc4f6f44766 100644
--- a/employee-portal/src/lib/opendata/queries/opendata.ts
+++ b/employee-portal/src/lib/opendata/queries/opendata.ts
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { GetOpenDocumentsRequest } from "@eshg/employee-portal-api/opendata";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+import { GetOpenDocumentsRequest } from "@eshg/opendata-api";
 import { useSuspenseQuery } from "@tanstack/react-query";
 
 import { useOpenDataApi } from "@/lib/opendata/api/clients";
diff --git a/employee-portal/src/lib/shared/api/clients.ts b/employee-portal/src/lib/shared/api/clients.ts
index dd61115a62cf6c720196298d0938d1c83cbb3158..ec34d5668dafe4f3b39464d3e1114073600a0720 100644
--- a/employee-portal/src/lib/shared/api/clients.ts
+++ b/employee-portal/src/lib/shared/api/clients.ts
@@ -4,19 +4,19 @@
  */
 
 import { ConfigurationParameters } from "@eshg/base-api";
+import {
+  ApiConfiguration,
+  useApiConfiguration,
+} from "@eshg/lib-portal/api/ApiProvider";
 import {
   ApiBusinessModule,
-  Configuration as BusinessProceduresConfiguration,
   GdprValidationTaskApi,
-} from "@eshg/employee-portal-api/businessProcedures";
+  Configuration as LibProceduresConfiguration,
+} from "@eshg/lib-procedures-api";
 import {
   Configuration as LibStatisticsConfiguration,
   StatisticsProcedureReferenceApi,
-} from "@eshg/employee-portal-api/libStatistics";
-import {
-  ApiConfiguration,
-  useApiConfiguration,
-} from "@eshg/lib-portal/api/ApiProvider";
+} from "@eshg/lib-statistics-api";
 
 type ConfigurationConstructor<TConfiguration> = new (
   params: ConfigurationParameters,
@@ -49,7 +49,7 @@ export function useConfigurationByBusinessModule<TConfiguration>(
 export function useGdprValidationTaskApi(businessModule: ApiBusinessModule) {
   const configuration = useConfigurationByBusinessModule(
     businessModule,
-    BusinessProceduresConfiguration,
+    LibProceduresConfiguration,
   );
   return new GdprValidationTaskApi(configuration);
 }
diff --git a/employee-portal/src/lib/shared/api/mutations/archiving.ts b/employee-portal/src/lib/shared/api/mutations/archiving.ts
index d98ecc54719d0b4dca1c3684f3767904d27940ec..d7ccc2cdf3e79404a876bc926efa19664a53f8f6 100644
--- a/employee-portal/src/lib/shared/api/mutations/archiving.ts
+++ b/employee-portal/src/lib/shared/api/mutations/archiving.ts
@@ -3,12 +3,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import {
-  ApiArchivingRelevance,
-  ArchivingApi,
-} from "@eshg/employee-portal-api/businessProcedures";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { ApiArchivingRelevance, ArchivingApi } from "@eshg/lib-procedures-api";
 
 import { join } from "@/lib/shared/helpers/strings";
 
diff --git a/employee-portal/src/lib/shared/api/mutations/gdpr.ts b/employee-portal/src/lib/shared/api/mutations/gdpr.ts
index 7d54003818a542d88e7aa2bd4137b5f75b69a299..bbe96928bc1d47fd5fe46b13a6c1da63bac1394a 100644
--- a/employee-portal/src/lib/shared/api/mutations/gdpr.ts
+++ b/employee-portal/src/lib/shared/api/mutations/gdpr.ts
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { GdprValidationTaskApiInterface } from "@eshg/employee-portal-api/businessProcedures";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { GdprValidationTaskApiInterface } from "@eshg/lib-procedures-api";
 
 export function useAddDownloadPackage(taskApi: GdprValidationTaskApiInterface) {
   const snackbar = useSnackbar();
diff --git a/employee-portal/src/lib/shared/api/mutations/inboxProcedures.ts b/employee-portal/src/lib/shared/api/mutations/inboxProcedures.ts
index 6ba57645a2eda39efd796252e57e8c32a9653395..0586c41d85a1c4bb562e144012bb638f70574e43 100644
--- a/employee-portal/src/lib/shared/api/mutations/inboxProcedures.ts
+++ b/employee-portal/src/lib/shared/api/mutations/inboxProcedures.ts
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import {
   ApiCreateInboxProcedureRequest,
   ApiInboxProcedure,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+} from "@eshg/lib-procedures-api";
 
 export function useCreateInboxProcedureTemplate(
   useInboxProcedureApi: () => {
diff --git a/employee-portal/src/lib/shared/api/mutations/libEditor.ts b/employee-portal/src/lib/shared/api/mutations/libEditor.ts
index e66e7248e968c400db5063f6aa88511c36149f5b..9b854fb496403d6a91834ce7f6ea7fda9db0eebb 100644
--- a/employee-portal/src/lib/shared/api/mutations/libEditor.ts
+++ b/employee-portal/src/lib/shared/api/mutations/libEditor.ts
@@ -8,7 +8,7 @@ import {
   EditorApiInterface,
   InsertEditorElementRequest,
   UpdateEditorElementRequest,
-} from "@eshg/employee-portal-api/libEditor";
+} from "@eshg/lib-editor-api";
 import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 
diff --git a/employee-portal/src/lib/shared/api/queries/archiving.ts b/employee-portal/src/lib/shared/api/queries/archiving.ts
index 0239e7ffd13d442c2782664b718e07b3a3636699..d0d8b3591593d9feb9e2ebd30baf0be5aea9f9d4 100644
--- a/employee-portal/src/lib/shared/api/queries/archiving.ts
+++ b/employee-portal/src/lib/shared/api/queries/archiving.ts
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { type QueryKeyFactory } from "@eshg/lib-portal/api/queryKeyFactory";
+import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import {
   ArchivingApi,
   GetArchivableProceduresRequest,
   GetRelevantArchivableProceduresRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { type QueryKeyFactory } from "@eshg/lib-portal/api/queryKeyFactory";
-import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+} from "@eshg/lib-procedures-api";
 import { useSuspenseQuery } from "@tanstack/react-query";
 
 import { mapArchivableProceduresResponse } from "@/lib/shared/components/archiving/api/models/archivableProcedure";
diff --git a/employee-portal/src/lib/shared/api/queries/gdpr.ts b/employee-portal/src/lib/shared/api/queries/gdpr.ts
index 683a6cae9314b50e042ff7368834ca4c7e15393b..d31f9322e1e768dddd46176ab230df1c4ba41028 100644
--- a/employee-portal/src/lib/shared/api/queries/gdpr.ts
+++ b/employee-portal/src/lib/shared/api/queries/gdpr.ts
@@ -4,6 +4,9 @@
  */
 
 import { ApiBaseFeature } from "@eshg/base-api";
+import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+import { PortalErrorCode } from "@eshg/lib-portal/errorHandling/PortalErrorCode";
+import { resolveError } from "@eshg/lib-portal/errorHandling/errorResolvers";
 import {
   ApiBusinessModule,
   ApiGdprDownloadPackageInfo,
@@ -11,10 +14,7 @@ import {
   ApiGetGdprNotificationBannerResponse,
   GdprValidationTaskApiInterface,
   GetAllGdprValidationTasksRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
-import { PortalErrorCode } from "@eshg/lib-portal/errorHandling/PortalErrorCode";
-import { resolveError } from "@eshg/lib-portal/errorHandling/errorResolvers";
+} from "@eshg/lib-procedures-api";
 import { queryOptions, useSuspenseQueries } from "@tanstack/react-query";
 import assert from "assert";
 import { isDefined } from "remeda";
diff --git a/employee-portal/src/lib/shared/api/queries/inboxProcedures.ts b/employee-portal/src/lib/shared/api/queries/inboxProcedures.ts
index b1f099f6beb28b35e17a379b9a91a488b2eff414..89c049fbaf7984ed8604bfe9b5edfa4534b6350a 100644
--- a/employee-portal/src/lib/shared/api/queries/inboxProcedures.ts
+++ b/employee-portal/src/lib/shared/api/queries/inboxProcedures.ts
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { InboxProcedureApi } from "@eshg/employee-portal-api/businessProcedures";
 import { type QueryKeyFactory } from "@eshg/lib-portal/api/queryKeyFactory";
+import { InboxProcedureApi } from "@eshg/lib-procedures-api";
 import { useSuspenseQuery } from "@tanstack/react-query";
 import { useSearchParams } from "next/navigation";
 
diff --git a/employee-portal/src/lib/shared/api/queries/statisticsProcedureReference.ts b/employee-portal/src/lib/shared/api/queries/statisticsProcedureReference.ts
index 0eb067bf874abd702c57bba70b101747e613986e..70c583402990f58d93a50a60c0af285777c0a959 100644
--- a/employee-portal/src/lib/shared/api/queries/statisticsProcedureReference.ts
+++ b/employee-portal/src/lib/shared/api/queries/statisticsProcedureReference.ts
@@ -3,11 +3,11 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 import {
   ApiGetProcedureIdsRequest,
   StatisticsProcedureReferenceApiInterface,
-} from "@eshg/employee-portal-api/libStatistics";
+} from "@eshg/lib-statistics-api";
 import { queryOptions } from "@tanstack/react-query";
 
 import { gdprValidationTaskApiQueryKey } from "@/lib/baseModule/api/queries/apiQueryKey";
diff --git a/employee-portal/src/lib/shared/api/queries/tasks.ts b/employee-portal/src/lib/shared/api/queries/tasks.ts
index 9cd9d24aaa7934801fd6aff7f2153f4f9dd97c5e..f7118711a339892c6202480819977ccbc6420be9 100644
--- a/employee-portal/src/lib/shared/api/queries/tasks.ts
+++ b/employee-portal/src/lib/shared/api/queries/tasks.ts
@@ -3,12 +3,12 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
 import {
   ApiGetTaskByUserResponse,
   ApiResponse,
   GetTasksByAssigneeRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { unwrapRawResponse } from "@eshg/lib-portal/api/unwrapRawResponse";
+} from "@eshg/lib-procedures-api";
 import { queryOptions } from "@tanstack/react-query";
 import { useSearchParams } from "next/navigation";
 
diff --git a/employee-portal/src/lib/shared/components/FileCard.tsx b/employee-portal/src/lib/shared/components/FileCard.tsx
index 52481f0b82a49412e1bf4621762628a2ee0085cb..e02438dd23ca8cc87c7c4458231009162b5bf721 100644
--- a/employee-portal/src/lib/shared/components/FileCard.tsx
+++ b/employee-portal/src/lib/shared/components/FileCard.tsx
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiFileType } from "@eshg/employee-portal-api/businessProcedures";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { formatFileSize } from "@eshg/lib-portal/helpers/file";
+import { ApiFileType } from "@eshg/lib-procedures-api";
 import AlternateEmailOutlinedIcon from "@mui/icons-material/AlternateEmailOutlined";
 import AudioFileOutlinedIcon from "@mui/icons-material/AudioFileOutlined";
 import ImageOutlinedIcon from "@mui/icons-material/ImageOutlined";
diff --git a/employee-portal/src/lib/shared/components/address/BaseAddressDetails.tsx b/employee-portal/src/lib/shared/components/address/BaseAddressDetails.tsx
index 9e4a3ae4c5c1dc249ca535c663d1cc57a3366f45..ebaaa1cc2be19d622cd5658a2e46578e156a2deb 100644
--- a/employee-portal/src/lib/shared/components/address/BaseAddressDetails.tsx
+++ b/employee-portal/src/lib/shared/components/address/BaseAddressDetails.tsx
@@ -7,9 +7,9 @@ import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
 import { SxProps } from "@mui/joy/styles/types/theme";
 import { isNonNullish } from "remeda";
 
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsColumn } from "@/lib/shared/components/detailsSection/DetailsColumn";
 import { DetailsRow } from "@/lib/shared/components/detailsSection/DetailsRow";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
 import {
   BaseAddress,
   isDomesticAddress,
@@ -25,53 +25,30 @@ export function BaseAddressDetails({ address, sx }: BaseAddressDetailsProps) {
   return (
     <DetailsColumn sx={sx}>
       {isNonNullish(address.differentName) && (
-        <DetailsCell
-          label={"Abweichender Empfänger"}
+        <DetailsItem
+          label="Abweichender Empfänger"
           value={address.differentName}
-          name={"differentName"}
         />
       )}
       {isPostboxAddress(address) && (
-        <DetailsCell
-          label={"Postfachnummer"}
-          value={address.postbox}
-          name={"postbox"}
-        />
+        <DetailsItem label="Postfachnummer" value={address.postbox} />
       )}
       {isDomesticAddress(address) && (
         <>
-          <DetailsCell
-            label={"Straße und Haus Nr."}
+          <DetailsItem
+            label="Straße und Haus Nr."
             value={[address.street, address.houseNumber].join(" ").trim()}
-            name={"streetAndHousenumber"}
           />
           {isNonNullish(address.addressAddition) && (
-            <DetailsCell
-              label={"Adresszusatz"}
-              value={address.addressAddition}
-              name={"addressAddition"}
-            />
+            <DetailsItem label="Adresszusatz" value={address.addressAddition} />
           )}
         </>
       )}
       <DetailsRow>
-        <DetailsCell
-          label={"Postleitzahl"}
-          value={address.postalCode}
-          name={"postalCode"}
-        />
-        <DetailsCell
-          label={"Ort"}
-          value={address.city}
-          name={"city"}
-          avoidWrap
-        />
+        <DetailsItem label="Postleitzahl" value={address.postalCode} />
+        <DetailsItem label="Ort" value={address.city} avoidWrap />
       </DetailsRow>
-      <DetailsCell
-        label={"Land"}
-        value={translateCountry(address.country)}
-        name={"country"}
-      />
+      <DetailsItem label="Land" value={translateCountry(address.country)} />
     </DetailsColumn>
   );
 }
diff --git a/employee-portal/src/lib/shared/components/appointmentBlocks/AppointmentStaffField.tsx b/employee-portal/src/lib/shared/components/appointmentBlocks/AppointmentStaffField.tsx
index e2bf5c00458e8a19614cf327973dac404055f76a..76f20899d8a9d0fe7e8b6ab3b264ecf9ec133443 100644
--- a/employee-portal/src/lib/shared/components/appointmentBlocks/AppointmentStaffField.tsx
+++ b/employee-portal/src/lib/shared/components/appointmentBlocks/AppointmentStaffField.tsx
@@ -7,30 +7,20 @@ import {
   BaseField,
   useBaseField,
 } from "@eshg/lib-portal/components/formFields/BaseField";
-import { SelectOption } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import { FieldProps } from "@eshg/lib-portal/types/form";
 import Close from "@mui/icons-material/Close";
-import {
-  Autocomplete,
-  AutocompleteProps,
-  Chip,
-  ChipProps,
-  Tooltip,
-} from "@mui/joy";
-import { isString } from "remeda";
+import { Autocomplete, Chip, ChipProps, Tooltip } from "@mui/joy";
 
-import { SelectionOption } from "@/lib/shared/components/appointmentBlocks/AppointmentStaffSelection";
+import { fullName } from "@/lib/shared/components/users/userFormatter";
 
-type JoyUiSelectValue = AutocompleteProps<
-  SelectionOption,
-  true,
-  boolean,
-  true
->["value"];
-type SelectFieldValue = NonNullable<JoyUiSelectValue>;
+export interface StaffUser {
+  userId: string;
+  firstName: string;
+  lastName: string;
+}
 
-interface AppointmentStaffFieldProps extends FieldProps<SelectFieldValue> {
-  options: SelectionOption[];
+interface AppointmentStaffFieldProps extends FieldProps<string[]> {
+  options: StaffUser[];
   placeholder?: string;
   blockedStaff: string[];
   freeStaff: string[];
@@ -41,21 +31,20 @@ export function AppointmentStaffField(
 ) {
   const field = useBaseField(props);
 
-  function setValue(newValue: (string | SelectOption)[]) {
-    const labelNames = newValue.map((v) => (isString(v) ? v : v.value));
-    void field.helpers.setValue(labelNames);
+  function setValue(newUserIds: string[]) {
+    void field.helpers.setValue(newUserIds);
   }
 
-  function getAvailability(item: SelectionOption): {
+  function getAvailability(item: StaffUser): {
     title: string;
     color: ChipProps["color"];
   } {
-    if (props.freeStaff.includes(item.value)) {
+    if (props.freeStaff.includes(item.userId)) {
       return {
         title: "Es gibt keine Konflikte.",
         color: "success",
       };
-    } else if (props.blockedStaff.includes(item.value)) {
+    } else if (props.blockedStaff.includes(item.userId)) {
       return {
         title: "Es gibt mindestens einen Terminkonflikt.",
         color: "danger",
@@ -77,28 +66,37 @@ export function AppointmentStaffField(
     >
       <Autocomplete
         multiple
-        freeSolo
+        autoHighlight
         clearOnBlur
         selectOnFocus
         filterSelectedOptions
         name={props.name}
+        value={props.options.filter((option) =>
+          field.input.value.includes(option.userId),
+        )}
         disableClearable={field.required}
         onChange={(_, newValue) => {
-          setValue(newValue);
+          setValue(newValue.map((user) => user.userId));
         }}
         filterOptions={(options, params) => {
           const { inputValue } = params;
-          return options.filter(
-            (opt) =>
-              opt.label.toLowerCase().includes(inputValue.toLowerCase()) &&
-              !field.input.value.includes(opt.label),
-          );
+          return options.filter((opt) => {
+            const optionName = fullName(opt);
+            const selectedUserIds = field.input.value;
+            const matchesOption = optionName
+              .toLowerCase()
+              .includes(inputValue.toLowerCase());
+            const matchesSelectedUser = selectedUserIds.some(
+              (userId) => opt.userId === userId,
+            );
+            return matchesOption && !matchesSelectedUser;
+          });
         }}
         onBlur={field.input.onBlur}
         placeholder={props.placeholder}
         options={props.options}
-        getOptionLabel={(value) => (isString(value) ? value : value.label)}
-        getOptionKey={(value) => (isString(value) ? value : value.value)}
+        getOptionLabel={(value) => fullName(value)}
+        getOptionKey={(value) => value.userId}
         renderTags={(options, getTagProps) =>
           options.map((item, index) => (
             <Tooltip title={getAvailability(item).title} key={index}>
@@ -109,9 +107,9 @@ export function AppointmentStaffField(
                 endDecorator={<Close fontSize="sm" />}
                 sx={{ minWidth: 0 }}
                 {...getTagProps({ index })}
-                key={item.value}
+                key={item.userId}
               >
-                {item.label}
+                {fullName(item)}
               </Chip>
             </Tooltip>
           ))
diff --git a/employee-portal/src/lib/shared/components/appointmentBlocks/AppointmentStaffSelection.tsx b/employee-portal/src/lib/shared/components/appointmentBlocks/AppointmentStaffSelection.tsx
index 93e7781a5f758be61d981fbee7cf1421e97f7df6..8cf97e565c7d3f0e7e6f0f58a24a08bf5c3991bf 100644
--- a/employee-portal/src/lib/shared/components/appointmentBlocks/AppointmentStaffSelection.tsx
+++ b/employee-portal/src/lib/shared/components/appointmentBlocks/AppointmentStaffSelection.tsx
@@ -6,7 +6,10 @@
 import { Button, Grid } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 
-import { AppointmentStaffField } from "@/lib/shared/components/appointmentBlocks/AppointmentStaffField";
+import {
+  AppointmentStaffField,
+  StaffUser,
+} from "@/lib/shared/components/appointmentBlocks/AppointmentStaffField";
 import { FormGroupGrid } from "@/lib/shared/components/form/FormGroupGrid";
 
 export const BUTTON_STYLES: SxProps = {
@@ -14,19 +17,14 @@ export const BUTTON_STYLES: SxProps = {
 };
 
 export interface AppointmentStaffSelectionProps {
-  physicianOptions: SelectionOption[];
-  medicalAssistantOptions?: SelectionOption[];
-  consultantOptions?: SelectionOption[];
+  physicianOptions: StaffUser[];
+  medicalAssistantOptions?: StaffUser[];
+  consultantOptions?: StaffUser[];
   blockedStaff: string[];
   freeStaff: string[];
   validateAvailability: () => void;
 }
 
-export interface SelectionOption {
-  label: string;
-  value: string;
-}
-
 export function AppointmentStaffSelection(
   props: Readonly<AppointmentStaffSelectionProps>,
 ) {
diff --git a/employee-portal/src/lib/shared/components/archiving/ArchiveView.tsx b/employee-portal/src/lib/shared/components/archiving/ArchiveView.tsx
index c26c1743308fb0a3833d363a53f9fc04fe0a75c8..840527f944e7f5315c927f932740bcedbc702c86 100644
--- a/employee-portal/src/lib/shared/components/archiving/ArchiveView.tsx
+++ b/employee-portal/src/lib/shared/components/archiving/ArchiveView.tsx
@@ -4,7 +4,7 @@
  */
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiProcedureType } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiProcedureType } from "@eshg/lib-procedures-api";
 
 import { UseBulkUpdateProceduresArchivingRelevance } from "@/lib/shared/api/mutations/archiving";
 import {
diff --git a/employee-portal/src/lib/shared/components/archiving/api/models/archivableProcedure.ts b/employee-portal/src/lib/shared/components/archiving/api/models/archivableProcedure.ts
index ca13ff425bb5879057cbe4b2000b9667026220a2..ee148efd40150de78d6a23f61cbfb0d7b6a8970c 100644
--- a/employee-portal/src/lib/shared/components/archiving/api/models/archivableProcedure.ts
+++ b/employee-portal/src/lib/shared/components/archiving/api/models/archivableProcedure.ts
@@ -6,7 +6,7 @@
 import {
   ApiGetArchivableProceduresResponse,
   ApiProcedure,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 
 export type ArchivableProcedure = ApiProcedure & { id: string };
 
diff --git a/employee-portal/src/lib/shared/components/archiving/components/ArchivingRelevanceChip.tsx b/employee-portal/src/lib/shared/components/archiving/components/ArchivingRelevanceChip.tsx
index 5be48068e793433228a7e1d901c0e7529b71a143..7b6476aace9d3e770a79e003d1ef2a143e2a3707 100644
--- a/employee-portal/src/lib/shared/components/archiving/components/ArchivingRelevanceChip.tsx
+++ b/employee-portal/src/lib/shared/components/archiving/components/ArchivingRelevanceChip.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiArchivingRelevance } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiArchivingRelevance } from "@eshg/lib-procedures-api";
 import Chip, { ChipProps } from "@mui/joy/Chip";
 
 import { archivingRelevanceNames } from "@/lib/shared/components/archiving/constants";
diff --git a/employee-portal/src/lib/shared/components/archiving/components/archiveAdminView/ArchiveAdminTable.tsx b/employee-portal/src/lib/shared/components/archiving/components/archiveAdminView/ArchiveAdminTable.tsx
index efcfa8cf468cf42d05481179eb54b44f37a2a8a6..f84944810b771e57d08d8dac7bcdbd520ec668d7 100644
--- a/employee-portal/src/lib/shared/components/archiving/components/archiveAdminView/ArchiveAdminTable.tsx
+++ b/employee-portal/src/lib/shared/components/archiving/components/archiveAdminView/ArchiveAdminTable.tsx
@@ -3,12 +3,12 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { useFileDownload } from "@eshg/lib-portal/api/files/download";
+import { formatFileSize } from "@eshg/lib-portal/helpers/file";
 import {
   ApiArchivingRelevance,
   ApiGetRelevantArchivableProceduresSortBy,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { useFileDownload } from "@eshg/lib-portal/api/files/download";
-import { formatFileSize } from "@eshg/lib-portal/helpers/file";
+} from "@eshg/lib-procedures-api";
 import { DeleteOutlined, DownloadOutlined } from "@mui/icons-material";
 import { Button } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/shared/components/archiving/components/archiveAdminView/archiveAdminTableColumns.tsx b/employee-portal/src/lib/shared/components/archiving/components/archiveAdminView/archiveAdminTableColumns.tsx
index 6f9839b4d8be1429a0ad522790bd069ecdefdff6..58956ece21e788c4f183df0ca54c9080f691ccba 100644
--- a/employee-portal/src/lib/shared/components/archiving/components/archiveAdminView/archiveAdminTableColumns.tsx
+++ b/employee-portal/src/lib/shared/components/archiving/components/archiveAdminView/archiveAdminTableColumns.tsx
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import {
-  ApiGetRelevantArchivableProceduresSortBy,
-  ApiProcedure,
-} from "@eshg/employee-portal-api/businessProcedures";
 import {
   formatDate,
   formatDateTime,
 } from "@eshg/lib-portal/formatters/dateTime";
+import {
+  ApiGetRelevantArchivableProceduresSortBy,
+  ApiProcedure,
+} from "@eshg/lib-procedures-api";
 import { createColumnHelper } from "@tanstack/react-table";
 
 const columnHelper = createColumnHelper<ApiProcedure>();
diff --git a/employee-portal/src/lib/shared/components/archiving/components/archiveView/ArchiveTable.tsx b/employee-portal/src/lib/shared/components/archiving/components/archiveView/ArchiveTable.tsx
index 43cd2ce7420ebfa0248f7e95e78c4fc4e075624d..aab0b9c5bcf1e854fdf24e9a516f80c911337a3d 100644
--- a/employee-portal/src/lib/shared/components/archiving/components/archiveView/ArchiveTable.tsx
+++ b/employee-portal/src/lib/shared/components/archiving/components/archiveView/ArchiveTable.tsx
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiGetArchivableProceduresSortBy } from "@eshg/employee-portal-api/businessProcedures";
 import { Alert } from "@eshg/lib-portal/components/Alert";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiGetArchivableProceduresSortBy } from "@eshg/lib-procedures-api";
 import { endOfMonth, isAfter, startOfYear } from "date-fns";
 
 import { ArchiveViewProps } from "@/lib/shared/components/archiving/ArchiveView";
diff --git a/employee-portal/src/lib/shared/components/archiving/components/archiveView/ArchiveTableTitle.tsx b/employee-portal/src/lib/shared/components/archiving/components/archiveView/ArchiveTableTitle.tsx
index 549372abfb5e3aa30f49f2cf34ebbaed0136cc36..31e9fa5f70da9124d092f9354068b5ae687abc6e 100644
--- a/employee-portal/src/lib/shared/components/archiving/components/archiveView/ArchiveTableTitle.tsx
+++ b/employee-portal/src/lib/shared/components/archiving/components/archiveView/ArchiveTableTitle.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiArchivingRelevance } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiArchivingRelevance } from "@eshg/lib-procedures-api";
 import { DeleteOutlined, Inventory2Outlined } from "@mui/icons-material";
 import { Divider, Typography } from "@mui/joy";
 import { RowSelectionState } from "@tanstack/react-table";
diff --git a/employee-portal/src/lib/shared/components/archiving/components/archiveView/archiveTableColumns.tsx b/employee-portal/src/lib/shared/components/archiving/components/archiveView/archiveTableColumns.tsx
index 7eed4580dc8a1d7825357a8b5de71528f92fcd3e..a8755767f70aa4cdca657eb375e39bb06735c3ca 100644
--- a/employee-portal/src/lib/shared/components/archiving/components/archiveView/archiveTableColumns.tsx
+++ b/employee-portal/src/lib/shared/components/archiving/components/archiveView/archiveTableColumns.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiGetArchivableProceduresSortBy } from "@eshg/employee-portal-api/businessProcedures";
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiGetArchivableProceduresSortBy } from "@eshg/lib-procedures-api";
 import { createColumnHelper } from "@tanstack/react-table";
 
 import { ArchivableProcedure } from "@/lib/shared/components/archiving/api/models/archivableProcedure";
diff --git a/employee-portal/src/lib/shared/components/archiving/hooks/useArchiveAdminFilterSettings.ts b/employee-portal/src/lib/shared/components/archiving/hooks/useArchiveAdminFilterSettings.ts
index 8a12b9b3bcdc85e345f2c5b22d836d04a5aa5d35..9e659ae528ee4eaca3a1912ccf1121d6b7d2302f 100644
--- a/employee-portal/src/lib/shared/components/archiving/hooks/useArchiveAdminFilterSettings.ts
+++ b/employee-portal/src/lib/shared/components/archiving/hooks/useArchiveAdminFilterSettings.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { GetRelevantArchivableProceduresRequest } from "@eshg/employee-portal-api/businessProcedures";
+import { GetRelevantArchivableProceduresRequest } from "@eshg/lib-procedures-api";
 
 import { FilterDefinition } from "@/lib/shared/components/filterSettings/models/FilterDefinition";
 import { FilterValue } from "@/lib/shared/components/filterSettings/models/FilterValue";
diff --git a/employee-portal/src/lib/shared/components/archiving/hooks/useArchiveFilterSettings.ts b/employee-portal/src/lib/shared/components/archiving/hooks/useArchiveFilterSettings.ts
index d7c40058543384317f3b2116b0bbbe8bc1cd3e5e..c4fb1b781015f794d6d19351afe7e245b25bb3da 100644
--- a/employee-portal/src/lib/shared/components/archiving/hooks/useArchiveFilterSettings.ts
+++ b/employee-portal/src/lib/shared/components/archiving/hooks/useArchiveFilterSettings.ts
@@ -8,7 +8,7 @@ import {
   ApiGetArchivingConfigurationResponse,
   ApiProcedureType,
   GetArchivableProceduresRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 
 import { archivingRelevanceNames } from "@/lib/shared/components/archiving/constants";
 import { FilterDefinition } from "@/lib/shared/components/filterSettings/models/FilterDefinition";
diff --git a/employee-portal/src/lib/shared/components/auditlog/constants.ts b/employee-portal/src/lib/shared/components/auditlog/constants.ts
index 865cf3200a0b8c34560f763db2aacd7a1be0f2fb..b48ecc84f0b83fec7e75a4290b9539bdcfd42e3b 100644
--- a/employee-portal/src/lib/shared/components/auditlog/constants.ts
+++ b/employee-portal/src/lib/shared/components/auditlog/constants.ts
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { ApiAuditLogSource } from "@eshg/auditlog-api";
 import { ApiBusinessModule } from "@eshg/base-api";
-import { ApiAuditLogSource } from "@eshg/employee-portal-api/auditlog/models";
 
 import { businessModuleNames } from "@/lib/shared/components/procedures/constants";
 
diff --git a/employee-portal/src/lib/shared/components/centralFile/display/CentralFileFacilityDetails.tsx b/employee-portal/src/lib/shared/components/centralFile/display/CentralFileFacilityDetails.tsx
index 66af588a8f7e6c9c5aa4a016dfedc17fa8b21d0f..484fc0019ec08f36d3055b551e09928d79bcfab6 100644
--- a/employee-portal/src/lib/shared/components/centralFile/display/CentralFileFacilityDetails.tsx
+++ b/employee-portal/src/lib/shared/components/centralFile/display/CentralFileFacilityDetails.tsx
@@ -3,16 +3,15 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import { Stack } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 import { ReactNode } from "react";
 
 import { ResponsiveDivider } from "@/lib/shared/components/ResponsiveDivider";
 import { BaseAddressDetails } from "@/lib/shared/components/address/BaseAddressDetails";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsColumn } from "@/lib/shared/components/detailsSection/DetailsColumn";
-import { ExternalLinkDetailsCell } from "@/lib/shared/components/detailsSection/ExternalLinkDetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
+import { ExternalLinkDetailsItem } from "@/lib/shared/components/detailsSection/items/ExternalLinkDetailsItem";
 import { BaseAddress } from "@/lib/shared/helpers/address";
 
 export interface CentralFileFacility {
@@ -22,8 +21,6 @@ export interface CentralFileFacility {
   readonly phoneNumbers?: string[];
 }
 
-const fieldName = createFieldNameMapper<CentralFileFacility>();
-
 export interface CentralFileFacilityDetailsProps<T> {
   readonly facility: T;
   readonly columnSx?: SxProps;
@@ -46,11 +43,7 @@ export function CentralFileFacilityDetails<T extends CentralFileFacility>(
       width="100%"
     >
       <DetailsColumn sx={props.columnSx}>
-        <DetailsCell
-          name={fieldName("name")}
-          label={"Name"}
-          value={facility.name}
-        />
+        <DetailsItem label="Name" value={facility.name} />
         {props.children}
       </DetailsColumn>
       {facility.contactAddress && (
@@ -62,19 +55,17 @@ export function CentralFileFacilityDetails<T extends CentralFileFacility>(
       {emailAddresses.length + phoneNumbers.length > 0 && (
         <DetailsColumn sx={props.columnSx}>
           {emailAddresses.map((email, index) => (
-            <ExternalLinkDetailsCell
+            <ExternalLinkDetailsItem
               key={`${email}.${index}`}
-              name={`emailAddress.${index}`}
-              label={"E-Mail-Adresse"}
+              label="E-Mail-Adresse"
               value={email}
               href={(value) => `mailto:${value}`}
             />
           ))}
           {phoneNumbers.map((phoneNumber, index) => (
-            <DetailsCell
+            <DetailsItem
               key={`${phoneNumber}.${index}`}
-              name={`phoneNumber.${index}`}
-              label={"Telefonnummer"}
+              label="Telefonnummer"
               value={phoneNumber}
             />
           ))}
diff --git a/employee-portal/src/lib/shared/components/centralFile/display/CentralFilePersonDetails.tsx b/employee-portal/src/lib/shared/components/centralFile/display/CentralFilePersonDetails.tsx
index b92933257bee7d7c6471a3195dc695ed97d9d4bb..ef2fb966bd33241268e68ed909d858581046e0a5 100644
--- a/employee-portal/src/lib/shared/components/centralFile/display/CentralFilePersonDetails.tsx
+++ b/employee-portal/src/lib/shared/components/centralFile/display/CentralFilePersonDetails.tsx
@@ -11,7 +11,6 @@ import {
 import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import { translateCountry } from "@eshg/lib-portal/helpers/countryOption";
 import { calculateAge } from "@eshg/lib-portal/helpers/dateTime";
-import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
 import { Stack } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 import { isDefined } from "remeda";
@@ -19,10 +18,10 @@ import { isDefined } from "remeda";
 import { GENDER_VALUES } from "@/lib/businessModules/schoolEntry/features/procedures/translations";
 import { ResponsiveDivider } from "@/lib/shared/components/ResponsiveDivider";
 import { BaseAddressDetails } from "@/lib/shared/components/address/BaseAddressDetails";
-import { DetailsCell } from "@/lib/shared/components/detailsSection/DetailsCell";
 import { DetailsColumn } from "@/lib/shared/components/detailsSection/DetailsColumn";
 import { DetailsRow } from "@/lib/shared/components/detailsSection/DetailsRow";
-import { ExternalLinkDetailsCell } from "@/lib/shared/components/detailsSection/ExternalLinkDetailsCell";
+import { DetailsItem } from "@/lib/shared/components/detailsSection/items/DetailsItem";
+import { ExternalLinkDetailsItem } from "@/lib/shared/components/detailsSection/items/ExternalLinkDetailsItem";
 import { BaseAddress } from "@/lib/shared/helpers/address";
 
 export interface CentralFilePerson {
@@ -40,8 +39,6 @@ export interface CentralFilePerson {
   readonly contactAddress?: BaseAddress;
 }
 
-const fieldName = createFieldNameMapper<CentralFilePerson>();
-
 export interface CentralFilePersonDetailsProps {
   readonly person: CentralFilePerson;
   readonly columnSx?: SxProps;
@@ -65,65 +62,52 @@ export function CentralFilePersonDetails(props: CentralFilePersonDetailsProps) {
         {(isDefined(person.salutation) || isDefined(person.title)) && (
           <DetailsRow>
             {isDefined(person.salutation) && (
-              <DetailsCell
-                name={fieldName("salutation")}
+              <DetailsItem
                 label={PERSON_FIELD_NAME.salutation}
                 value={SALUTATION_VALUES[person.salutation]}
               />
             )}
-            <DetailsCell
-              name={fieldName("title")}
-              label={PERSON_FIELD_NAME.title}
-              value={person.title}
-            />
+            <DetailsItem label={PERSON_FIELD_NAME.title} value={person.title} />
           </DetailsRow>
         )}
-        <DetailsCell
-          name={fieldName("firstName")}
+        <DetailsItem
           label={PERSON_FIELD_NAME.firstName}
           value={person.firstName}
         />
-        <DetailsCell
-          name={fieldName("lastName")}
+        <DetailsItem
           label={PERSON_FIELD_NAME.lastName}
           value={person.lastName}
         />
         <DetailsRow>
-          <DetailsCell
-            name={fieldName("dateOfBirth")}
+          <DetailsItem
             label={PERSON_FIELD_NAME.dateOfBirth}
             value={formatDate(person.dateOfBirth)}
           />
           {props.showAge && (
-            <DetailsCell
-              name="currentAge"
+            <DetailsItem
               label="Alter"
               value={calculateAge(person.dateOfBirth)}
             />
           )}
           {isDefined(person.gender) && (
-            <DetailsCell
-              name={fieldName("gender")}
+            <DetailsItem
               label={PERSON_FIELD_NAME.gender}
               value={GENDER_VALUES[person.gender]}
             />
           )}
         </DetailsRow>
-        <DetailsCell
-          name={fieldName("nameAtBirth")}
+        <DetailsItem
           label={PERSON_FIELD_NAME.nameAtBirth}
           value={person.nameAtBirth}
         />
         {(person.placeOfBirth ?? person.countryOfBirth) && (
           <DetailsRow>
-            <DetailsCell
-              name={fieldName("placeOfBirth")}
+            <DetailsItem
               label={PERSON_FIELD_NAME.placeOfBirth}
               value={person.placeOfBirth}
             />
             {person.countryOfBirth && (
-              <DetailsCell
-                name={fieldName("countryOfBirth")}
+              <DetailsItem
                 label={PERSON_FIELD_NAME.countryOfBirth}
                 value={translateCountry(person.countryOfBirth)}
               />
@@ -140,18 +124,16 @@ export function CentralFilePersonDetails(props: CentralFilePersonDetailsProps) {
       {emailAddresses.length + phoneNumbers.length > 0 && (
         <DetailsColumn sx={props.columnSx}>
           {emailAddresses.map((email, index) => (
-            <ExternalLinkDetailsCell
+            <ExternalLinkDetailsItem
               key={`${email}.${index}`}
-              name={`emailAddress.${index}`}
               label={PERSON_FIELD_NAME.emailAddresses}
               value={email}
               href={(value) => `mailto:${value}`}
             />
           ))}
           {phoneNumbers.map((phoneNumber, index) => (
-            <DetailsCell
+            <DetailsItem
               key={`${phoneNumber}.${index}`}
-              name={`phoneNumber.${index}`}
               label={PERSON_FIELD_NAME.phoneNumbers}
               value={phoneNumber}
             />
diff --git a/employee-portal/src/lib/shared/components/centralFile/sync/SyncBarrier.tsx b/employee-portal/src/lib/shared/components/centralFile/sync/SyncBarrier.tsx
index 463ed8a9e9be640176aa6d28e1b3c64d4a7714f3..778222d4f058e07d9728839d916c15da7a0da2b1 100644
--- a/employee-portal/src/lib/shared/components/centralFile/sync/SyncBarrier.tsx
+++ b/employee-portal/src/lib/shared/components/centralFile/sync/SyncBarrier.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiFacilitySync } from "@eshg/employee-portal-api/officialMedicalService";
 import { RequiresChildren } from "@eshg/lib-portal/types/react";
+import { ApiFacilitySync } from "@eshg/official-medical-service-api";
 import { useRouter } from "next/navigation";
 
 import { PersonDetails } from "@/lib/businessModules/schoolEntry/api/models/Person";
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentDisplay.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentDisplay.tsx
index 306702f9a11bb1715d0c0a416891e06fc465e03e..f479fe31822147ea7d4abd5eee9aed9ee4e08178 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentDisplay.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentDisplay.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiEditorBodyElementsInner } from "@eshg/employee-portal-api/libEditor";
+import { ApiEditorBodyElementsInner } from "@eshg/lib-editor-api";
 import { Box } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 import { MouseEventHandler, PropsWithChildren } from "react";
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentEditor.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentEditor.tsx
index 0c149a6776c2ad5ccbfdd298f6c93fdb2bf306f5..937e6a56b4649d5cb98a40b3710ee2527633b24e 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentEditor.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentEditor.tsx
@@ -10,7 +10,7 @@ import {
   ApiEditorBodyElementsInner,
   ApiUpdateEditorRequest,
   EditorApiInterface,
-} from "@eshg/employee-portal-api/libEditor";
+} from "@eshg/lib-editor-api";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import { Box } from "@mui/joy";
 import { useEffect, useRef, useState } from "react";
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElement.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElement.tsx
index 4ea800345d510af6eebe7fb35f278c9853dd7da6..2a2b073ab3682e67973d38d0b3b6876da01ddac3 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElement.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElement.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiEditorBodyElementsInner } from "@eshg/employee-portal-api/libEditor";
+import { ApiEditorBodyElementsInner } from "@eshg/lib-editor-api";
 import { Divider, Stack, Typography } from "@mui/joy";
 
 import { ContentElementAudios } from "@/lib/shared/components/contentEditor/ContentElementAudio";
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElementAudio.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElementAudio.tsx
index b07307b5af4c1f29eaaaa6df98c07fe95926c1a0..5ad2d6e4ac87b52304ba7e7d58e6d1c7aa88f050 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElementAudio.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElementAudio.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiEditorElementAudios } from "@eshg/employee-portal-api/libEditor";
+import { ApiEditorElementAudios } from "@eshg/lib-editor-api";
 import { OpenInNew } from "@mui/icons-material";
 import { Stack, Typography } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElementFullTextEditor.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElementFullTextEditor.tsx
index 636644db51f94c72125450841e9bdec86cd5b4ba..6c555f0314acffbcde12b39df0919da211bc2529 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElementFullTextEditor.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElementFullTextEditor.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUpdateEditorRequest } from "@eshg/employee-portal-api/libEditor";
+import { ApiUpdateEditorRequest } from "@eshg/lib-editor-api";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { Divider, Stack, Typography } from "@mui/joy";
 import { Formik } from "formik";
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElementImages.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElementImages.tsx
index cec0cde50b2892017db73caa896b5b349050cc94..197c40e05bf3e7eccb63a954f7abbef07e868efc 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElementImages.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElementImages.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiFileType } from "@eshg/employee-portal-api/businessProcedures";
-import { ApiEditorElementImages } from "@eshg/employee-portal-api/libEditor";
+import { ApiEditorElementImages } from "@eshg/lib-editor-api";
+import { ApiFileType } from "@eshg/lib-procedures-api";
 import { OpenInNew } from "@mui/icons-material";
 import { Stack, Typography } from "@mui/joy";
 
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElementProperties.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElementProperties.tsx
index dd6ba6a3311f5946627bae32045db3b5ed3cb93a..c0d7334b34159a215f34b7c64379ba1896f9b06f 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElementProperties.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElementProperties.tsx
@@ -6,7 +6,7 @@
 import {
   ApiEditorBodyElementsInner,
   ApiUpdateEditorRequest,
-} from "@eshg/employee-portal-api/libEditor";
+} from "@eshg/lib-editor-api";
 import { Typography } from "@mui/joy";
 
 import { ContentElementFullTextEditor } from "@/lib/shared/components/contentEditor/ContentElementFullTextEditor";
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElementPropertySheet.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElementPropertySheet.tsx
index 774f4cda45a3f0fa7afaf5283b2e702530987347..f8c73217a7d085f8becd49c2177c1f133740a980 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElementPropertySheet.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElementPropertySheet.tsx
@@ -6,7 +6,7 @@
 import {
   ApiEditorBodyElementsInner,
   ApiUpdateEditorRequest,
-} from "@eshg/employee-portal-api/libEditor";
+} from "@eshg/lib-editor-api";
 import { Divider, Typography } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
 
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElementQA.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElementQA.tsx
index a1b93bbc93ffeb3c5a9f9d2c1ca19c21adea8006..96bfa809672625b837e9308954c33189232fedb3 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElementQA.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElementQA.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiEditorElementQA } from "@eshg/employee-portal-api/libEditor";
+import { ApiEditorElementQA } from "@eshg/lib-editor-api";
 import {
   Checkbox,
   FormControl,
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElementQAEditor.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElementQAEditor.tsx
index 65b78c35ef41f7635c723924e95492a46e6425bb..ae8c0f8d0befe13704fb8181d294bd2a042e176b 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElementQAEditor.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElementQAEditor.tsx
@@ -7,7 +7,7 @@ import {
   ApiEditorElementAnswer,
   ApiEditorElementQA,
   ApiUpdateEditorRequest,
-} from "@eshg/employee-portal-api/libEditor";
+} from "@eshg/lib-editor-api";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import CheckBox from "@mui/icons-material/CheckBox";
 import CheckBoxOutlineBlank from "@mui/icons-material/CheckBoxOutlineBlank";
diff --git a/employee-portal/src/lib/shared/components/contentEditor/ContentElementTextEditor.tsx b/employee-portal/src/lib/shared/components/contentEditor/ContentElementTextEditor.tsx
index a8ab3191f4ecd261a934a45304543a9dd9caf403..eb7fd17a77fa4c59380ca67e1856cfe9b85ee396 100644
--- a/employee-portal/src/lib/shared/components/contentEditor/ContentElementTextEditor.tsx
+++ b/employee-portal/src/lib/shared/components/contentEditor/ContentElementTextEditor.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUpdateEditorRequest } from "@eshg/employee-portal-api/libEditor";
+import { ApiUpdateEditorRequest } from "@eshg/lib-editor-api";
 import { FormPlus } from "@eshg/lib-portal/components/form/FormPlus";
 import { Divider, Stack, Typography } from "@mui/joy";
 import { Formik } from "formik";
diff --git a/employee-portal/src/lib/shared/components/detailsSection/DetailsCell.tsx b/employee-portal/src/lib/shared/components/detailsSection/DetailsCell.tsx
index 81439bab13f2a63a2991a9bb61cbf1b5be38166c..0f202ee83a009f0d8746287985d26462bffe11c4 100644
--- a/employee-portal/src/lib/shared/components/detailsSection/DetailsCell.tsx
+++ b/employee-portal/src/lib/shared/components/detailsSection/DetailsCell.tsx
@@ -22,6 +22,11 @@ export interface DetailsCellProps {
   valueSx?: SxProps;
 }
 
+/**
+ * @deprecated This component is very old and messy. Please migrate and start using the newer DetailsItem instead of DetailsCell.
+ *             The new component is based on composition and is more adaptable to situations through `slotProps`.
+ *             We removed the `name` prop, to properly enforce using the labels for locators in tests.
+ */
 export function DetailsCellWrapped(props: DetailsCellProps) {
   return (
     <DetailsCell
@@ -40,6 +45,11 @@ export function DetailsCellWrapped(props: DetailsCellProps) {
   );
 }
 
+/**
+ * @deprecated This component is very old and messy. Please migrate and start using the newer DetailsItem instead of DetailsCell.
+ *             The new component is based on composition and is more adaptable to situations through `slotProps`.
+ *             We removed the `name` prop, to properly enforce using the labels for locators in tests.
+ */
 export function DetailsCell({
   name: givenName,
   label,
diff --git a/employee-portal/src/lib/shared/components/detailsSection/items/DetailsItem.tsx b/employee-portal/src/lib/shared/components/detailsSection/items/DetailsItem.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..81af4283ff12226262566b4261f11ed1659d7e41
--- /dev/null
+++ b/employee-portal/src/lib/shared/components/detailsSection/items/DetailsItem.tsx
@@ -0,0 +1,96 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { Stack, StackProps, Typography, TypographyProps } from "@mui/joy";
+import { ComponentType, useId } from "react";
+import { isString } from "remeda";
+
+export interface DetailsItemProps<TLabelProps, TValueProps> {
+  label: TypographyProps["children"];
+  value: TypographyProps["children"] | undefined;
+
+  avoidWrap?: boolean;
+
+  slots?: {
+    label?: ComponentType<TLabelProps>;
+    value?: ComponentType<TValueProps>;
+  };
+  slotProps?: {
+    label?: Omit<TLabelProps, "children">;
+    value?: Omit<TValueProps, "children">;
+    root?: StackProps;
+  };
+}
+
+export function DetailsItem<
+  TLabelProps = TypographyProps,
+  TValueProps = TypographyProps,
+>(props: DetailsItemProps<TLabelProps, TValueProps>) {
+  const LabelComponent = props.slots?.label ?? DetailsItemLabel;
+  const DefaultValueComponent = props.avoidWrap
+    ? DetailsValueAvoidWrap
+    : DetailsItemValue;
+  const ValueComponent = props.slots?.value ?? DefaultValueComponent;
+
+  const labelProps = props.slotProps?.label;
+  const valueProps = props.slotProps?.value;
+
+  const isValueEmpty =
+    props.value === undefined ||
+    (isString(props.value) && props.value.trim() === "");
+
+  const id = useId();
+
+  if (isValueEmpty) {
+    return null;
+  }
+
+  return (
+    <Stack gap={0.25} {...props.slotProps?.root}>
+      <LabelComponent {...(labelProps as TLabelProps)} id={id}>
+        {props.label}
+      </LabelComponent>
+      <ValueComponent {...(valueProps as TValueProps)} aria-labelledby={id}>
+        {props.value}
+      </ValueComponent>
+    </Stack>
+  );
+}
+
+export function DetailsItemLabel({ sx, ...props }: TypographyProps) {
+  return (
+    <Typography
+      level="body-sm"
+      textColor="text.secondary"
+      noWrap
+      sx={{
+        width: "fit-content",
+        maxWidth: "100%",
+        ...sx,
+      }}
+      {...props}
+    />
+  );
+}
+
+export function DetailsItemValue({ sx, ...props }: TypographyProps) {
+  return (
+    <Typography
+      level="title-md"
+      sx={{
+        hyphens: "auto",
+        textWrap: "pretty",
+        wordBreak: "normal",
+        overflowWrap: "anywhere",
+        ...sx,
+      }}
+      {...props}
+    />
+  );
+}
+
+export function DetailsValueAvoidWrap({ sx, ...props }: TypographyProps) {
+  return <DetailsItemValue sx={{ width: "fit-content", ...sx }} {...props} />;
+}
diff --git a/employee-portal/src/lib/shared/components/detailsSection/items/ExternalLinkDetailsItem.tsx b/employee-portal/src/lib/shared/components/detailsSection/items/ExternalLinkDetailsItem.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..83c1ea9e36b82a0cf78ac3ee03ee615de285ddcb
--- /dev/null
+++ b/employee-portal/src/lib/shared/components/detailsSection/items/ExternalLinkDetailsItem.tsx
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { ExternalLink } from "@eshg/lib-portal/components/navigation/ExternalLink";
+import { TypographyProps } from "@mui/joy";
+import { ComponentProps } from "react";
+import { isString } from "remeda";
+
+import {
+  DetailsItem,
+  DetailsItemProps,
+  DetailsItemValue,
+} from "@/lib/shared/components/detailsSection/items/DetailsItem";
+
+type ReducedItemProps<TLabelProps> = Omit<
+  DetailsItemProps<
+    TLabelProps,
+    ComponentProps<typeof DetailsValueExternalLink>
+  >,
+  "value"
+>;
+
+interface ExternalLinkDetailsItemProps<TLabelProps>
+  extends ReducedItemProps<TLabelProps> {
+  value: string | undefined;
+  href: (value: string) => string;
+}
+
+export function ExternalLinkDetailsItem<TLabelProps = TypographyProps>(
+  props: ExternalLinkDetailsItemProps<TLabelProps>,
+) {
+  return (
+    <DetailsItem
+      {...props}
+      slots={{
+        ...props.slots,
+        value: DetailsValueExternalLink,
+      }}
+      slotProps={{
+        ...props.slotProps,
+        value: {
+          href: props.href,
+          ...props.slotProps?.value,
+        },
+      }}
+    />
+  );
+}
+
+function DetailsValueExternalLink({
+  children,
+  href,
+  ...props
+}: TypographyProps & {
+  href: (value: string) => string;
+}) {
+  return (
+    <DetailsItemValue {...props}>
+      <ExternalLink
+        href={isString(children) ? href(children) : undefined}
+        sx={{ wordBreak: "break-word", hyphens: "manual" }}
+      >
+        {children}
+      </ExternalLink>
+    </DetailsItemValue>
+  );
+}
diff --git a/employee-portal/src/lib/shared/components/filterSettings/FilterSettings.tsx b/employee-portal/src/lib/shared/components/filterSettings/FilterSettings.tsx
index fc1cb4ee893a56f7c0f6378e4dcfa582a086b448..24c1e080d0dc593a2ed0ec7dd332fa046bc280e3 100644
--- a/employee-portal/src/lib/shared/components/filterSettings/FilterSettings.tsx
+++ b/employee-portal/src/lib/shared/components/filterSettings/FilterSettings.tsx
@@ -17,6 +17,7 @@ import {
   FilterTemplates,
   FilterTemplatesProps,
 } from "@/lib/shared/components/filterSettings/FilterTemplates";
+import { TextFilter } from "@/lib/shared/components/filterSettings/TextFilter";
 import { YearFilter } from "@/lib/shared/components/filterSettings/YearFilter";
 import { FilterDefinition } from "@/lib/shared/components/filterSettings/models/FilterDefinition";
 import { FilterDraftValue } from "@/lib/shared/components/filterSettings/models/FilterValue";
@@ -170,6 +171,19 @@ export function FilterSettings(props: FilterSettingsProps) {
                   }
                 />
               );
+            case "Text":
+              return (
+                <TextFilter
+                  definition={item.filterDefinition}
+                  value={findValueByDefinition(
+                    props.draftValues,
+                    item.filterDefinition,
+                  )}
+                  onChange={(value) =>
+                    props.onDraftValueChange(item.filterDefinition.key, value)
+                  }
+                />
+              );
           }
         }}
       />
diff --git a/employee-portal/src/lib/shared/components/filterSettings/SearchInstitutionFilter.tsx b/employee-portal/src/lib/shared/components/filterSettings/SearchInstitutionFilter.tsx
index 187d865536bfcdbb2d1aead09afad848482e0bea..ed9e9ae59eca6a90f363e2be13233bcf48bbc341 100644
--- a/employee-portal/src/lib/shared/components/filterSettings/SearchInstitutionFilter.tsx
+++ b/employee-portal/src/lib/shared/components/filterSettings/SearchInstitutionFilter.tsx
@@ -3,7 +3,6 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { SearchOutlined } from "@mui/icons-material";
 import { Autocomplete } from "@mui/joy";
 import { useState } from "react";
 import { identity } from "remeda";
@@ -17,6 +16,7 @@ import { mapContactToSelectOption } from "@/lib/shared/helpers/selectOptionMappe
 interface SearchInstitutionFilterProps {
   institutionId: string | undefined;
   onChange: (institutionId: string | undefined) => void;
+  placeholder: string;
 }
 
 export function SearchInstitutionFilter(props: SearchInstitutionFilterProps) {
@@ -41,8 +41,7 @@ export function SearchInstitutionFilter(props: SearchInstitutionFilterProps) {
       inputValue={institutionName}
       options={institutionOptions}
       filterOptions={identity()}
-      placeholder="Schule suchen"
-      endDecorator={<SearchOutlined />}
+      placeholder={props.placeholder}
       loading={searchInstitutions.isLoading}
       onInputChange={(_, newInputValue) => setInstitutionName(newInputValue)}
       onChange={(_event, value) => {
diff --git a/employee-portal/src/lib/shared/components/filterSettings/TextFilter.tsx b/employee-portal/src/lib/shared/components/filterSettings/TextFilter.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..002b5b480d803fe1c49c31ad7e17b8019ec3121a
--- /dev/null
+++ b/employee-portal/src/lib/shared/components/filterSettings/TextFilter.tsx
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { Input } from "@mui/joy";
+
+import {
+  TextFilterDefinition,
+  TextFilterValue,
+} from "@/lib/shared/components/filterSettings/models/TextFilter";
+
+export interface TextFilterProps {
+  definition: TextFilterDefinition;
+  value: TextFilterValue | null;
+  onChange: (value: TextFilterValue | null) => void;
+}
+
+export function TextFilter(props: TextFilterProps) {
+  function handleChange(optionValue: string) {
+    props.onChange(
+      optionValue
+        ? {
+            type: "Text",
+            key: props.definition.key,
+            value: optionValue,
+          }
+        : null,
+    );
+  }
+
+  return (
+    <Input
+      type="text"
+      value={props.value?.value ?? ""}
+      onChange={(event) => handleChange(event.target.value)}
+      sx={{ width: "100%" }}
+    />
+  );
+}
diff --git a/employee-portal/src/lib/shared/components/filterSettings/models/FilterDefinition.ts b/employee-portal/src/lib/shared/components/filterSettings/models/FilterDefinition.ts
index 767c1ddb57da4cf8c9fefe83f6cf17f6c70228e3..d08a8586179243ce5942d531a8fca0ce25be16f2 100644
--- a/employee-portal/src/lib/shared/components/filterSettings/models/FilterDefinition.ts
+++ b/employee-portal/src/lib/shared/components/filterSettings/models/FilterDefinition.ts
@@ -7,6 +7,7 @@ import { DateComparisonFilterDefinition } from "@/lib/shared/components/filterSe
 import { DateSpanFilterDefinition } from "@/lib/shared/components/filterSettings/models/DateSpanFilter";
 import { EnumFilterDefinition } from "@/lib/shared/components/filterSettings/models/EnumFilter";
 import { NumberFilterDefinition } from "@/lib/shared/components/filterSettings/models/NumberFilter";
+import { TextFilterDefinition } from "@/lib/shared/components/filterSettings/models/TextFilter";
 import { YearFilterDefinition } from "@/lib/shared/components/filterSettings/models/YearFilter";
 
 import { DateFilterDefinition } from "./DateFilter";
@@ -26,4 +27,5 @@ export type FilterDefinition =
   | DateSpanFilterDefinition
   | DateComparisonFilterDefinition
   | NumberFilterDefinition
-  | YearFilterDefinition;
+  | YearFilterDefinition
+  | TextFilterDefinition;
diff --git a/employee-portal/src/lib/shared/components/filterSettings/models/FilterValue.ts b/employee-portal/src/lib/shared/components/filterSettings/models/FilterValue.ts
index 9c109b25815334166cd41299da3151b9e779b045..8d4cc6e158b890a00b9c6702bc5acafb5d6a6bc2 100644
--- a/employee-portal/src/lib/shared/components/filterSettings/models/FilterValue.ts
+++ b/employee-portal/src/lib/shared/components/filterSettings/models/FilterValue.ts
@@ -12,6 +12,7 @@ import {
   NumberFilterDraftValue,
   NumberFilterValue,
 } from "@/lib/shared/components/filterSettings/models/NumberFilter";
+import { TextFilterValue } from "@/lib/shared/components/filterSettings/models/TextFilter";
 import { YearFilterValue } from "@/lib/shared/components/filterSettings/models/YearFilter";
 
 import { DateFilterValue } from "./DateFilter";
@@ -29,7 +30,8 @@ export type FilterValue =
   | EnumFilterValue
   | EnumSingleFilterValue
   | NumberFilterValue
-  | YearFilterValue;
+  | YearFilterValue
+  | TextFilterValue;
 
 export type FilterDraftValue =
   | DateFilterValue
@@ -38,4 +40,5 @@ export type FilterDraftValue =
   | EnumFilterValue
   | EnumSingleFilterValue
   | NumberFilterDraftValue
-  | YearFilterValue;
+  | YearFilterValue
+  | TextFilterValue;
diff --git a/employee-portal/src/lib/shared/components/filterSettings/models/TextFilter.ts b/employee-portal/src/lib/shared/components/filterSettings/models/TextFilter.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0ddc8014d6a2dfc5ccb19fac979646f1691404b7
--- /dev/null
+++ b/employee-portal/src/lib/shared/components/filterSettings/models/TextFilter.ts
@@ -0,0 +1,16 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { FilterDefinitionBase } from "@/lib/shared/components/filterSettings/models/FilterDefinition";
+import { FilterValueBase } from "@/lib/shared/components/filterSettings/models/FilterValue";
+
+export interface TextFilterDefinition extends FilterDefinitionBase {
+  type: "Text";
+}
+
+export interface TextFilterValue extends FilterValueBase {
+  type: "Text";
+  value: string;
+}
diff --git a/employee-portal/src/lib/shared/components/filterSettings/useSearchParamStateProvider.ts b/employee-portal/src/lib/shared/components/filterSettings/useSearchParamStateProvider.ts
index 7c3838b2f8e3b29d98a43c5e20630b1c1898bfa8..6703b1c2421ed90625f914a769b343312569c753 100644
--- a/employee-portal/src/lib/shared/components/filterSettings/useSearchParamStateProvider.ts
+++ b/employee-portal/src/lib/shared/components/filterSettings/useSearchParamStateProvider.ts
@@ -94,6 +94,8 @@ export function activeValueToParamValues(activeValue: FilterValue): string[] {
       return [activeValue.startDate, activeValue.endDate].filter(
         (value) => value !== undefined,
       );
+    case "Text":
+      return [activeValue.value];
   }
 }
 
diff --git a/employee-portal/src/lib/shared/components/form/MultiFormButtonBar.tsx b/employee-portal/src/lib/shared/components/form/MultiFormButtonBar.tsx
index 33bcbb627a885b8df3e0fe6e96f51ca522cda675..0910d239464de73d4a8c66e6157ec68deea6baa8 100644
--- a/employee-portal/src/lib/shared/components/form/MultiFormButtonBar.tsx
+++ b/employee-portal/src/lib/shared/components/form/MultiFormButtonBar.tsx
@@ -13,6 +13,7 @@ interface MultiFormButtonBarProps {
   onCancel?: () => void;
   onBack?: () => void;
   onDelete?: () => void;
+  onReject?: () => void;
   submitting: boolean;
   submitLabel: string | undefined;
 }
@@ -43,6 +44,11 @@ export function MultiFormButtonBar(props: MultiFormButtonBarProps) {
               Entfernen
             </Button>
           )}
+          {isDefined(props.onReject) && (
+            <Button variant="plain" color="danger" onClick={props.onReject}>
+              Ablehnen
+            </Button>
+          )}
           {isDefined(props.submitLabel) && (
             <SubmitButton
               submitting={props.submitting}
diff --git a/employee-portal/src/lib/shared/components/formDialog/FormDialog.tsx b/employee-portal/src/lib/shared/components/formDialog/FormDialog.tsx
index cf912d11ae7c001aea578630b7c5ac88cbc7d3cc..89117e7b742a6424ca3eb2ea297b4f95536f51e2 100644
--- a/employee-portal/src/lib/shared/components/formDialog/FormDialog.tsx
+++ b/employee-portal/src/lib/shared/components/formDialog/FormDialog.tsx
@@ -37,7 +37,7 @@ export function FormDialog<T extends FormikValues>({
   return (
     <BaseModal modalTitle={title} color={color} open={open} onClose={onClose}>
       <Formik initialValues={initialValues} onSubmit={onSubmit}>
-        {({ isSubmitting, handleSubmit }) => {
+        {({ isSubmitting }) => {
           return (
             <FormPlus>
               <Typography textColor="text.secondary">{description}</Typography>
@@ -54,10 +54,10 @@ export function FormDialog<T extends FormikValues>({
                     {cancelLabel}
                   </Button>
                   <Button
+                    type="submit"
                     size="sm"
                     color={color}
                     loading={isSubmitting}
-                    onClick={() => handleSubmit()}
                     loadingPosition={"start"}
                     data-testid="formDialogConfirm"
                   >
diff --git a/employee-portal/src/lib/shared/components/formFields/CheckboxField.tsx b/employee-portal/src/lib/shared/components/formFields/CheckboxField.tsx
index 53d07132773e556c8d82e78e704d0f88f18697ac..94051b4789ffa2b7b1c272ee20bfb2cb35c2636d 100644
--- a/employee-portal/src/lib/shared/components/formFields/CheckboxField.tsx
+++ b/employee-portal/src/lib/shared/components/formFields/CheckboxField.tsx
@@ -8,8 +8,8 @@ import { useBaseField } from "@eshg/lib-portal/components/formFields/BaseField";
 import { FieldProps } from "@eshg/lib-portal/types/form";
 import { Checkbox, CheckboxProps, FormControl, FormHelperText } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
-import { useFormikContext } from "formik";
-import { ChangeEventHandler } from "react";
+import { FormikHandlers, useFormikContext } from "formik";
+import { ChangeEventHandler, memo } from "react";
 import { isString } from "remeda";
 
 export interface CheckboxFieldProps extends FieldProps<boolean> {
@@ -22,10 +22,9 @@ export interface CheckboxFieldProps extends FieldProps<boolean> {
   "aria-label"?: string;
 }
 
-function isChecked(
-  value: string | number | readonly string[],
-  representingValue?: string,
-): boolean {
+type ValueType = boolean | number | string | readonly string[];
+
+function isChecked(value: ValueType, representingValue?: string): boolean {
   if (value == null) {
     return false;
   }
@@ -37,12 +36,11 @@ function isChecked(
 }
 
 export function CheckboxField(props: CheckboxFieldProps) {
-  const disabled = useIsFormDisabled() || props.disabled;
   const {
     input: field,
     required,
     meta,
-  } = useBaseField<number | string | readonly string[]>({
+  } = useBaseField<ValueType>({
     name: props.name,
     required: props.required,
     type: "checkbox",
@@ -53,34 +51,70 @@ export function CheckboxField(props: CheckboxFieldProps) {
       return props.required;
     },
   });
+  const { isValid } = useFormikContext();
+
+  return (
+    <MemoizedCheckboxField
+      {...props}
+      fieldName={field.name}
+      fieldValue={field.value}
+      fieldOnChange={field.onChange}
+      fieldOnBlur={field.onBlur}
+      fieldRequired={required}
+      metaError={meta.error}
+      isValid={isValid}
+    />
+  );
+}
+
+interface InnerCheckboxFieldProps extends CheckboxFieldProps {
+  fieldName: string;
+  fieldValue: ValueType;
+  fieldOnChange: FormikHandlers["handleChange"];
+  fieldOnBlur: FormikHandlers["handleBlur"];
+  fieldRequired: boolean;
+  metaError?: string;
+  isValid: boolean;
+}
+
+const MemoizedCheckboxField = memo(function InnerCheckboxField({
+  fieldName,
+  fieldValue,
+  fieldOnChange,
+  fieldOnBlur,
+  fieldRequired,
+  metaError,
+  isValid,
+  ...props
+}: InnerCheckboxFieldProps) {
+  const disabled = useIsFormDisabled() || props.disabled;
 
   const starLabel =
     isString(props.label) && props.required ? `${props.label} *` : props.label;
 
-  const { isValid } = useFormikContext();
-  const hasValidationError = !!meta.error && !isValid;
+  const hasValidationError = !!metaError && !isValid;
 
   // Often checkbox helper text is shown for a whole group,
   // only show for single checkbox if the checkbox is "required"
   const showHelperText = hasValidationError && props.required != null;
 
   return (
-    <FormControl error={hasValidationError} required={required}>
+    <FormControl error={hasValidationError} required={fieldRequired}>
       <Checkbox
-        name={field.name}
+        name={fieldName}
         onChange={(event) => {
-          field.onChange(event);
+          fieldOnChange(event);
           if (props.onChange != null) {
             props.onChange(event);
           }
         }}
-        onBlur={field.onBlur}
+        onBlur={fieldOnBlur}
         label={starLabel}
         disabled={disabled}
-        checked={isChecked(field.value, props.representingValue)}
+        checked={isChecked(fieldValue, props.representingValue)}
         value={props.representingValue ?? "true"}
         size={props.size}
-        required={required}
+        required={fieldRequired}
         variant={props.variant}
         sx={props.sx}
         slotProps={{
@@ -92,4 +126,4 @@ export function CheckboxField(props: CheckboxFieldProps) {
       ) : null}
     </FormControl>
   );
-}
+});
diff --git a/employee-portal/src/lib/shared/components/formFields/SearchContactField.tsx b/employee-portal/src/lib/shared/components/formFields/SearchContactField.tsx
index 487ac9a6b54fcd261a93f1f586d20e594b6449ca..66974b389e455f054520d1772d25e5ba36b0a8ce 100644
--- a/employee-portal/src/lib/shared/components/formFields/SearchContactField.tsx
+++ b/employee-portal/src/lib/shared/components/formFields/SearchContactField.tsx
@@ -4,7 +4,6 @@
  */
 
 import { ApiContactCategory } from "@eshg/base-api";
-import { SearchOutlined } from "@mui/icons-material";
 
 import { contactCategoryNames } from "@/lib/baseModule/shared/translations";
 import { SelectContactField } from "@/lib/shared/components/formFields/SelectContactField";
@@ -34,7 +33,6 @@ export function SearchContactField(props: SearchContactFieldProps) {
       categories={new Set([props.category])}
       placeholder={`${translatedCategory} suchen`}
       required={requiredMessage[props.category]}
-      endDecorator={<SearchOutlined />}
     />
   );
 }
diff --git a/employee-portal/src/lib/shared/components/formFields/SearchMultipleContactsField.tsx b/employee-portal/src/lib/shared/components/formFields/SearchMultipleContactsField.tsx
index b16f0b9b2b08f0332f48dce89bdf84d983275436..af173f022d95fd9e4474ed3b6d764c2e9364a366 100644
--- a/employee-portal/src/lib/shared/components/formFields/SearchMultipleContactsField.tsx
+++ b/employee-portal/src/lib/shared/components/formFields/SearchMultipleContactsField.tsx
@@ -5,7 +5,6 @@
 
 import { ApiContactCategory } from "@eshg/base-api";
 import { SingleAutocompleteField } from "@eshg/lib-portal/components/formFields/autocomplete/SingleAutocompleteField";
-import { SearchOutlined } from "@mui/icons-material";
 import { useState } from "react";
 
 import { useSearchContacts } from "@/lib/baseModule/api/queries/contacts";
@@ -35,7 +34,6 @@ export function SearchMultipleContactsField(props: SearchContactFieldProps) {
       required={`Bitte ein/e ${categories} angeben.`}
       options={options}
       placeholder={`${categories} suchen`}
-      endDecorator={<SearchOutlined />}
       loading={searchContacts.isLoading}
       onInputChange={(_, newInputValue) => setContactName(newInputValue)}
       disableFiltering
diff --git a/employee-portal/src/lib/shared/components/formFields/SelectContactField.tsx b/employee-portal/src/lib/shared/components/formFields/SelectContactField.tsx
index 31961102cb15e58ed2d9fb11be9e617f3795131a..83cb27f70ddf0194cb048895625595075c988100 100644
--- a/employee-portal/src/lib/shared/components/formFields/SelectContactField.tsx
+++ b/employee-portal/src/lib/shared/components/formFields/SelectContactField.tsx
@@ -23,6 +23,7 @@ interface SelectContactFieldProps {
   required?: string;
   placeholder?: string;
   endDecorator?: ReactNode;
+  disabled?: boolean;
 }
 
 export function SelectContactField(props: SelectContactFieldProps) {
@@ -42,6 +43,7 @@ export function SelectContactField(props: SelectContactFieldProps) {
       required={props.required}
       placeholder={props.placeholder}
       endDecorator={props.endDecorator}
+      disabled={props.disabled}
     />
   );
 }
diff --git a/employee-portal/src/lib/shared/components/formFields/TextareaField.tsx b/employee-portal/src/lib/shared/components/formFields/TextareaField.tsx
index c379a37cf988e43ed408afb96d0ffa970af0529f..5b4145c04d0d02a02732e71d10e8f2a38ab18ec5 100644
--- a/employee-portal/src/lib/shared/components/formFields/TextareaField.tsx
+++ b/employee-portal/src/lib/shared/components/formFields/TextareaField.tsx
@@ -27,6 +27,7 @@ export interface TextareaFieldProps extends ValidationRules<string> {
   "data-testid"?: string;
   "aria-label"?: string;
   slotProps?: TextareaProps["slotProps"];
+  className?: string;
 }
 
 export function TextareaField(props: TextareaFieldProps) {
@@ -53,6 +54,7 @@ export function TextareaField(props: TextareaFieldProps) {
       error={field.error}
       sx={props.sx}
       disabled={disabled}
+      className={props.className}
     >
       <Textarea
         aria-labelledby={props["label-id"]}
diff --git a/employee-portal/src/lib/shared/components/gdpr/useGdprValidationTasksAlert.ts b/employee-portal/src/lib/shared/components/gdpr/useGdprValidationTasksAlert.ts
index 7883c2134a994092f0a8c1fb5cc0e01318b1d9af..21b9f579c08d481d8d6e5490ac554c42a26f27a0 100644
--- a/employee-portal/src/lib/shared/components/gdpr/useGdprValidationTasksAlert.ts
+++ b/employee-portal/src/lib/shared/components/gdpr/useGdprValidationTasksAlert.ts
@@ -5,11 +5,11 @@
 
 "use client";
 
+import { useControlledAlert } from "@eshg/lib-portal/errorHandling/AlertContext";
 import {
   ApiBusinessModule,
   ApiGetGdprNotificationBannerResponse,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { useControlledAlert } from "@eshg/lib-portal/errorHandling/AlertContext";
+} from "@eshg/lib-procedures-api";
 import { isPast } from "date-fns";
 
 import { routes } from "@/lib/baseModule/shared/routes";
@@ -19,23 +19,27 @@ export function useGdprValidationTasksAlert({
   banner,
   businessModule,
 }: {
-  banner: ApiGetGdprNotificationBannerResponse;
+  banner: ApiGetGdprNotificationBannerResponse | undefined;
   businessModule: ApiBusinessModule;
 }) {
-  const { openValidationTasksCount, earliestDueDate } = banner;
+  let numberOfTasksLine = "";
+  let deadlineLine = "";
 
-  const numberOfTasksLine =
-    openValidationTasksCount === 1
-      ? `Es liegt eine DSGVO-Anfrage vor.`
-      : `Es liegen ${openValidationTasksCount} DSGVO-Anfragen vor.`;
-  const deadlineLine =
-    earliestDueDate === undefined || isPast(earliestDueDate)
-      ? "Sie müssen diese sofort bearbeiten."
-      : `Sie haben noch ${formatDurationFromNowUntil(earliestDueDate)} Zeit, diese zu bearbeiten.`;
+  if (banner) {
+    const { openValidationTasksCount, earliestDueDate } = banner;
+    numberOfTasksLine =
+      openValidationTasksCount === 1
+        ? `Es liegt eine DSGVO-Anfrage vor.`
+        : `Es liegen ${openValidationTasksCount} DSGVO-Anfragen vor.`;
+    deadlineLine =
+      earliestDueDate === undefined || isPast(earliestDueDate)
+        ? "Sie müssen diese sofort bearbeiten."
+        : `Sie haben noch ${formatDurationFromNowUntil(earliestDueDate)} Zeit, diese zu bearbeiten.`;
+  }
 
   useControlledAlert({
     type: "warning",
-    open: openValidationTasksCount > 0,
+    open: !!banner && banner.openValidationTasksCount > 0,
     message: `${numberOfTasksLine} ${deadlineLine}`,
     action: {
       text: "Anfragen Prüfen",
diff --git a/employee-portal/src/lib/shared/components/icons/AddTextTemplate.tsx b/employee-portal/src/lib/shared/components/icons/AddTextTemplate.tsx
index bbb3465990daf3512f8470145a099fb3e8ec2421..dc27e441505f2d3f27c2385683211b8614b350e7 100644
--- a/employee-portal/src/lib/shared/components/icons/AddTextTemplate.tsx
+++ b/employee-portal/src/lib/shared/components/icons/AddTextTemplate.tsx
@@ -19,13 +19,13 @@ export function AddTextTemplate(props: SvgIconProps) {
           fillRule="evenodd"
           clipRule="evenodd"
           d="M17.2368 13.3759H15.307V15.3057H13.3772V17.2355H15.307V19.1654H17.2368V17.2355H19.1667V15.3057H17.2368V13.3759Z"
-          fill="#0B6BCB"
+          fill="currentColor"
         />
         <path
           fillRule="evenodd"
           clipRule="evenodd"
           d="M10.9498 1.29941L14.8321 5.18167C15.1374 5.48698 15.307 5.89782 15.307 6.32374V10.9862C13.0267 11.2124 11.2137 13.0254 10.9875 15.3057H2.44277C1.55701 15.3057 0.833328 14.582 0.833328 13.6963V2.44147C0.833328 1.55572 1.55701 0.832031 2.44277 0.832031H9.8153C10.2412 0.832031 10.6521 1.00164 10.9498 1.29941ZM9.51754 4.04715H4.04845V5.65659H9.51754V4.04715ZM4.04845 12.0906H9.51754V10.4812H4.04845V12.0906ZM4.04845 8.87171H11.4474V7.26604H4.04845V8.87171Z"
-          fill="#0B6BCB"
+          fill="currentColor"
         />
       </svg>
     </SvgIcon>
diff --git a/employee-portal/src/lib/shared/components/infoTile/InformationSheet.tsx b/employee-portal/src/lib/shared/components/infoTile/InformationSheet.tsx
index 87c29060d871fd2dc0ca22e3e96bec826a0723b9..8843009aa20421d950a78ed7fc03403c1a7f0f95 100644
--- a/employee-portal/src/lib/shared/components/infoTile/InformationSheet.tsx
+++ b/employee-portal/src/lib/shared/components/infoTile/InformationSheet.tsx
@@ -11,7 +11,11 @@ export function InformationSheet({
   sx,
   dataTestId,
   ...props
-}: PropsWithChildren<SheetProps & { dataTestId?: string }>) {
+}: PropsWithChildren<
+  SheetProps & {
+    dataTestId?: string;
+  }
+>) {
   return (
     <Sheet
       sx={{
@@ -24,7 +28,13 @@ export function InformationSheet({
       data-testid={dataTestId}
       {...props}
     >
-      <Stack gap={2} sx={{ flexGrow: 1, width: "100%" }}>
+      <Stack
+        gap={2}
+        sx={{
+          flexGrow: 1,
+          width: "100%",
+        }}
+      >
         {children}
       </Stack>
     </Sheet>
diff --git a/employee-portal/src/lib/shared/components/legacyPersonSidebar/LegacyPersonSidebar.tsx b/employee-portal/src/lib/shared/components/legacyPersonSidebar/LegacyPersonSidebar.tsx
index e155d73eafd8831d261dd908d605a8e2a64d8fdd..436077a1d0ec25c929627668d4eeb08cd6549a6c 100644
--- a/employee-portal/src/lib/shared/components/legacyPersonSidebar/LegacyPersonSidebar.tsx
+++ b/employee-portal/src/lib/shared/components/legacyPersonSidebar/LegacyPersonSidebar.tsx
@@ -90,7 +90,7 @@ export function LegacyPersonSidebar({
   const { openCancelDialog } = useConfirmationDialog();
   const sidebarPersonFormRef = useRef<SidebarFormHandle>(null);
   const sidebarSearchFormRef = useRef<SidebarFormHandle>(null);
-  const searchTitle = searchFormTitle ? searchFormTitle : personFormTitle;
+  const searchTitle = searchFormTitle ?? personFormTitle;
 
   function resetAndCloseForm() {
     onClose();
diff --git a/employee-portal/src/lib/shared/components/legacyPersonSidebar/form/LegacyBasePersonForm.tsx b/employee-portal/src/lib/shared/components/legacyPersonSidebar/form/LegacyBasePersonForm.tsx
index 3a3dfc4d4baf5e5b5df5b23fcfb53d8a3aa4252b..9a69ef8ffbe033920b318ed166f79a622ff674bd 100644
--- a/employee-portal/src/lib/shared/components/legacyPersonSidebar/form/LegacyBasePersonForm.tsx
+++ b/employee-portal/src/lib/shared/components/legacyPersonSidebar/form/LegacyBasePersonForm.tsx
@@ -13,7 +13,10 @@ import {
   TITLE_OPTIONS,
   TITLE_VALUES,
 } from "@eshg/lib-portal/components/formFields/constants";
-import { validateLength } from "@eshg/lib-portal/helpers/validators";
+import {
+  validateDateOfBirth,
+  validateLength,
+} from "@eshg/lib-portal/helpers/validators";
 import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
 import { Grid, Stack } from "@mui/joy";
 
@@ -116,6 +119,7 @@ export function LegacyBasePersonForm({
             label="Geburtsdatum"
             required="Bitte ein Geburtsdatum angeben."
             disabled={disabledFields?.includes("dateOfBirth")}
+            validate={validateDateOfBirth}
           />
         </Grid>
         {!hiddenFields?.includes("gender") && (
diff --git a/employee-portal/src/lib/shared/components/legacyPersonSidebar/search/LegacyPersonSearchForm.tsx b/employee-portal/src/lib/shared/components/legacyPersonSidebar/search/LegacyPersonSearchForm.tsx
index c5a08f2c6de90dcef3eee75eb069489379e347ee..17c7abf68b3e797f2b349d9ca8bf7008af6bd3e4 100644
--- a/employee-portal/src/lib/shared/components/legacyPersonSidebar/search/LegacyPersonSearchForm.tsx
+++ b/employee-portal/src/lib/shared/components/legacyPersonSidebar/search/LegacyPersonSearchForm.tsx
@@ -6,6 +6,7 @@
 import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
+import { validateDateOfBirth } from "@eshg/lib-portal/helpers/validators";
 import SearchIcon from "@mui/icons-material/Search";
 import { Stack, Typography } from "@mui/joy";
 import { Formik } from "formik";
@@ -72,6 +73,7 @@ export function LegacyPersonSearchForm({
                   name="dateOfBirth"
                   label="Geburtsdatum"
                   required="Bitte ein Geburtsdatum angeben."
+                  validate={validateDateOfBirth}
                 />
                 <SubmitButton
                   submitting={loading === true || isSubmitting}
diff --git a/employee-portal/src/lib/shared/components/personSearch/PersonSearchForm.tsx b/employee-portal/src/lib/shared/components/personSearch/PersonSearchForm.tsx
index ba5192fcf5c953a6cf4b5efb9e9d0a192d4686ab..f47b395a726a03949143ba7e51eca4cf55886684 100644
--- a/employee-portal/src/lib/shared/components/personSearch/PersonSearchForm.tsx
+++ b/employee-portal/src/lib/shared/components/personSearch/PersonSearchForm.tsx
@@ -7,6 +7,7 @@ import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { formatPersonName } from "@eshg/lib-portal/formatters/person";
 import { toUtcDate } from "@eshg/lib-portal/helpers/dateTime";
+import { validateDateOfBirth } from "@eshg/lib-portal/helpers/validators";
 import {
   Close,
   InsertLinkOutlined,
@@ -100,6 +101,7 @@ export function PersonSearchForm(props: PersonSearchFormProps) {
             name="dateOfBirth"
             label="Geburtsdatum"
             required="Bitte Geburtsdatum eingeben"
+            validate={validateDateOfBirth}
           />
 
           <Button
diff --git a/employee-portal/src/lib/shared/components/personSidebar/form/DefaultPersonForm.tsx b/employee-portal/src/lib/shared/components/personSidebar/form/DefaultPersonForm.tsx
index 2c1451f7714a9344a1da3193264a424e4b2b85b9..2631fa572b296da25ef231e128829ea43ffef456 100644
--- a/employee-portal/src/lib/shared/components/personSidebar/form/DefaultPersonForm.tsx
+++ b/employee-portal/src/lib/shared/components/personSidebar/form/DefaultPersonForm.tsx
@@ -20,7 +20,10 @@ import {
   TITLE_OPTIONS,
 } from "@eshg/lib-portal/components/formFields/constants";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
-import { validateLength } from "@eshg/lib-portal/helpers/validators";
+import {
+  validateDateOfBirth,
+  validateLength,
+} from "@eshg/lib-portal/helpers/validators";
 import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
 import DeleteIcon from "@mui/icons-material/DeleteOutlined";
 import { Box, Divider, Grid, IconButton, Stack, Typography } from "@mui/joy";
@@ -134,6 +137,7 @@ export function DefaultPersonForm<TValues extends DefaultPersonFormValues>(
                     ? "Bitte ein Geburtsdatum angeben"
                     : undefined
                 }
+                validate={validateDateOfBirth}
               />
             </Grid>
             <Grid xxs>
diff --git a/employee-portal/src/lib/shared/components/personSidebar/helpers.ts b/employee-portal/src/lib/shared/components/personSidebar/helpers.ts
index afdac432d4cb2d05e823d1208f8ff894dd247e78..6f7fd035d6324fe3283596e17b1afcfde07e1b0b 100644
--- a/employee-portal/src/lib/shared/components/personSidebar/helpers.ts
+++ b/employee-portal/src/lib/shared/components/personSidebar/helpers.ts
@@ -23,6 +23,7 @@ import {
 import { DefaultPersonFormValues } from "@/lib/shared/components/personSidebar/form/DefaultPersonForm";
 
 export function normalizeListInputs(input: string[] | undefined): string[] {
+  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
   return input === undefined || input.length === 0 ? [""] : input;
 }
 
diff --git a/employee-portal/src/lib/shared/components/personSidebar/search/DefaultSearchPersonFormFields.tsx b/employee-portal/src/lib/shared/components/personSidebar/search/DefaultSearchPersonFormFields.tsx
index a67cde1868a0a88d26ddaf2c0a94727e8c50adc2..1ab111571d94268773da58ac94df7fab8ea8c977 100644
--- a/employee-portal/src/lib/shared/components/personSidebar/search/DefaultSearchPersonFormFields.tsx
+++ b/employee-portal/src/lib/shared/components/personSidebar/search/DefaultSearchPersonFormFields.tsx
@@ -6,7 +6,10 @@
 import { DateField } from "@eshg/lib-portal/components/formFields/DateField";
 import { InputField } from "@eshg/lib-portal/components/formFields/InputField";
 import { createFieldNameMapper } from "@eshg/lib-portal/helpers/form";
-import { validateLength } from "@eshg/lib-portal/helpers/validators";
+import {
+  validateDateOfBirth,
+  validateLength,
+} from "@eshg/lib-portal/helpers/validators";
 
 import { SearchPersonFormValues } from "@/lib/shared/components/personSidebar/search/SearchPersonSidebar";
 
@@ -31,6 +34,7 @@ export function DefaultSearchPersonFormFields() {
         name={fieldName("dateOfBirth")}
         label="Geburtsdatum"
         required="Bitte ein Geburtsdatum angeben."
+        validate={validateDateOfBirth}
       />
     </>
   );
diff --git a/employee-portal/src/lib/shared/components/procedures/helper.ts b/employee-portal/src/lib/shared/components/procedures/helper.ts
index d8f6b4596a217d76aac0e0133465fd94b0df4df1..7e77761d7d03f45acb8efea51d564ea0ed70e12d 100644
--- a/employee-portal/src/lib/shared/components/procedures/helper.ts
+++ b/employee-portal/src/lib/shared/components/procedures/helper.ts
@@ -13,7 +13,7 @@ import {
 import {
   ApiManualProgressEntryType,
   ApiProgressEntryClass,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 import { ReadonlyURLSearchParams } from "next/navigation";
 
 import { EnumFilterValue } from "@/lib/shared/components/filterSettings/models/EnumFilter";
diff --git a/employee-portal/src/lib/shared/components/procedures/inbox/InboxProcedureDetailsSidebar.tsx b/employee-portal/src/lib/shared/components/procedures/inbox/InboxProcedureDetailsSidebar.tsx
index 8ea3f17f7e00b3eea9e9595cd8a3afa9594766eb..211d95a1129f3f449e8d7fc9dfa6d9163009dce9 100644
--- a/employee-portal/src/lib/shared/components/procedures/inbox/InboxProcedureDetailsSidebar.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/inbox/InboxProcedureDetailsSidebar.tsx
@@ -3,13 +3,13 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { SALUTATION_VALUES } from "@eshg/lib-portal/components/formFields/constants";
+import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
 import {
   ApiGetInboxProcedureResponse,
   ApiInboxProcedureAddress,
   ApiInboxProcedureStatus,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { SALUTATION_VALUES } from "@eshg/lib-portal/components/formFields/constants";
-import { formatDate } from "@eshg/lib-portal/formatters/dateTime";
+} from "@eshg/lib-procedures-api";
 import { Button, Divider, Stack, Typography } from "@mui/joy";
 import { ReactElement, useState } from "react";
 
diff --git a/employee-portal/src/lib/shared/components/procedures/inbox/InboxProcedureStatusChip.tsx b/employee-portal/src/lib/shared/components/procedures/inbox/InboxProcedureStatusChip.tsx
index 9db3b6408c7283e7cc2e3e08a3d02acbaf19afac..77045d7fea7b5cf4beb0c71d54cc72200c508a1a 100644
--- a/employee-portal/src/lib/shared/components/procedures/inbox/InboxProcedureStatusChip.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/inbox/InboxProcedureStatusChip.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiInboxProcedureStatus } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiInboxProcedureStatus } from "@eshg/lib-procedures-api";
 import Chip from "@mui/joy/Chip";
 
 import { statusColors, statusNames } from "./constants";
diff --git a/employee-portal/src/lib/shared/components/procedures/inbox/InboxProceduresPage.tsx b/employee-portal/src/lib/shared/components/procedures/inbox/InboxProceduresPage.tsx
index f88a91741ae3b951c7572d07635e6b08560db19b..3b132ec6370a2ffe0f591d0ed5c212300eebffc8 100644
--- a/employee-portal/src/lib/shared/components/procedures/inbox/InboxProceduresPage.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/inbox/InboxProceduresPage.tsx
@@ -5,7 +5,7 @@
 
 "use client";
 
-import { ApiProcedureType } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiProcedureType } from "@eshg/lib-procedures-api";
 
 import {
   UseFetchInboxProcedure,
diff --git a/employee-portal/src/lib/shared/components/procedures/inbox/InboxProceduresTable.tsx b/employee-portal/src/lib/shared/components/procedures/inbox/InboxProceduresTable.tsx
index 92cb1e4b54ae17473f273970a7720da40e02f140..1c64fbcfd85db6cd76f5b358915fecf443efd234 100644
--- a/employee-portal/src/lib/shared/components/procedures/inbox/InboxProceduresTable.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/inbox/InboxProceduresTable.tsx
@@ -5,8 +5,8 @@
 
 "use client";
 
-import { ApiProcedureType } from "@eshg/employee-portal-api/businessProcedures";
 import { optionsFromRecord } from "@eshg/lib-portal/components/formFields/SelectOptions";
+import { ApiProcedureType } from "@eshg/lib-procedures-api";
 import { Stack } from "@mui/joy";
 
 import {
diff --git a/employee-portal/src/lib/shared/components/procedures/inbox/columns.tsx b/employee-portal/src/lib/shared/components/procedures/inbox/columns.tsx
index 31a699b091c6e8a63117dbf012a744fb4f88365a..c45534bc41c70de7a990f78de31111994a8477a4 100644
--- a/employee-portal/src/lib/shared/components/procedures/inbox/columns.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/inbox/columns.tsx
@@ -5,8 +5,8 @@
 
 "use client";
 
-import { ApiInboxProcedure } from "@eshg/employee-portal-api/businessProcedures";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiInboxProcedure } from "@eshg/lib-procedures-api";
 import { createColumnHelper } from "@tanstack/react-table";
 import { isDefined } from "remeda";
 
diff --git a/employee-portal/src/lib/shared/components/procedures/inbox/constants.ts b/employee-portal/src/lib/shared/components/procedures/inbox/constants.ts
index d74daa5df0f306fcfaf765a3c2e1d91d434cce7b..f7256aadea4fb367db6b74b39a12a1231c22c935 100644
--- a/employee-portal/src/lib/shared/components/procedures/inbox/constants.ts
+++ b/employee-portal/src/lib/shared/components/procedures/inbox/constants.ts
@@ -8,7 +8,7 @@ import {
   ApiInboxProcedureStatus,
   ApiInboxProgressEntryType,
   ApiTitle,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 import { ChipProps } from "@mui/joy/Chip";
 
 export const statusNames = {
diff --git a/employee-portal/src/lib/shared/components/procedures/inbox/mutations/useCloseInboxProcedureStatusTemplate.ts b/employee-portal/src/lib/shared/components/procedures/inbox/mutations/useCloseInboxProcedureStatusTemplate.ts
index cb1d8872f4bc6c5d83ade18f461d877802e3817a..26916e3973ab03cfcd86d8b940fe72641025ca35 100644
--- a/employee-portal/src/lib/shared/components/procedures/inbox/mutations/useCloseInboxProcedureStatusTemplate.ts
+++ b/employee-portal/src/lib/shared/components/procedures/inbox/mutations/useCloseInboxProcedureStatusTemplate.ts
@@ -3,12 +3,12 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiInboxProcedureStatus,
   InboxProcedureApi,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+} from "@eshg/lib-procedures-api";
 
 type UseCloseInboxProcedureResult = ReturnType<
   typeof useCloseInboxProcedureTemplate
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/EntryFile.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/EntryFile.tsx
index 576c6c0920f8244bc889d9c33d4ba5b76f0136c0..8506621f325175b3aa71c37a30bce0665b7369ea 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/EntryFile.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/EntryFile.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiInboxProgressEntryFileReference } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiInboxProgressEntryFileReference } from "@eshg/lib-procedures-api";
 import { Box } from "@mui/joy";
 import { isDefined } from "remeda";
 
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/FileCardWithActions.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/FileCardWithActions.tsx
index 7a8e21de58bf8c44d17994266e8415ddfb949a6a..af190d938d705728ba9419e08b7dace21304e243 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/FileCardWithActions.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/FileCardWithActions.tsx
@@ -5,8 +5,8 @@
 
 "use client";
 
-import { ApiAbstractFile } from "@eshg/employee-portal-api/businessProcedures";
 import { useFileDownload } from "@eshg/lib-portal/api/files/download";
+import { ApiAbstractFile } from "@eshg/lib-procedures-api";
 import DeleteIcon from "@mui/icons-material/Delete";
 import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined";
 import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/FileOrDeletionNote.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/FileOrDeletionNote.tsx
index ec99d92a3b36c1455197263f70aebeab25834459..766e67c39bfea553b544b994bd0eef89ae323dbd 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/FileOrDeletionNote.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/FileOrDeletionNote.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiInboxProgressEntryFileReference } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiInboxProgressEntryFileReference } from "@eshg/lib-procedures-api";
 import { Typography } from "@mui/joy";
 
 import { FileCardWithActions } from "./FileCardWithActions";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/ProgressEntriesContext.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/ProgressEntriesContext.tsx
index 4df1805f17defa2868f60add8ebff9a2a207f774..ceed181be45f667c2904504cfcebeacceecefabc 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/ProgressEntriesContext.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/ProgressEntriesContext.tsx
@@ -5,8 +5,8 @@
 
 "use client";
 
-import { ApiProcedureStatus } from "@eshg/employee-portal-api/businessProcedures";
 import { RequiresChildren } from "@eshg/lib-portal/types/react";
+import { ApiProcedureStatus } from "@eshg/lib-procedures-api";
 import { createContext, useContext, useState } from "react";
 
 import { useHasUserRoleCheck } from "@/lib/shared/hooks/useAccessControl";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/SortSelect.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/SortSelect.tsx
index 4dc669deda5a8fae04adf4481b88aed3c9950eb3..49b5447d0ece88bfb5f7d3d0de344721038eac93 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/SortSelect.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/SortSelect.tsx
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiProgressEntrySortOrder } from "@eshg/employee-portal-api/businessProcedures";
 import { SelectOptions } from "@eshg/lib-portal/components/formFields/SelectOptions";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
+import { ApiProgressEntrySortOrder } from "@eshg/lib-procedures-api";
 import { Select } from "@mui/joy";
 import { isDefined } from "remeda";
 
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/buildTimelineEntryProps.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/buildTimelineEntryProps.tsx
index 47f81abbf54cd85763e2231a1aa6fc4aa4d7dd7b..d150ba8cf60eac60b11c71702ac2e35b8a021a64 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/buildTimelineEntryProps.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/buildTimelineEntryProps.tsx
@@ -3,15 +3,15 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { ButtonLink } from "@eshg/lib-portal/components/buttons/ButtonLink";
+import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import {
   ApiGetProgressEntriesResponseProgressEntriesInner,
   ApiManualProgressEntry,
   ApiProcessedInboxProgressEntry,
   ApiSystemProgressEntry,
   ApiUser,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { ButtonLink } from "@eshg/lib-portal/components/buttons/ButtonLink";
-import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+} from "@eshg/lib-procedures-api";
 import CheckIcon from "@mui/icons-material/Check";
 import MailOutlinedIcon from "@mui/icons-material/MailOutlined";
 import { Sheet, Stack, Typography } from "@mui/joy";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/constants.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/constants.tsx
index 6d6b673e04e0c15b138b77399bf5584dc8176351..392457b02280a80533f11d2334933edd301df7a8 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/constants.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/constants.tsx
@@ -4,12 +4,12 @@
  */
 
 import { systemProgressEntryTypeTitles as dentalSystemProgressEntryTypeTitles } from "@eshg/dental/shared/progressEntries";
+import { FileType } from "@eshg/lib-portal/components/formFields/file/FileType";
 import {
   ApiInboxProgressEntryType,
   ApiManualProgressEntryType,
   ApiProgressEntryClass,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { FileType } from "@eshg/lib-portal/components/formFields/file/FileType";
+} from "@eshg/lib-procedures-api";
 import {
   CallOutlined,
   DescriptionOutlined,
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/helper.ts b/employee-portal/src/lib/shared/components/procedures/progress-entries/helper.ts
index 9664b83ceafcfc24b803de707676f897f3584119..55efbe8d881241fbbd0b8a56b51f0960e6d5ce93 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/helper.ts
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/helper.ts
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
 import {
   ApiManualProgressEntryType,
   ApiProgressEntry,
   ApiSystemProgressEntry,
   ApiTriggerType,
   ApiUser,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+} from "@eshg/lib-procedures-api";
 import { isDefined, isEmpty } from "remeda";
 
 import { manualProgressEntryFileTypes } from "@/lib/shared/components/procedures/progress-entries/constants";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/hooks/useHasEditRights.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/hooks/useHasEditRights.tsx
index 35c5765263f77e7484f8f3275c619d66a74de109..92ee715f78fde7acb4fba4c6793f688793a3d090 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/hooks/useHasEditRights.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/hooks/useHasEditRights.tsx
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiManualProgressEntry } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiManualProgressEntry } from "@eshg/lib-procedures-api";
 
 import { useGetSelfUser } from "@/lib/baseModule/api/queries/users";
 
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/hooks/useProgressEntriesFilterSettings.ts b/employee-portal/src/lib/shared/components/procedures/progress-entries/hooks/useProgressEntriesFilterSettings.ts
index e6fd0db1a10259275cf18e826b943c54f35fe290..77fe5d3cd10df36b7f86c377ed94fc636f987490 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/hooks/useProgressEntriesFilterSettings.ts
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/hooks/useProgressEntriesFilterSettings.ts
@@ -4,7 +4,7 @@
  */
 
 import { ApiUser } from "@eshg/base-api";
-import { ApiProgressEntryClassFromJSON } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiProgressEntryClassFromJSON } from "@eshg/lib-procedures-api";
 import { Dispatch, SetStateAction, startTransition } from "react";
 
 import { EnumFilterDefinition } from "@/lib/shared/components/filterSettings/models/EnumFilter";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/mapper.ts b/employee-portal/src/lib/shared/components/procedures/progress-entries/mapper.ts
index b44baadd9862dafa84bdae00a3de0ee1d443923e..729acfe5dbe377801dedc92252129b49d3781543 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/mapper.ts
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/mapper.ts
@@ -3,6 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
 import {
   ApiAbstractFile,
   ApiCreateManualProgressEntryRequest,
@@ -11,8 +12,7 @@ import {
   ApiManualProgressEntryType,
   ApiPatchManualProgressEntryRequest,
   ApiUpdateFileMetaDataRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
+} from "@eshg/lib-procedures-api";
 import { isDefined, isEmpty } from "remeda";
 
 import { FileCardProps } from "@/lib/shared/components/FileCard";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/approvalRequestApi.ts b/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/approvalRequestApi.ts
index 28d905326aae6215267fcb5224704395a0976302..1fd14230ce1c536027f74861eaafaf30c6d8777c 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/approvalRequestApi.ts
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/approvalRequestApi.ts
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiApprovalRequest } from "@eshg/employee-portal-api/businessProcedures";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { ApiApprovalRequest } from "@eshg/lib-procedures-api";
 import { useMutation } from "@tanstack/react-query";
 
 import { ApprovalRequestClient } from "@/lib/shared/components/procedures/progress-entries/types";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/fileApi.ts b/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/fileApi.ts
index de792b83a2517256328409f816f16891df5f5f8f..a6fc5e71d6ea5df11a9bffa96737ce28f4525b46 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/fileApi.ts
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/fileApi.ts
@@ -3,9 +3,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiCreateApprovalRequestRequest } from "@eshg/employee-portal-api/businessProcedures";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+import { ApiCreateApprovalRequestRequest } from "@eshg/lib-procedures-api";
 
 import { FileClient } from "@/lib/shared/components/procedures/progress-entries/types";
 
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/progressEntryApi.ts b/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/progressEntryApi.ts
index 7bd7fc6dd570cd0d2b85708fff54b2f912b69461..fdc43e7b8ea20dc20c844d01a31b49d836ba4564 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/progressEntryApi.ts
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/mutations/progressEntryApi.ts
@@ -3,15 +3,15 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
+import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
 import {
   ApiCreateApprovalRequestRequest,
   ApiCreateManualProgressEntryRequest,
   ApiFileMetaData,
   ApiPatchManualProgressEntryRequest,
   ApiUpdateFileMetaDataRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
-import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
+} from "@eshg/lib-procedures-api";
 import { isDefined } from "remeda";
 
 import { useProgressEntriesConfig } from "@/lib/shared/components/procedures/progress-entries/ProgressEntriesContext";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/queries/progressEntryApi.ts b/employee-portal/src/lib/shared/components/procedures/progress-entries/queries/progressEntryApi.ts
index 181e84b218dba999d8806f6f2e1940c0de3aa9eb..db44939eca1538a4a4153772135e339899021c32 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/queries/progressEntryApi.ts
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/queries/progressEntryApi.ts
@@ -4,8 +4,8 @@
  */
 
 import { ApiUserRole } from "@eshg/base-api";
-import { ApiGetProceduresSortOrder } from "@eshg/employee-portal-api/businessProcedures";
 import { type QueryKeyFactory } from "@eshg/lib-portal/api/queryKeyFactory";
+import { ApiGetProceduresSortOrder } from "@eshg/lib-procedures-api";
 import { useSuspenseQuery } from "@tanstack/react-query";
 import { useSearchParams } from "next/navigation";
 import { isDefined, reverse } from "remeda";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/CreateProgressEntrySidebar.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/CreateProgressEntrySidebar.tsx
index 8a8d91c3acca954644403e20fd6718b5eab3b7b0..5cf5c245c1848cc3001f6d69b54a4775d63cd299 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/CreateProgressEntrySidebar.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/CreateProgressEntrySidebar.tsx
@@ -5,11 +5,11 @@
 
 "use client";
 
-import { ApiManualProgressEntryType } from "@eshg/employee-portal-api/businessProcedures";
 import { SelectField } from "@eshg/lib-portal/components/formFields/SelectField";
 import { buildEnumOptions } from "@eshg/lib-portal/helpers/form";
 import { validateFile } from "@eshg/lib-portal/helpers/validators";
 import { OptionalFieldValue } from "@eshg/lib-portal/types/form";
+import { ApiManualProgressEntryType } from "@eshg/lib-procedures-api";
 import { Stack } from "@mui/joy";
 import { Formik, FormikHelpers } from "formik";
 import { isEmpty } from "remeda";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/ApprovalRequestCard.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/ApprovalRequestCard.tsx
index f83b3c4b3e0b7862bf4de5250e010db384e98a03..47c9d1fa5ae8a795442e6296a33c08d1daeee305 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/ApprovalRequestCard.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/ApprovalRequestCard.tsx
@@ -3,10 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import {
-  ApiAbstractFile,
-  ApiApprovalRequest,
-} from "@eshg/employee-portal-api/businessProcedures";
+import { ApiAbstractFile, ApiApprovalRequest } from "@eshg/lib-procedures-api";
 import {
   Box,
   Button,
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/FileAsApprovalRequestEntity.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/FileAsApprovalRequestEntity.tsx
index 757e73b2f2da45a6f5a9141a508d82efb37b30e1..efbaa21af0cea1ea511a86dc43117818328df516 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/FileAsApprovalRequestEntity.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/FileAsApprovalRequestEntity.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiAbstractFile } from "@eshg/employee-portal-api/businessProcedures";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiAbstractFile } from "@eshg/lib-procedures-api";
 import { Stack, Typography } from "@mui/joy";
 import { useContext } from "react";
 import { isDefined } from "remeda";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/ProgressEntryAsApprovalRequestEntity.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/ProgressEntryAsApprovalRequestEntity.tsx
index cfca8be373a64c9634c920ebfdf8b206816cffb8..dfdafc6f6329485e1806c80654616cd4464f9614 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/ProgressEntryAsApprovalRequestEntity.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/approvalRequestOverviewSidebar/ProgressEntryAsApprovalRequestEntity.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiManualProgressEntry } from "@eshg/employee-portal-api/businessProcedures";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiManualProgressEntry } from "@eshg/lib-procedures-api";
 import { Stack, Typography } from "@mui/joy";
 import { useContext } from "react";
 import { isDefined } from "remeda";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/DetailsContentWrapper.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/DetailsContentWrapper.tsx
index eb88d27c65be50a7d372e5633e92d62fc13bc4cd..23371663703fb7256d533d96af4f025a3d918447 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/DetailsContentWrapper.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/DetailsContentWrapper.tsx
@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
 import {
   ApiGetFile200Response,
   ApiGetProgressEntryResponseRelatedKeyDocumentProgressEntriesInner,
   ApiInboxProgressEntryFileReference,
   ApiMail,
   ApiProgressEntry,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+} from "@eshg/lib-procedures-api";
 import DateRangeOutlinedIcon from "@mui/icons-material/DateRangeOutlined";
 import PersonOutlineIcon from "@mui/icons-material/PersonOutline";
 import WarningAmberOutlinedIcon from "@mui/icons-material/WarningAmberOutlined";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/DetailsHistory.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/DetailsHistory.tsx
index f37ef0258309972929e2cf9b66d6cebe8c07ac50..91d965c729641301e285ef5a73558f91a64a2df5 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/DetailsHistory.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/DetailsHistory.tsx
@@ -3,8 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiManualProgressEntry } from "@eshg/employee-portal-api/businessProcedures";
 import { formatDateTime } from "@eshg/lib-portal/formatters/dateTime";
+import { ApiManualProgressEntry } from "@eshg/lib-procedures-api";
 import {
   Button,
   Chip,
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/InboxProgressEntryDetails.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/InboxProgressEntryDetails.tsx
index 222394ee24fe2c5bad12e6962f9efe5eb4acbd2d..ea21426e49644d17e07a2c67d7aa5ed4acb66aa3 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/InboxProgressEntryDetails.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/InboxProgressEntryDetails.tsx
@@ -6,7 +6,7 @@
 import {
   ApiProcessedInboxProgressEntry,
   ApiUser,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 import { isDefined } from "remeda";
 
 import { inboxProgressEntryTitles } from "@/lib/shared/components/procedures/progress-entries/constants";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/ManualProgressEntryDetails.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/ManualProgressEntryDetails.tsx
index 1cf09dc0b443ebae1c80fc5e3d8c86e20697880c..55f089881903437427ffe03e73c47e836e927b41 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/ManualProgressEntryDetails.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/ManualProgressEntryDetails.tsx
@@ -3,12 +3,12 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
+import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
 import {
   ApiGetProgressEntryResponseRelatedKeyDocumentProgressEntriesInner,
   ApiManualProgressEntry,
   ApiUser,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { SubmitButton } from "@eshg/lib-portal/components/buttons/SubmitButton";
+} from "@eshg/lib-procedures-api";
 import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
 import { Button, Chip } from "@mui/joy";
 import { Formik } from "formik";
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/SystemProgressEntryDetails.tsx b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/SystemProgressEntryDetails.tsx
index 596cce0b1786b2faaf238b1f84e573197bba712e..678e744148cc50ae32169cdda09162546923a7ab 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/SystemProgressEntryDetails.tsx
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/sidebars/progressEntryDetailsSidebar/SystemProgressEntryDetails.tsx
@@ -7,7 +7,7 @@ import {
   ApiGetProgressEntryResponseRelatedKeyDocumentProgressEntriesInner,
   ApiSystemProgressEntry,
   ApiUser,
-} from "@eshg/employee-portal-api/businessProcedures";
+} from "@eshg/lib-procedures-api";
 import { Chip } from "@mui/joy";
 import { isDefined } from "remeda";
 
diff --git a/employee-portal/src/lib/shared/components/procedures/progress-entries/types.ts b/employee-portal/src/lib/shared/components/procedures/progress-entries/types.ts
index d4c2cbb9e73cb6f9fad1c44a3d178fa5561ae589..2802af95f0fe80dcab1cab9ee9cae686a454458e 100644
--- a/employee-portal/src/lib/shared/components/procedures/progress-entries/types.ts
+++ b/employee-portal/src/lib/shared/components/procedures/progress-entries/types.ts
@@ -6,6 +6,8 @@
 "use server";
 
 import { ApiUserRole } from "@eshg/base-api";
+import { QueryKeyFactory } from "@eshg/lib-portal/api/queryKeyFactory";
+import { SearchParams } from "@eshg/lib-portal/helpers/searchParams";
 import {
   ApiGetDetailedProcedureResponse,
   ApiGetProcedureApprovalRequestsResponse,
@@ -17,9 +19,7 @@ import {
   GetProgressEntriesRequest,
   ProcedureApi,
   ProgressEntryApi,
-} from "@eshg/employee-portal-api/businessProcedures";
-import { QueryKeyFactory } from "@eshg/lib-portal/api/queryKeyFactory";
-import { SearchParams } from "@eshg/lib-portal/helpers/searchParams";
+} from "@eshg/lib-procedures-api";
 
 import { UseFilterSettings } from "@/lib/shared/components/filterSettings/useFilterSettings";
 
diff --git a/employee-portal/src/lib/shared/components/table/TableSheet.tsx b/employee-portal/src/lib/shared/components/table/TableSheet.tsx
index b8114b28259c4d6c69bbca21a3227389ebef6f31..3700197acb05614e7b3482a9d19f314e4bb58a45 100644
--- a/employee-portal/src/lib/shared/components/table/TableSheet.tsx
+++ b/employee-portal/src/lib/shared/components/table/TableSheet.tsx
@@ -22,11 +22,12 @@ export interface TableSheetProps extends RequiresChildren {
   hideTable?: boolean;
   title?: ReactNode;
   footer?: ReactNode;
+  "aria-label"?: string;
 }
 
 export function TableSheet(props: TableSheetProps): ReactElement {
   return (
-    <StyledSheet>
+    <StyledSheet aria-label={props["aria-label"]}>
       <Stack flex={1} overflow="auto">
         {props.title}
         {props.hideTable ? <Box flex={1} overflow="auto" /> : props.children}
diff --git a/employee-portal/src/lib/shared/components/users/userFormatter.ts b/employee-portal/src/lib/shared/components/users/userFormatter.ts
index bf06605d2cc7288daf5fdfba4b1d4e555478d2e5..f50ed4a1736a9b6e95d1f6c9c6d5f70ee8f640f5 100644
--- a/employee-portal/src/lib/shared/components/users/userFormatter.ts
+++ b/employee-portal/src/lib/shared/components/users/userFormatter.ts
@@ -3,12 +3,16 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiUser } from "@eshg/base-api";
 import { formatPersonName } from "@eshg/lib-portal/formatters/person";
 import { isNonNullish } from "remeda";
 
 export const unknownUser = "Unbekannter Benutzer";
 
-export function fullName(user: ApiUser | undefined) {
+interface NamedUser {
+  firstName: string;
+  lastName: string;
+}
+
+export function fullName(user: NamedUser | undefined) {
   return isNonNullish(user) ? formatPersonName(user) : unknownUser;
 }
diff --git a/employee-portal/src/lib/shared/helpers/facilityUtils.ts b/employee-portal/src/lib/shared/helpers/facilityUtils.ts
index a7e19ba00b173f724d920b8526bf1f5e37fa921c..79847945ae2a1d9da21b914ba7f3dd736d2f42a1 100644
--- a/employee-portal/src/lib/shared/helpers/facilityUtils.ts
+++ b/employee-portal/src/lib/shared/helpers/facilityUtils.ts
@@ -8,7 +8,7 @@ import {
   ApiAddFacilityFileStateResponse,
   ApiFacilityContactPerson,
 } from "@eshg/base-api";
-import { ApiDataOrigin } from "@eshg/employee-portal-api/inspection";
+import { ApiDataOrigin } from "@eshg/inspection-api";
 import { mapOptionalValue } from "@eshg/lib-portal/helpers/form";
 import { isNullish } from "remeda";
 
diff --git a/employee-portal/src/lib/shared/helpers/guards.ts b/employee-portal/src/lib/shared/helpers/guards.ts
index 008390a30d022372621749baedcfaac4ce7eba48..e18189c475eec16f8ca60a9725984d1453c00064 100644
--- a/employee-portal/src/lib/shared/helpers/guards.ts
+++ b/employee-portal/src/lib/shared/helpers/guards.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiBusinessModule } from "@eshg/employee-portal-api/businessProcedures";
+import { ApiBusinessModule } from "@eshg/lib-procedures-api";
 
 export function isInteger(value: unknown): value is number {
   return Number.isInteger(value);
diff --git a/employee-portal/src/lib/shared/hooks/searchParams/useSearchParam.ts b/employee-portal/src/lib/shared/hooks/searchParams/useSearchParam.ts
index 03151082e7686a0d3a7aa80192d00ce92d3d0e14..e94ee3a747221f35ad0c0743d4c9752b40cf652e 100644
--- a/employee-portal/src/lib/shared/hooks/searchParams/useSearchParam.ts
+++ b/employee-portal/src/lib/shared/hooks/searchParams/useSearchParam.ts
@@ -33,12 +33,13 @@ export function useSearchParam<K extends BooleanNumberStringNames>(
   });
   let value = arrayParam[0];
   if (castTo === "boolean") {
-    value = !!value as NonNullable<BooleanNumberStringType<K>>;
+    value = (value != null) as NonNullable<BooleanNumberStringType<K>>;
   }
-  return [
-    (value ?? null) as BooleanNumberStringType<K>,
-    (value) => setArrayParam([value]),
-  ];
+  const setValue = useCallback(
+    (newValue: BooleanNumberStringType<K>) => setArrayParam([newValue]),
+    [setArrayParam],
+  );
+  return [(value ?? null) as BooleanNumberStringType<K>, setValue];
 }
 
 export function updateSearchParam(
@@ -106,7 +107,7 @@ export function useSearchParamArray<K extends BooleanNumberStringNames>(
     return [
       rawValues.map(
         (rawValue) =>
-          (rawValue === "true") as NonNullable<BooleanNumberStringType<K>>,
+          (rawValue !== "false") as NonNullable<BooleanNumberStringType<K>>,
       ),
       setParam,
     ];
diff --git a/employee-portal/src/serviceWorker/common/common.ts b/employee-portal/src/serviceWorker/common/common.ts
index e20a0bf8fc4b22c54bddc1fca1fbfddfe6147cfc..8320910bb85654be05a29f88f2255477643e26f4 100644
--- a/employee-portal/src/serviceWorker/common/common.ts
+++ b/employee-portal/src/serviceWorker/common/common.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiResponse } from "@eshg/employee-portal-api/inspection";
+import { ApiResponse } from "@eshg/inspection-api";
 
 export const SERVICE_WORKER_SERVER_NAME = "eshg-employee-portal-service-worker";
 
diff --git a/employee-portal/src/serviceWorker/sw/inspection/controller/getPendingFacilities.ts b/employee-portal/src/serviceWorker/sw/inspection/controller/getPendingFacilities.ts
index 060363a395fcb0b5b99373dc95c719d36cd74e24..c03864df653a93131083c5b9620a40c0a37bf9b8 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/controller/getPendingFacilities.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/controller/getPendingFacilities.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiInspPendingFacilitiesOverviewResponse } from "@eshg/employee-portal-api/inspection";
+import { ApiInspPendingFacilitiesOverviewResponse } from "@eshg/inspection-api";
 
 import { precachedInspectionIds } from "@/serviceWorker/common/precachedInspectionIds";
 import { getFacilities } from "@/serviceWorker/sw/inspection/service/getFacilities";
diff --git a/employee-portal/src/serviceWorker/sw/inspection/controller/updateChecklist.ts b/employee-portal/src/serviceWorker/sw/inspection/controller/updateChecklist.ts
index 0e026407c283d93d8297a62f675eac0e6cb29f25..888a113bf2db13b2ced48f7cdcd1736efa4bd291 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/controller/updateChecklist.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/controller/updateChecklist.ts
@@ -6,7 +6,7 @@
 import {
   ApiUpdateChecklistRequestFromJSON,
   ApiUpdateChecklistResponseToJSON,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { API_INSPECTION_CHECKLISTS_CHECKLIST_PATH_PATTERN } from "@/serviceWorker/sw/config";
 import { updateChecklist } from "@/serviceWorker/sw/inspection/service/updateChecklist";
diff --git a/employee-portal/src/serviceWorker/sw/inspection/controller/updateFile.ts b/employee-portal/src/serviceWorker/sw/inspection/controller/updateFile.ts
index d9683a82eb2a1a6ed0b91d60c0580d67323ad23a..b8993abd9f7faa53d62a668db6c1b453a8e2abe9 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/controller/updateFile.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/controller/updateFile.ts
@@ -7,7 +7,7 @@ import {
   ApiUpdateChecklistResponseToJSON,
   ApiUploadMediaFileRequest,
   ApiUploadMediaFileRequestFromJSON,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { API_INSPECTION_CHECKLISTS_FILE_PATH_PATTERN } from "@/serviceWorker/sw/config";
 import {
diff --git a/employee-portal/src/serviceWorker/sw/inspection/controller/updateIncidents.ts b/employee-portal/src/serviceWorker/sw/inspection/controller/updateIncidents.ts
index d3d61fb8f4535d9e33dc08c326b3e8b58b040685..1293143c19619634b044ad49faf1fb6a23cf4aee 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/controller/updateIncidents.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/controller/updateIncidents.ts
@@ -10,7 +10,7 @@ import {
   ApiInspectionIncident,
   ApiInspectionIncidentToJSON,
   ApiUpdateInspectionIncidentRequestFromJSON,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { uuidV4Re } from "@/serviceWorker/common/common";
 import { getFromApiCache, writeToApiCache } from "@/serviceWorker/sw/cache";
diff --git a/employee-portal/src/serviceWorker/sw/inspection/controller/updateInspection.ts b/employee-portal/src/serviceWorker/sw/inspection/controller/updateInspection.ts
index 264da5c5cfa176975a00368799575396f6b51dca..ae17a6bd0ab5acc089b1be12ac09f7f5bc6aa49f 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/controller/updateInspection.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/controller/updateInspection.ts
@@ -6,7 +6,7 @@
 import {
   ApiInspectionToJSON,
   ApiUpdateInspectionRequestFromJSON,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { uuidV4Re } from "@/serviceWorker/common/common";
 import { getFromApiCache, writeToApiCache } from "@/serviceWorker/sw/cache";
diff --git a/employee-portal/src/serviceWorker/sw/inspection/controller/updatePacklists.ts b/employee-portal/src/serviceWorker/sw/inspection/controller/updatePacklists.ts
index 9f43edb59485eea6d9a5224ab2b4dbae3a9fedf9..f2ae4b3532e05edaad392c71d1bdec6b7ceb47cf 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/controller/updatePacklists.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/controller/updatePacklists.ts
@@ -6,7 +6,7 @@
 import {
   ApiPacklistToJSON,
   ApiUpdatePacklistElementRequestFromJSON,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { API_INSPECTION_PACKLISTS_PACKLIST_PATH_PATTERN } from "@/serviceWorker/sw/config";
 import { updatePacklistElement } from "@/serviceWorker/sw/inspection/service/updatePacklistElement";
diff --git a/employee-portal/src/serviceWorker/sw/inspection/service/getFacilities.ts b/employee-portal/src/serviceWorker/sw/inspection/service/getFacilities.ts
index 6a0586f6e3cdda2d1f97f771503b13197f1037ed..e09b9e75197d0697faf4cc8d266558bdef69445e 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/service/getFacilities.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/service/getFacilities.ts
@@ -3,10 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import {
-  ApiInspPendingFacility,
-  ApiInspection,
-} from "@eshg/employee-portal-api/inspection";
+import { ApiInspPendingFacility, ApiInspection } from "@eshg/inspection-api";
 
 import { getInspection } from "@/serviceWorker/sw/inspection/service/updateInspection";
 
diff --git a/employee-portal/src/serviceWorker/sw/inspection/service/updateChecklist.ts b/employee-portal/src/serviceWorker/sw/inspection/service/updateChecklist.ts
index 282b86a858ccd440cf9cde51b643f9c91b4e68db..a256a6372243ebbff8ba5f78b23cbf9549a058a3 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/service/updateChecklist.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/service/updateChecklist.ts
@@ -10,7 +10,7 @@ import {
   ApiGetChecklistsResponseFromJSON,
   ApiGetChecklistsResponseToJSON,
   ApiUpdateChecklistRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { getFromApiCache, writeToApiCache } from "@/serviceWorker/sw/cache";
 import {
diff --git a/employee-portal/src/serviceWorker/sw/inspection/service/updateFile.ts b/employee-portal/src/serviceWorker/sw/inspection/service/updateFile.ts
index fb76efd03d2fc4f82befc069f6a31e0c8ec9aeed..110b37d8b8f46ecc6750fa7aef8f84f7557771cb 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/service/updateFile.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/service/updateFile.ts
@@ -10,7 +10,7 @@ import {
   ApiGetChecklistsResponseFromJSON,
   ApiGetChecklistsResponseToJSON,
   ApiUpdateChecklistElementsInner,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { X_ESHG_INSPECTION_ID, uuidV4Re } from "@/serviceWorker/common/common";
 import {
diff --git a/employee-portal/src/serviceWorker/sw/inspection/service/updateIncidents.ts b/employee-portal/src/serviceWorker/sw/inspection/service/updateIncidents.ts
index a2ef56f40d81b041902558bd0dd78cb831595113..86a59da7747815e5ebff809827e92a6b44ba455c 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/service/updateIncidents.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/service/updateIncidents.ts
@@ -8,7 +8,7 @@ import {
   ApiGetInspectionIncidentsResponseToJSON,
   ApiInspectionIncident,
   ApiUpdateInspectionIncidentRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { isDefined } from "remeda";
 
 import { getFromApiCache, writeToApiCache } from "@/serviceWorker/sw/cache";
diff --git a/employee-portal/src/serviceWorker/sw/inspection/service/updateInspection.ts b/employee-portal/src/serviceWorker/sw/inspection/service/updateInspection.ts
index 9a31b92c008b0aa40f2d43d1a98c068280befe87..f9f103554239a4b518ea1c51631e9f6901896723 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/service/updateInspection.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/service/updateInspection.ts
@@ -8,7 +8,7 @@ import {
   ApiInspectionIncident,
   ApiInspectionPhase,
   ApiInspectionToJSON,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { getFromApiCache, writeToApiCache } from "@/serviceWorker/sw/cache";
 import { API_INSPECTION_INSPECTIONS_FINALIZE_PATH_PATTERN } from "@/serviceWorker/sw/config";
diff --git a/employee-portal/src/serviceWorker/sw/inspection/service/updatePacklistElement.ts b/employee-portal/src/serviceWorker/sw/inspection/service/updatePacklistElement.ts
index 6791deb575c5ce5e20fe7c36b7ca9808e7c6fc58..6c92bbabeca9a376f508e247128f6cbb3e5f2e88 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/service/updatePacklistElement.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/service/updatePacklistElement.ts
@@ -8,7 +8,7 @@ import {
   ApiGetPacklistsResponseToJSON,
   ApiPacklist,
   ApiUpdatePacklistElementRequest,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 
 import { getFromApiCache, writeToApiCache } from "@/serviceWorker/sw/cache";
 
diff --git a/employee-portal/src/serviceWorker/sw/inspection/test/cacheMock.ts b/employee-portal/src/serviceWorker/sw/inspection/test/cacheMock.ts
index 608ac26cb4cc66721fcf15b9bd8d1c93ab4870d2..dee73dc3ad26f851f9fb5c5c800b26a54f262345 100644
--- a/employee-portal/src/serviceWorker/sw/inspection/test/cacheMock.ts
+++ b/employee-portal/src/serviceWorker/sw/inspection/test/cacheMock.ts
@@ -10,7 +10,7 @@ import {
   ApiGetChecklistsResponseToJSON,
   ApiInspection,
   ApiInspectionToJSON,
-} from "@eshg/employee-portal-api/inspection";
+} from "@eshg/inspection-api";
 import { isString } from "remeda";
 import { vi } from "vitest";
 
diff --git a/employee-portal/src/serviceWorker/sw/replaceRecursive.ts b/employee-portal/src/serviceWorker/sw/replaceRecursive.ts
index f946e83328a954ef064ba19fbd5fc7addf6a32ce..ccb242ece34ca7f1b5d730475b51dbc4cc754056 100644
--- a/employee-portal/src/serviceWorker/sw/replaceRecursive.ts
+++ b/employee-portal/src/serviceWorker/sw/replaceRecursive.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
-import { ApiUpdateChecklistElementsInner } from "@eshg/employee-portal-api/inspection";
+import { ApiUpdateChecklistElementsInner } from "@eshg/inspection-api";
 import { isArray, isPlainObject } from "remeda";
 
 // Recursively update all objects with matching id and type.
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 2c3521197d7c4586c843d1d3e9090525f1898cde..a4b76b9530d66f5e68d973ea569d8e19de379189 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index dedd5d1e69e694f9dc7b13edab8c7f2e9c377e45..d9fbee2e1d61a32b9c35e11fd9a851dd3639dda0 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-all.zip
 networkTimeout=10000
 validateDistributionUrl=true
 zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index f5feea6d6b116baaca5a2642d4d9fa1f47d574a7..f3b75f3b0d4faeb4b1c8a02b5c47007e6efb7dcd 100755
--- a/gradlew
+++ b/gradlew
@@ -86,8 +86,7 @@ done
 # shellcheck disable=SC2034
 APP_BASE_NAME=${0##*/}
 # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
-' "$PWD" ) || exit
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD=maximum
diff --git a/lib-portal/gradleDependencies.json b/lib-portal/gradleDependencies.json
index b786b4de554f64e1b4ae33ea6f127fbf60268651..890ca1a3395b9fcd515a8b18ecd48927d4f9a384 100644
--- a/lib-portal/gradleDependencies.json
+++ b/lib-portal/gradleDependencies.json
@@ -1,3 +1,3 @@
 {
-  "dependencies": [":base-api", ":employee-portal-api"]
+  "dependencies": [":base-api", ":medical-registry-api"]
 }
diff --git a/lib-portal/package.json b/lib-portal/package.json
index 24a6d73caa0b2602a13b8d55f92907ed5f6e0d5f..e2570187d4950b3f3f00ec3fad2c06f070bfc875 100644
--- a/lib-portal/package.json
+++ b/lib-portal/package.json
@@ -8,7 +8,7 @@
   },
   "dependencies": {
     "@eshg/base-api": "workspace:*",
-    "@eshg/employee-portal-api": "workspace:*",
+    "@eshg/medical-registry-api": "workspace:*",
     "@mui/icons-material": "catalog:joy",
     "@mui/joy": "catalog:joy",
     "@mui/material": "catalog:joy",
@@ -26,18 +26,18 @@
     "@eslint/compat": "catalog:eslint",
     "@eslint/eslintrc": "catalog:eslint",
     "@tanstack/eslint-plugin-query": "catalog:common",
-    "@types/react": "catalog:react",
-    "@types/react-dom": "catalog:react",
     "@trivago/prettier-plugin-sort-imports": "catalog:prettier",
     "@types/node": "catalog:common",
+    "@types/react": "catalog:react",
+    "@types/react-dom": "catalog:react",
     "@vitejs/plugin-react": "catalog:vitest",
     "@vitest/coverage-istanbul": "catalog:vitest",
     "eslint": "catalog:eslint",
-    "eslint-plugin-import": "catalog:eslint",
     "eslint-config-next": "catalog:next",
     "eslint-config-prettier": "catalog:eslint",
-    "eslint-plugin-unused-imports": "catalog:eslint",
+    "eslint-plugin-import": "catalog:eslint",
     "eslint-plugin-promise": "catalog:eslint",
+    "eslint-plugin-unused-imports": "catalog:eslint",
     "prettier": "catalog:prettier",
     "typescript": "catalog:common",
     "vite-tsconfig-paths": "catalog:vitest",
diff --git a/lib-portal/src/api/errorInterceptionMiddleware.ts b/lib-portal/src/api/errorInterceptionMiddleware.ts
index 2f445f6171d724a041a8004193de347fbbb3d927..b925e50ac0a56c7a1b78279167944a6b5e9f5a5d 100644
--- a/lib-portal/src/api/errorInterceptionMiddleware.ts
+++ b/lib-portal/src/api/errorInterceptionMiddleware.ts
@@ -5,6 +5,8 @@
 
 import { Middleware } from "@eshg/base-api";
 
+import { PortalError } from "../errorHandling/PortalError";
+import { PortalErrorCode } from "../errorHandling/PortalErrorCode";
 import { resolveErrorResponse } from "../errorHandling/errorResolvers";
 
 export const errorInterceptionMiddleware = {
@@ -18,7 +20,10 @@ export const errorInterceptionMiddleware = {
   async onError(context) {
     if (context.response === undefined) {
       const cause = resolveCause(context.error);
-      throw new Error(`Failed to fetch ${context.url}${cause}`);
+      throw new PortalError({
+        errorCode: PortalErrorCode.UnexpectedError,
+        message: `Failed to fetch ${context.url}${cause}`,
+      });
     }
     return Promise.resolve();
   },
diff --git a/lib-portal/src/api/useHandledMutation.ts b/lib-portal/src/api/useHandledMutation.ts
index 101b75c4d9880bfd4eb7bff45fcf297bc0eabd85..1b20dbd320eda39914c8a44af436d864d40e10ae 100644
--- a/lib-portal/src/api/useHandledMutation.ts
+++ b/lib-portal/src/api/useHandledMutation.ts
@@ -17,6 +17,29 @@ import {
 } from "../errorHandling/errorMappers";
 import { resolveError } from "../errorHandling/errorResolvers";
 
+interface AlertOptions {
+  /**
+   * Enables retrying the mutation from the alert after a recoverable error
+   *
+   * Use this option for mutations where the original trigger (e.g. a button)
+   * is not available anymore when an error occurs.
+   */
+  enableRetryAfterError?: boolean;
+  /**
+   * Enables closing any error alert
+   */
+  closeable?: boolean;
+}
+
+interface UseHandledMutationOptions<
+  TData = unknown,
+  TError = DefaultError,
+  TVariables = void,
+  TContext = unknown,
+> extends UseMutationOptions<TData, TError, TVariables, TContext> {
+  alertOptions?: AlertOptions;
+}
+
 /**
  * Use mutation with default error handling
  *
@@ -28,26 +51,33 @@ export function useHandledMutation<
   TError = DefaultError,
   TVariables = void,
   TContext = unknown,
->(options: UseMutationOptions<TData, TError, TVariables, TContext>) {
+>(options: UseHandledMutationOptions<TData, TError, TVariables, TContext>) {
+  const { alertOptions, ...mutationOptions } = options;
   const alert = useAlert();
 
-  return useMutation({
-    ...options,
-    onError: runBefore(options.onError, (error) => {
+  const mutation = useMutation({
+    ...mutationOptions,
+    onError: runBefore(options.onError, (error, variables) => {
       const { errorCode } = resolveError(error);
       const { title, message } = getErrorDescription(errorCode);
+      const onReset =
+        alertOptions?.enableRetryAfterError === true
+          ? () => mutation.mutate(variables)
+          : undefined;
 
       alert.error({
         title,
         message,
-        action: getErrorAction(errorCode),
-        closeable: getCloseable(errorCode),
+        action: getErrorAction(errorCode, onReset),
+        closeable: alertOptions?.closeable ?? getCloseable(errorCode),
       });
     }),
     onMutate: runBefore(options.onMutate, () => {
       alert.close();
     }),
   });
+
+  return mutation;
 }
 
 function runBefore<const TParams extends unknown[]>(
diff --git a/lib-portal/src/businessModules/medicalRegistry/api/mapper.ts b/lib-portal/src/businessModules/medicalRegistry/api/mapper.ts
index 2c6671693e7f3e17eede7bd5003d922c547d4eda..bd3e306f2fceb79dfeecdfb49334f2baa40f03bf 100644
--- a/lib-portal/src/businessModules/medicalRegistry/api/mapper.ts
+++ b/lib-portal/src/businessModules/medicalRegistry/api/mapper.ts
@@ -13,7 +13,7 @@ import {
   ApiTypeOfFullChange,
   ApiTypeOfPracticeChange,
   CreateProcedureRequest,
-} from "@eshg/employee-portal-api/medicalRegistry";
+} from "@eshg/medical-registry-api";
 import { isEmpty } from "remeda";
 
 import {
diff --git a/lib-portal/src/businessModules/medicalRegistry/constants.ts b/lib-portal/src/businessModules/medicalRegistry/constants.ts
index cc7f763b0dd7860aa46ec6d852eb1404f393d2b0..58d43a0e691fb4c6d32d3324b811e99020a8ca56 100644
--- a/lib-portal/src/businessModules/medicalRegistry/constants.ts
+++ b/lib-portal/src/businessModules/medicalRegistry/constants.ts
@@ -8,7 +8,7 @@ import {
   ApiEmploymentType,
   ApiProfessionalTitle,
   ApiTypeOfChange,
-} from "@eshg/employee-portal-api/medicalRegistry";
+} from "@eshg/medical-registry-api";
 
 export const changeTypeNames = {
   [ApiTypeOfChange.NewRegistration]: "Neuanmeldung",
diff --git a/lib-portal/src/businessModules/medicalRegistry/medicalRegistryCreateProcedureFormValues.ts b/lib-portal/src/businessModules/medicalRegistry/medicalRegistryCreateProcedureFormValues.ts
index 59d5c768d8f4ddda9d9bef46219c2861f6920fd6..02a8a19a5437d7fb36cbe44681dadf8f1abc5585 100644
--- a/lib-portal/src/businessModules/medicalRegistry/medicalRegistryCreateProcedureFormValues.ts
+++ b/lib-portal/src/businessModules/medicalRegistry/medicalRegistryCreateProcedureFormValues.ts
@@ -9,7 +9,7 @@ import {
   ApiEmploymentType,
   ApiProfessionalTitle,
   ApiTypeOfChange,
-} from "@eshg/employee-portal-api/medicalRegistry";
+} from "@eshg/medical-registry-api";
 
 import { NullableFieldValue, OptionalFieldValue } from "../../types/form";
 
diff --git a/lib-portal/src/businessModules/medicalRegistry/sections.ts b/lib-portal/src/businessModules/medicalRegistry/sections.ts
index 58b51b74bf48d41026dec583519e9bef343bf903..21541e1b58d8a6cc9ab6bedb7cda2ff3c133751e 100644
--- a/lib-portal/src/businessModules/medicalRegistry/sections.ts
+++ b/lib-portal/src/businessModules/medicalRegistry/sections.ts
@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { ApiTypeOfChange } from "@eshg/employee-portal-api/medicalRegistry";
+import { ApiTypeOfChange } from "@eshg/medical-registry-api";
 
 type Section =
   | "profession"
diff --git a/lib-portal/src/components/formFields/InputField.tsx b/lib-portal/src/components/formFields/InputField.tsx
index ea8afc09b08fa12156ec867e2ee8b4051f69bcd6..2db70a8db8d2005250c64947a32e10ea5756da6c 100644
--- a/lib-portal/src/components/formFields/InputField.tsx
+++ b/lib-portal/src/components/formFields/InputField.tsx
@@ -5,12 +5,14 @@
 
 import { Input, InputProps } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
+import { FormikErrors } from "formik";
 import {
   ChangeEvent,
   FocusEvent,
   FocusEventHandler,
   HTMLInputTypeAttribute,
   ReactNode,
+  memo,
 } from "react";
 
 import { FieldProps } from "../../types/form";
@@ -46,35 +48,75 @@ export interface InputFieldProps
 }
 
 export function InputField(props: Readonly<InputFieldProps>) {
+  const field = useBaseField<string>(props);
+
+  return (
+    <MemoizedInputField
+      {...props}
+      fieldHelperText={field.helperText}
+      fieldRequired={field.required}
+      fieldError={field.error}
+      fieldInputValue={field.input.value}
+      fieldHelpersSetValue={field.helpers.setValue}
+      fieldInputOnBlur={field.input.onBlur}
+      fieldInputOnChange={field.input.onChange}
+    />
+  );
+}
+
+interface InnerInputFieldProps extends InputFieldProps {
+  fieldHelperText?: string;
+  fieldRequired: boolean;
+  fieldError: boolean;
+  fieldInputValue: string;
+  fieldHelpersSetValue: (
+    value: string,
+    shouldValidate?: boolean,
+  ) => Promise<void | FormikErrors<string>>;
+  fieldInputOnBlur: (event: FocusEvent<HTMLInputElement>) => void;
+  fieldInputOnChange: (event: ChangeEvent<HTMLInputElement>) => void;
+}
+
+const MemoizedInputField = memo(function InnerInputField(
+  props: Readonly<InnerInputFieldProps>,
+) {
   const FieldComponent = props.component ?? BaseField;
   const InputComponent = props.input ?? Input;
-  const field = useBaseField<string>(props);
   const disabled = useIsFormDisabled() || props.disabled;
+  const {
+    fieldHelperText,
+    fieldError,
+    fieldRequired,
+    fieldHelpersSetValue,
+    fieldInputValue,
+    fieldInputOnBlur,
+    fieldInputOnChange,
+  } = props;
 
   function handleChange(event: ChangeEvent<HTMLInputElement>): void {
-    field.input.onChange(event);
+    fieldInputOnChange(event);
     props.onChange?.(event.target.value);
   }
 
   async function handleBlur(event: FocusEvent<HTMLInputElement>) {
     if (!props.untrimmedInput) {
-      const value: string | undefined = field.input.value;
+      const value: string | undefined = fieldInputValue;
       const trimmedValue = value?.trim();
       if (value !== trimmedValue) {
-        await field.helpers.setValue(trimmedValue);
+        await fieldHelpersSetValue(trimmedValue);
         event.target.value = trimmedValue;
       }
     }
-    field.input.onBlur?.(event);
+    fieldInputOnBlur?.(event);
     props.onBlur?.(event);
   }
 
   return (
     <FieldComponent
       label={props.label}
-      helperText={field.helperText}
-      required={field.required}
-      error={field.error}
+      helperText={fieldHelperText}
+      required={fieldRequired}
+      error={fieldError}
       sx={props.sx}
       fieldDecorator={props.fieldDecorator}
       disabled={disabled}
@@ -82,7 +124,7 @@ export function InputField(props: Readonly<InputFieldProps>) {
       <InputComponent
         type={props.type}
         name={props.name}
-        value={field.input.value}
+        value={fieldInputValue}
         placeholder={props.placeholder}
         onChange={handleChange}
         onFocus={props.onFocus}
@@ -108,4 +150,4 @@ export function InputField(props: Readonly<InputFieldProps>) {
       />
     </FieldComponent>
   );
-}
+});
diff --git a/lib-portal/src/components/formFields/SelectField.tsx b/lib-portal/src/components/formFields/SelectField.tsx
index 16e171312451bc9f25f9bee0ec2ce2aab49340ab..1ff9b18dd6adc664b8e963a9547fb79b606b6f38 100644
--- a/lib-portal/src/components/formFields/SelectField.tsx
+++ b/lib-portal/src/components/formFields/SelectField.tsx
@@ -5,7 +5,15 @@
 
 import { Select, SelectProps } from "@mui/joy";
 import { SxProps } from "@mui/joy/styles/types";
-import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
+import { FieldHelperProps, FormikHandlers } from "formik";
+import {
+  ReactNode,
+  memo,
+  useCallback,
+  useEffect,
+  useRef,
+  useState,
+} from "react";
 import { isDefined } from "remeda";
 
 import { FieldProps } from "../../types/form";
@@ -60,9 +68,47 @@ export function SelectField<
   TMultiple extends boolean = false,
   TOptionLabel extends string | ReactNode = string,
 >(props: SelectFieldProps<TMultiple, TOptionLabel>) {
+  const field = useBaseField<SelectFieldValue<TMultiple>>(props);
+
+  return (
+    <MemoizedSelectField
+      {...props}
+      fieldHelperText={field.helperText}
+      fieldRequired={field.required}
+      fieldError={field.error}
+      fieldInputValue={field.input.value}
+      fieldHelpersSetValue={field.helpers.setValue}
+      fieldHelpersSetTouched={field.helpers.setTouched}
+      fieldInputOnBlur={field.input.onBlur}
+    />
+  );
+}
+
+interface InnerSelectFieldProps<
+  TMultiple extends boolean,
+  TOptionLabel extends string | ReactNode = string,
+> extends SelectFieldProps<TMultiple, TOptionLabel> {
+  fieldHelperText?: string;
+  fieldRequired: boolean;
+  fieldError: boolean;
+  fieldInputValue: SelectFieldValue<TMultiple>;
+  fieldHelpersSetValue: FieldHelperProps<
+    SelectFieldValue<TMultiple>
+  >["setValue"];
+  fieldHelpersSetTouched: FieldHelperProps<
+    SelectFieldValue<TMultiple>
+  >["setTouched"];
+  fieldInputOnBlur: FormikHandlers["handleBlur"];
+}
+
+const MemoizedSelectField = memo(InnerSelectField) as typeof InnerSelectField;
+
+function InnerSelectField<
+  TMultiple extends boolean = false,
+  TOptionLabel extends string | ReactNode = string,
+>(props: Readonly<InnerSelectFieldProps<TMultiple, TOptionLabel>>) {
   const FieldComponent = props.component ?? BaseField;
   const SelectComponent = props.select ?? Select;
-  const field = useBaseField<SelectFieldValue<TMultiple>>(props);
   const disabled = useIsFormDisabled() || props.disabled;
 
   const { enqueue } = usePromiseSequencer();
@@ -70,34 +116,34 @@ export function SelectField<
   return (
     <FieldComponent
       label={props.label}
-      helperText={field.helperText}
-      required={field.required}
-      error={field.error}
+      helperText={props.fieldHelperText}
+      required={props.fieldRequired}
+      error={props.fieldError}
       className={props.className}
       sx={props.sx}
       disabled={disabled}
     >
       <SelectComponent
         name={props.name}
-        value={toJoyUiSelectValue<TMultiple>(field.input.value)}
+        value={toJoyUiSelectValue<TMultiple>(props.fieldInputValue)}
         onChange={(_, newValue) => {
           const emptyValue = props.multiple ? [] : "";
           const newFieldValue = (newValue ??
             emptyValue) as SelectFieldValue<TMultiple>;
           enqueue(async () => {
-            await field.helpers.setValue(newFieldValue);
+            await props.fieldHelpersSetValue(newFieldValue);
             if (isDefined(props.onChange)) {
               props.onChange(newFieldValue);
             }
           });
         }}
         // Trigger the validation when the dropdown is closed, acting similar to a blur
-        onClose={() => enqueue(() => field.helpers.setTouched(true, true))}
+        onClose={() => enqueue(() => props.fieldHelpersSetTouched(true, true))}
         onBlur={(event) => {
           // The relatedTarget is a <li> when the dropdown is opened,
           // we don't want to trigger the blur in that case.
           if (event.relatedTarget instanceof HTMLInputElement) {
-            field.input.onBlur(event);
+            props.fieldInputOnBlur(event);
           }
         }}
         multiple={props.multiple}
diff --git a/lib-portal/src/components/formFields/appointmentPicker/AppointmentListForDate.tsx b/lib-portal/src/components/formFields/appointmentPicker/AppointmentListForDate.tsx
index b5e8b2ac691876780c1cd740fa848d21ab38b2de..a3cb2b01a62a62daf6bc94d9a20a6e481ba27638 100644
--- a/lib-portal/src/components/formFields/appointmentPicker/AppointmentListForDate.tsx
+++ b/lib-portal/src/components/formFields/appointmentPicker/AppointmentListForDate.tsx
@@ -5,6 +5,7 @@
 
 import {
   Chip,
+  ChipProps,
   Divider,
   List,
   ListItem,
@@ -73,7 +74,14 @@ export function AppointmentListForDate<T extends Appointment>({
   onAppointmentSelected,
   isAppointmentEqual = (apt1, apt2) => apt1 === apt2,
   label,
-}: AppointmentListProps<T>) {
+  slotProps,
+  getLabel = (apt) => timeForm.format(apt.start),
+}: AppointmentListProps<T> & {
+  slotProps?: {
+    chip?: Omit<ChipProps, "variant" | "color">;
+  };
+  getLabel?: (appointment: T) => string;
+}) {
   const theme = useTheme();
   const labelId = useId();
   const hasAppointments = appointments.length > 0;
@@ -88,6 +96,8 @@ export function AppointmentListForDate<T extends Appointment>({
     };
   }
 
+  const { sx: chipSx, ...otherChipProps } = slotProps?.chip ?? {};
+
   return (
     <RadioGroup>
       <Divider sx={{ my: 2 }} />
@@ -118,7 +128,9 @@ export function AppointmentListForDate<T extends Appointment>({
                   minWidth: "56px",
                   textAlign: "center",
                   paddingX: 2,
+                  ...chipSx,
                 }}
+                {...otherChipProps}
               >
                 <Radio
                   disableIcon
@@ -146,7 +158,7 @@ export function AppointmentListForDate<T extends Appointment>({
                         fontWeight: theme.fontWeight.md,
                       }}
                     >
-                      {timeForm.format(apt.start)}
+                      {getLabel(apt)}
                     </Typography>
                   }
                 />
diff --git a/lib-portal/src/components/formFields/autocomplete/SingleAutocompleteField.tsx b/lib-portal/src/components/formFields/autocomplete/SingleAutocompleteField.tsx
index e0e779418d6dd8cb0e20c33bbe5a6c6ce554df60..d4527fb9f43b0b3a630e0c8751c4f0df60c4ae39 100644
--- a/lib-portal/src/components/formFields/autocomplete/SingleAutocompleteField.tsx
+++ b/lib-portal/src/components/formFields/autocomplete/SingleAutocompleteField.tsx
@@ -20,6 +20,7 @@ export interface SingleAutocompleteFieldProps
   freeSolo?: boolean;
   disableFiltering?: boolean;
   popupIcon?: ReactNode;
+  disabled?: boolean;
 }
 
 export function SingleAutocompleteField(props: SingleAutocompleteFieldProps) {
@@ -47,7 +48,8 @@ export function SingleAutocompleteField(props: SingleAutocompleteFieldProps) {
       <Autocomplete
         {...autocompleteProps}
         multiple={false}
-        freeSolo={props.freeSolo}
+        freeSolo={true}
+        forcePopupIcon={!props.freeSolo}
         value={field.input.value}
         onChange={(_, newValue) => {
           handleChange(newValue);
@@ -55,7 +57,7 @@ export function SingleAutocompleteField(props: SingleAutocompleteFieldProps) {
         onInputChange={handleInputChange}
         options={props.options.map((opt) => opt.value)}
         filterOptions={props.disableFiltering ? identity() : undefined}
-        disabled={disabled}
+        disabled={disabled || props.disabled}
         popupIcon={props.popupIcon}
       />
     </BaseField>
diff --git a/lib-portal/src/components/navigation/InternalLinkIconButton.tsx b/lib-portal/src/components/navigation/InternalLinkIconButton.tsx
index 6680c75562a9b019c5953c03fa8458394737133a..2018b87c8f6284e1a517e901d388e89c01708405 100644
--- a/lib-portal/src/components/navigation/InternalLinkIconButton.tsx
+++ b/lib-portal/src/components/navigation/InternalLinkIconButton.tsx
@@ -4,11 +4,13 @@
  */
 
 import { IconButton, IconButtonProps } from "@mui/joy";
+import { forwardRef } from "react";
 
 import { NavigationLink } from "./NavigationLink";
 
-export function InternalLinkIconButton(
-  props: Omit<IconButtonProps<typeof NavigationLink>, "component">,
-) {
-  return <IconButton component={NavigationLink} {...props} />;
-}
+export const InternalLinkIconButton = forwardRef<
+  HTMLAnchorElement,
+  Omit<IconButtonProps<typeof NavigationLink>, "component">
+>(function InternalLinkIconButton(props, ref) {
+  return <IconButton component={NavigationLink} ref={ref} {...props} />;
+});
diff --git a/lib-portal/src/components/snackbar/SnackbarProvider.tsx b/lib-portal/src/components/snackbar/SnackbarProvider.tsx
index 1989d5c4e7138eb7fe5fe4fe7b1cfa080ae6af3e..2de6bd55308d8a1daf3fb905e1c2085c4a379fa3 100644
--- a/lib-portal/src/components/snackbar/SnackbarProvider.tsx
+++ b/lib-portal/src/components/snackbar/SnackbarProvider.tsx
@@ -149,10 +149,9 @@ function BaseSnackbar({
   );
 }
 
-const SnackbarContext = createContext<{
-  queue: SnackbarValues[];
-  setQueue: Dispatch<SetStateAction<SnackbarValues[]>>;
-}>(null!);
+const SnackbarContext = createContext<
+  Dispatch<SetStateAction<SnackbarValues[]>>
+>(null!);
 
 export function SnackbarProvider({
   children,
@@ -164,8 +163,9 @@ export function SnackbarProvider({
   closeLabel?: string;
 }>) {
   const [queue, setQueue] = useState<SnackbarValues[]>([]);
+
   return (
-    <SnackbarContext.Provider value={{ queue, setQueue }}>
+    <SnackbarContext.Provider value={setQueue}>
       <>
         {queue.map((snackbarValues, index) => (
           <BaseSnackbar
@@ -204,11 +204,10 @@ export interface Snackbar {
 }
 
 export function useSnackbar(): Snackbar {
-  const context = useContext(SnackbarContext);
-  if (context === null) {
+  const setQueue = useContext(SnackbarContext);
+  if (setQueue === null) {
     throw new Error("useSnackbar was called outside SnackbarProvider");
   }
-  const { setQueue } = context;
 
   return useMemo(() => {
     function enqueueSnackbar(snackbar: SnackbarPropsKeyOptional) {
@@ -249,7 +248,10 @@ export function useSnackbar(): Snackbar {
      */
     function close(key: string) {
       setQueue((prevQueue) =>
-        removeSnackbarFromQueue({ queue: prevQueue, key }),
+        removeSnackbarFromQueue({
+          queue: prevQueue,
+          key,
+        }),
       );
     }
 
diff --git a/lib-portal/src/helpers/validators.ts b/lib-portal/src/helpers/validators.ts
index 68d9862e2db69c384f3cca3c4816c433fe0fb778..db941e08a1b15251c5a908716e10cb97fa1d23ef 100644
--- a/lib-portal/src/helpers/validators.ts
+++ b/lib-portal/src/helpers/validators.ts
@@ -3,7 +3,18 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-import { endOfDay, isFuture, isThisMonth, isToday } from "date-fns";
+import {
+  addYears,
+  endOfDay,
+  isAfter,
+  isBefore,
+  isFuture,
+  isThisMonth,
+  isToday,
+  parseISO,
+  startOfDay,
+  subYears,
+} from "date-fns";
 import { isDefined, isEmpty, isNullish } from "remeda";
 
 import { OptionalFieldValue, Validator } from "../types/form";
@@ -116,6 +127,23 @@ export function validatePastMonthAndYear(year: number, month: number) {
   return undefined;
 }
 
+export function validateDateOfBirth(value: string) {
+  const inputDate = parseISO(value);
+
+  const today = new Date();
+  const minDate = subYears(startOfDay(today), 150);
+  const maxDate = addYears(endOfDay(today), 1);
+
+  if (isBefore(inputDate, minDate)) {
+    return "Das Geburtsdatum darf maximal 150 Jahre in der Vergangenheit liegen.";
+  }
+  if (isAfter(inputDate, maxDate)) {
+    return "Das Geburtsdatum darf maximal ein Jahr in der Zukunft liegen.";
+  }
+
+  return undefined;
+}
+
 export function validateInteger(value: OptionalFieldValue<number>) {
   if (isEmptyString(value) || isInteger(value)) {
     return undefined;
diff --git a/package.json b/package.json
index 553c5709ec189092fa0a12296e493fb20d323b6f..e2e819452daed888903362da88cc7e39ebf15009 100644
--- a/package.json
+++ b/package.json
@@ -4,13 +4,13 @@
   "type": "module",
   "private": true,
   "devDependencies": {
-    "@cyclonedx/cdxgen": "11.0.10",
+    "@cyclonedx/cdxgen": "11.1.7",
     "@eslint/compat": "catalog:eslint",
     "@eslint/eslintrc": "catalog:eslint",
     "@eslint/js": "catalog:eslint",
-    "@pnpm/lockfile.fs": "1001.1.1",
+    "@pnpm/lockfile.fs": "1001.1.2",
     "@pnpm/meta-updater": "2.0.3",
-    "@pnpm/types": "1000.1.0",
+    "@pnpm/types": "1000.1.1",
     "@tanstack/eslint-plugin-query": "catalog:common",
     "@trivago/prettier-plugin-sort-imports": "catalog:prettier",
     "@types/node": "catalog:common",
diff --git a/packages/auditlog-api/.gitignore b/packages/auditlog-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/auditlog-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/auditlog-api/build.gradle b/packages/auditlog-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..e9288fc83f3f12916c7a3ea0c156a342852b5e8d
--- /dev/null
+++ b/packages/auditlog-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('auditlog/openApi.json')
+}
diff --git a/citizen-portal-api/buildscript-gradle.lockfile b/packages/auditlog-api/buildscript-gradle.lockfile
similarity index 100%
rename from citizen-portal-api/buildscript-gradle.lockfile
rename to packages/auditlog-api/buildscript-gradle.lockfile
diff --git a/packages/auditlog-api/package.json b/packages/auditlog-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..13bd42aee89f42f46443aba294820da56a7c762c
--- /dev/null
+++ b/packages/auditlog-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/auditlog-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/auditlog-api/tsconfig.json b/packages/auditlog-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/auditlog-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/auditlog-api/tsup.config.ts b/packages/auditlog-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/auditlog-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/central-repository-api/.gitignore b/packages/central-repository-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/central-repository-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/central-repository-api/build.gradle b/packages/central-repository-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..60720b3dab4d7d8d398bf5e9b387964c842a626f
--- /dev/null
+++ b/packages/central-repository-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('central-repository/openApi.json')
+}
diff --git a/employee-portal-api/buildscript-gradle.lockfile b/packages/central-repository-api/buildscript-gradle.lockfile
similarity index 100%
rename from employee-portal-api/buildscript-gradle.lockfile
rename to packages/central-repository-api/buildscript-gradle.lockfile
diff --git a/packages/central-repository-api/package.json b/packages/central-repository-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..fbf41b0faa60b67b37e248a764405e412bbdce74
--- /dev/null
+++ b/packages/central-repository-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/central-repository-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/central-repository-api/tsconfig.json b/packages/central-repository-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/central-repository-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/central-repository-api/tsup.config.ts b/packages/central-repository-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/central-repository-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/chat-management-api/.gitignore b/packages/chat-management-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/chat-management-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/chat-management-api/build.gradle b/packages/chat-management-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..d7bc319ff81a7f7a9ad135860bd3563ad69461a9
--- /dev/null
+++ b/packages/chat-management-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('chat-management/openApi.json')
+}
diff --git a/packages/chat-management-api/buildscript-gradle.lockfile b/packages/chat-management-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/chat-management-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/chat-management-api/package.json b/packages/chat-management-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..f15ab137165539cba35544933b9f2cddc7112dcf
--- /dev/null
+++ b/packages/chat-management-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/chat-management-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/chat-management-api/tsconfig.json b/packages/chat-management-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/chat-management-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/chat-management-api/tsup.config.ts b/packages/chat-management-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/chat-management-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/dental/src/api/models/ChildExamination.ts b/packages/dental/src/api/models/ChildExamination.ts
index ac886ed991e7b3aa21893e586d2daa9413330ac6..f7b4883eb6a71c5578d240f3cac61d7390a224d5 100644
--- a/packages/dental/src/api/models/ChildExamination.ts
+++ b/packages/dental/src/api/models/ChildExamination.ts
@@ -14,6 +14,8 @@ import { ExaminationStatus, mapToExaminationStatus } from "./ExaminationStatus";
 
 export interface ChildExamination {
   readonly childId: string;
+  readonly examinationId: string;
+  readonly examinationVersion: number;
   readonly firstName: string;
   readonly lastName: string;
   readonly dateOfBirth: Date;
@@ -30,6 +32,8 @@ export function mapChildExamination(
 ): ChildExamination {
   return {
     childId: response.childId,
+    examinationId: response.examinationId,
+    examinationVersion: response.examinationVersion,
     firstName: response.firstName,
     lastName: response.lastName,
     dateOfBirth: response.dateOfBirth,
diff --git a/packages/dental/src/api/models/Examination.ts b/packages/dental/src/api/models/Examination.ts
index 851155235569d6be814d4de4439caba2f143b1dd..11345c2b425e1599dd0fe261cb892eccc67265af 100644
--- a/packages/dental/src/api/models/Examination.ts
+++ b/packages/dental/src/api/models/Examination.ts
@@ -4,27 +4,34 @@
  */
 
 import { ApiExamination, ApiProphylaxisType } from "@eshg/dental-api";
-import { BaseEntity } from "@eshg/lib-employee-portal/api/models/BaseEntity";
+import {
+  BaseEntity,
+  mapBaseEntity,
+} from "@eshg/lib-employee-portal/api/models/BaseEntity";
+import {
+  Versioned,
+  mapVersioned,
+} from "@eshg/lib-employee-portal/api/models/Versioned";
 import { mapOptional } from "@eshg/lib-employee-portal/api/models/utils";
 
 import { ExaminationResult, mapExaminationResult } from "./ExaminationResult";
 import { ExaminationStatus, mapToExaminationStatus } from "./ExaminationStatus";
 
-export interface Examination extends BaseEntity {
+export interface Examination extends BaseEntity, Versioned {
   readonly dateAndTime: Date;
   readonly prophylaxisType: ApiProphylaxisType;
   readonly screening: boolean;
   readonly fluoridation: boolean;
-  readonly fluoridationConsentGiven: boolean;
+  readonly fluoridationConsentGiven?: boolean;
   readonly note?: string;
   readonly result?: ExaminationResult;
-  readonly version: number;
   readonly status: ExaminationStatus;
 }
 
 export function mapExamination(response: ApiExamination): Examination {
   return {
-    ...response,
+    ...mapBaseEntity(response),
+    ...mapVersioned(response),
     dateAndTime: response.dateAndTime,
     prophylaxisType: response.prophylaxisType,
     screening: response.isScreening,
diff --git a/packages/dental/src/api/models/ExaminationResult.ts b/packages/dental/src/api/models/ExaminationResult.ts
index a93a629a4a72cb35cb9e55ce01921e9632ef8510..97c7680e8c770ed1275da31e1dc24a185dce7429 100644
--- a/packages/dental/src/api/models/ExaminationResult.ts
+++ b/packages/dental/src/api/models/ExaminationResult.ts
@@ -10,7 +10,11 @@ import {
   ApiOralHygieneStatus,
   ApiReasonForAbsence,
   ApiScreeningExaminationResult,
+  ApiTooth,
 } from "@eshg/dental-api";
+import { mapToObj } from "remeda";
+
+import { ToothDiagnosis, mapToothDiagnosis } from "./ToothDiagnosis";
 
 export type ExaminationResult =
   | FluoridationExaminationResult
@@ -19,18 +23,21 @@ export type ExaminationResult =
 
 export interface FluoridationExaminationResult {
   readonly type: "fluoridation";
-  readonly fluorideVarnishApplied: boolean;
+  readonly fluorideVarnishApplied?: boolean;
 }
 
 export interface ScreeningExaminationResult {
   readonly type: "screening";
   readonly oralHygieneStatus?: ApiOralHygieneStatus;
-  readonly fluorideVarnishApplied: boolean;
+  readonly fluorideVarnishApplied?: boolean;
+  readonly toothDiagnoses: ToothDiagnoses;
 }
 
+export type ToothDiagnoses = Partial<Record<ApiTooth, ToothDiagnosis>>;
+
 export interface AbsenceExaminationResult {
   readonly type: "absence";
-  readonly reasonForAbsence?: ApiReasonForAbsence;
+  readonly reasonForAbsence: ApiReasonForAbsence;
 }
 
 export function mapExaminationResult(
@@ -62,6 +69,13 @@ function mapScreeningExaminationResult(
     type: "screening",
     oralHygieneStatus: response.oralHygieneStatus,
     fluorideVarnishApplied: response.fluorideVarnishApplied,
+    toothDiagnoses: mapToObj(
+      response.toothDiagnoses,
+      (toothDiagnosisResponse) => [
+        toothDiagnosisResponse.tooth,
+        mapToothDiagnosis(toothDiagnosisResponse),
+      ],
+    ),
   };
 }
 
@@ -73,3 +87,67 @@ function mapAbsenceExaminationResult(
     reasonForAbsence: response.reasonForAbsence,
   };
 }
+
+type FieldFunctionMap<T> = {
+  [K in keyof T]-?: (value: T[K]) => boolean;
+};
+
+const screeningResultEmptinessChecks: FieldFunctionMap<ScreeningExaminationResult> =
+  {
+    type: (value) => {
+      return value === "screening";
+    },
+    oralHygieneStatus: (value) => {
+      return value === undefined;
+    },
+    fluorideVarnishApplied: (value) => {
+      return value === undefined;
+    },
+    toothDiagnoses: (value) => {
+      return Object.keys(value).length === 0;
+    },
+  };
+
+const fluoridationResultEmptinessChecks: FieldFunctionMap<FluoridationExaminationResult> =
+  {
+    type: (value) => {
+      return value === "fluoridation";
+    },
+    fluorideVarnishApplied: (value) => {
+      return value === undefined;
+    },
+  };
+
+function isEmptyResult<T extends ExaminationResult>(
+  examinationResult: T,
+  emptinessChecks: { [K in keyof T]: (val: T[K]) => boolean },
+): boolean {
+  const keys = Object.keys(examinationResult) as (keyof T)[];
+  return keys.every((key) => {
+    const isEmpty = emptinessChecks[key];
+    const value = examinationResult[key];
+    return isEmpty(value);
+  });
+}
+
+function isEmptyScreeningExaminationResult(
+  result: ScreeningExaminationResult,
+): boolean {
+  return isEmptyResult(result, screeningResultEmptinessChecks);
+}
+
+function isEmptyFluoridationExaminationResult(
+  result: FluoridationExaminationResult,
+): boolean {
+  return isEmptyResult(result, fluoridationResultEmptinessChecks);
+}
+
+export function isEmptyExaminationResult(
+  result: ScreeningExaminationResult | FluoridationExaminationResult,
+): boolean {
+  if (result.type === "screening") {
+    return isEmptyScreeningExaminationResult(result);
+  } else {
+    return isEmptyFluoridationExaminationResult(result);
+  }
+}
diff --git a/packages/dental/src/api/models/ExaminationStatus.ts b/packages/dental/src/api/models/ExaminationStatus.ts
index 4dadf8ecca1e5cb65f04ea97dfdc5b7f685e138c..862b3c0e2121d831bd4ffe75112c28661c063ce7 100644
--- a/packages/dental/src/api/models/ExaminationStatus.ts
+++ b/packages/dental/src/api/models/ExaminationStatus.ts
@@ -6,10 +6,13 @@
 import { ApiExaminationResult } from "@eshg/dental-api";
 import { isDefined } from "remeda";
 
-export type ExaminationStatus = "OPEN" | "CLOSED";
+export type ExaminationStatus = "OPEN" | "CLOSED" | "NOT_PRESENT";
 
 export function mapToExaminationStatus(
   examinationResult: ApiExaminationResult | undefined,
 ): ExaminationStatus {
+  if (examinationResult?.type === "AbsenceExaminationResult") {
+    return "NOT_PRESENT";
+  }
   return isDefined(examinationResult) ? "CLOSED" : "OPEN";
 }
diff --git a/packages/dental/src/api/models/ToothDiagnosis.ts b/packages/dental/src/api/models/ToothDiagnosis.ts
new file mode 100644
index 0000000000000000000000000000000000000000..420ce0b2a2c61bd8b00c15f4a565f83556e7f900
--- /dev/null
+++ b/packages/dental/src/api/models/ToothDiagnosis.ts
@@ -0,0 +1,27 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import {
+  ApiMainResult,
+  ApiSecondaryResult,
+  ApiTooth,
+  ApiToothDiagnosis,
+} from "@eshg/dental-api";
+
+export interface ToothDiagnosis {
+  readonly tooth: ApiTooth;
+  readonly mainResult: ApiMainResult;
+  readonly secondaryResult1?: ApiSecondaryResult;
+  readonly secondaryResult2?: ApiSecondaryResult;
+}
+
+export function mapToothDiagnosis(response: ApiToothDiagnosis): ToothDiagnosis {
+  return {
+    tooth: response.tooth,
+    mainResult: response.mainResult,
+    secondaryResult1: response.secondaryResult1,
+    secondaryResult2: response.secondaryResult2,
+  };
+}
diff --git a/packages/dental/src/api/mutations/prophylaxisSessionApi.ts b/packages/dental/src/api/mutations/prophylaxisSessionApi.ts
index 67261f4f6871f3395e5a924212d205847c0b0686..e78ba126fcbded9604114d064eb98a160f288140 100644
--- a/packages/dental/src/api/mutations/prophylaxisSessionApi.ts
+++ b/packages/dental/src/api/mutations/prophylaxisSessionApi.ts
@@ -6,7 +6,9 @@
 import {
   ApiCreateProphylaxisSessionRequest,
   ApiProphylaxisSessionDetails,
+  ApiUpdateExaminationsInBulkRequest,
   ApiUpdateProphylaxisSessionParticipantsRequest,
+  ApiUpdateProphylaxisSessionRequest,
 } from "@eshg/dental-api";
 import { useHandledMutation } from "@eshg/lib-portal/api/useHandledMutation";
 import { useSnackbar } from "@eshg/lib-portal/components/snackbar/SnackbarProvider";
@@ -28,6 +30,21 @@ export function useCreateProphylaxisSession() {
   });
 }
 
+export function useUpdateProphylaxisSession(prophylaxisSessionId: string) {
+  const { prophylaxisSessionApi } = useDentalApi();
+  const snackbar = useSnackbar();
+  return useHandledMutation({
+    mutationFn: (request: ApiUpdateProphylaxisSessionRequest) =>
+      prophylaxisSessionApi.updateProphylaxisSession(
+        prophylaxisSessionId,
+        request,
+      ),
+    onSuccess: () => {
+      snackbar.confirmation("Prophylaxe erfolgreich gespeichert.");
+    },
+  });
+}
+
 export function useDeleteProphylaxisSessionParticipantOptions(
   prophylaxisSessionId: string,
   prophylaxisSessionVersion: number,
@@ -79,3 +96,37 @@ export function useUpdateProphylaxisSessionParticipants(
     },
   });
 }
+
+interface UseUpdateProphylaxisSessionExaminationsOptions {
+  onSuccess: () => void;
+}
+
+export function useUpdateProphylaxisSessionExaminations(
+  prophylaxisSessionId: string,
+  options?: UseUpdateProphylaxisSessionExaminationsOptions,
+) {
+  const { prophylaxisSessionApi } = useDentalApi();
+  const queryClient = useQueryClient();
+  const { queryKey } = getProphylaxisSessionQuery(prophylaxisSessionApi, {
+    prophylaxisSessionId,
+  });
+  const snackbar = useSnackbar();
+
+  return useHandledMutation({
+    meta: { updatesQuery: queryKey },
+    mutationFn: (examinationUpdates: ApiUpdateExaminationsInBulkRequest[]) =>
+      prophylaxisSessionApi.updateProphylaxisSessionExaminations(
+        prophylaxisSessionId,
+        { examinationUpdates },
+      ),
+    onSuccess: (response) => {
+      queryClient.setQueryData(queryKey, response);
+      snackbar.confirmation("Untersuchungen erfolgreich gespeichert.");
+      options?.onSuccess?.();
+    },
+    alertOptions: {
+      enableRetryAfterError: true,
+      closeable: true,
+    },
+  });
+}
diff --git a/packages/inspection-api/.gitignore b/packages/inspection-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/inspection-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/inspection-api/build.gradle b/packages/inspection-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..42319de815412a803e4241a8e91f996b3194e2ee
--- /dev/null
+++ b/packages/inspection-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('inspection/openApi.json')
+}
diff --git a/packages/inspection-api/buildscript-gradle.lockfile b/packages/inspection-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/inspection-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/inspection-api/package.json b/packages/inspection-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..a60cf433fa702bd3d09c4833405c80c13c60ae42
--- /dev/null
+++ b/packages/inspection-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/inspection-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/inspection-api/tsconfig.json b/packages/inspection-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/inspection-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/inspection-api/tsup.config.ts b/packages/inspection-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/inspection-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/lib-editor-api/.gitignore b/packages/lib-editor-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/lib-editor-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/lib-editor-api/build.gradle b/packages/lib-editor-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..0eccd5262611ab42f503c75d5c378d2930920084
--- /dev/null
+++ b/packages/lib-editor-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('lib-editor/openApi.json')
+}
diff --git a/packages/lib-editor-api/buildscript-gradle.lockfile b/packages/lib-editor-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/lib-editor-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/lib-editor-api/package.json b/packages/lib-editor-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..dae8aebf915e4b6ea8daac4c89324f531cfc8f82
--- /dev/null
+++ b/packages/lib-editor-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/lib-editor-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/lib-editor-api/tsconfig.json b/packages/lib-editor-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/lib-editor-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/lib-editor-api/tsup.config.ts b/packages/lib-editor-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/lib-editor-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/lib-employee-portal/gradleDependencies.json b/packages/lib-employee-portal/gradleDependencies.json
index 5b6411646fb63f4153cbae8eb91c30d698bb3693..b88ecd1573087425e1add90d1a9180480c505f35 100644
--- a/packages/lib-employee-portal/gradleDependencies.json
+++ b/packages/lib-employee-portal/gradleDependencies.json
@@ -1,3 +1,3 @@
 {
-  "dependencies": [":base-api", ":employee-portal-api", ":lib-portal"]
+  "dependencies": [":base-api", ":lib-portal"]
 }
diff --git a/packages/lib-employee-portal/package.json b/packages/lib-employee-portal/package.json
index cb2b05c6fa475f43aa043280a0adbdd7b46889da..b09f3074a7c06e6d5edd10291f92aaf4295a6002 100644
--- a/packages/lib-employee-portal/package.json
+++ b/packages/lib-employee-portal/package.json
@@ -13,7 +13,6 @@
   },
   "dependencies": {
     "@eshg/base-api": "workspace:*",
-    "@eshg/employee-portal-api": "workspace:*",
     "@eshg/lib-portal": "workspace:*",
     "@mui/icons-material": "catalog:joy",
     "@mui/joy": "catalog:joy",
@@ -41,7 +40,7 @@
     "eslint-plugin-promise": "catalog:eslint",
     "prettier": "catalog:prettier",
     "resolve-tspaths": "catalog:common",
-    "tsup": "8.3.5",
+    "tsup": "catalog:common",
     "typescript": "catalog:common",
     "typescript-eslint": "catalog:eslint",
     "vite-tsconfig-paths": "catalog:vitest",
diff --git a/packages/lib-procedures-api/.gitignore b/packages/lib-procedures-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/lib-procedures-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/lib-procedures-api/build.gradle b/packages/lib-procedures-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..d381d3e1f1981efa373e244404c86efe95c08739
--- /dev/null
+++ b/packages/lib-procedures-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('lib-procedures/openApi.json')
+}
diff --git a/packages/lib-procedures-api/buildscript-gradle.lockfile b/packages/lib-procedures-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/lib-procedures-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/lib-procedures-api/package.json b/packages/lib-procedures-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..fbb2e9b997fdd71379e3fa5da290c69e53154e3c
--- /dev/null
+++ b/packages/lib-procedures-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/lib-procedures-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/lib-procedures-api/tsconfig.json b/packages/lib-procedures-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/lib-procedures-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/lib-procedures-api/tsup.config.ts b/packages/lib-procedures-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/lib-procedures-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/lib-statistics-api/.gitignore b/packages/lib-statistics-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/lib-statistics-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/lib-statistics-api/build.gradle b/packages/lib-statistics-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..00905a6517f564f3d8d0e77213dcc50742d349e0
--- /dev/null
+++ b/packages/lib-statistics-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('lib-statistics/openApi.json')
+}
diff --git a/packages/lib-statistics-api/buildscript-gradle.lockfile b/packages/lib-statistics-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/lib-statistics-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/lib-statistics-api/package.json b/packages/lib-statistics-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..ab2185f29ed6ea0da76fa5f7d8288cbef18418fa
--- /dev/null
+++ b/packages/lib-statistics-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/lib-statistics-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/lib-statistics-api/tsconfig.json b/packages/lib-statistics-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/lib-statistics-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/lib-statistics-api/tsup.config.ts b/packages/lib-statistics-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/lib-statistics-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/medical-registry-api/.gitignore b/packages/medical-registry-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/medical-registry-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/medical-registry-api/build.gradle b/packages/medical-registry-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..727bbb1b0527fd810e1ca43cad93928b878f62a8
--- /dev/null
+++ b/packages/medical-registry-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('medical-registry/openApi.json')
+}
diff --git a/packages/medical-registry-api/buildscript-gradle.lockfile b/packages/medical-registry-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/medical-registry-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/medical-registry-api/package.json b/packages/medical-registry-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..0e31159b7a57cb6a31ef55782ce1d96e9cb5a82b
--- /dev/null
+++ b/packages/medical-registry-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/medical-registry-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/medical-registry-api/tsconfig.json b/packages/medical-registry-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/medical-registry-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/medical-registry-api/tsup.config.ts b/packages/medical-registry-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/medical-registry-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/official-medical-service-api/.gitignore b/packages/official-medical-service-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/official-medical-service-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/official-medical-service-api/build.gradle b/packages/official-medical-service-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..3b7a3f7ad7aad283f05750a5f8b0de4805694d22
--- /dev/null
+++ b/packages/official-medical-service-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('official-medical-service/openApi.json')
+}
diff --git a/packages/official-medical-service-api/buildscript-gradle.lockfile b/packages/official-medical-service-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/official-medical-service-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/official-medical-service-api/package.json b/packages/official-medical-service-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..0680736634cd6f603fa10c53b83571df88110596
--- /dev/null
+++ b/packages/official-medical-service-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/official-medical-service-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/official-medical-service-api/tsconfig.json b/packages/official-medical-service-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/official-medical-service-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/official-medical-service-api/tsup.config.ts b/packages/official-medical-service-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/official-medical-service-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/opendata-api/.gitignore b/packages/opendata-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/opendata-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/opendata-api/build.gradle b/packages/opendata-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..42fbbd3e742d91472a26527f62e683c5e5964a44
--- /dev/null
+++ b/packages/opendata-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('opendata/openApi.json')
+}
diff --git a/packages/opendata-api/buildscript-gradle.lockfile b/packages/opendata-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/opendata-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/opendata-api/package.json b/packages/opendata-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..1bb376ef2b1bbd78447da6f2a809ce09919ccccf
--- /dev/null
+++ b/packages/opendata-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/opendata-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/opendata-api/tsconfig.json b/packages/opendata-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/opendata-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/opendata-api/tsup.config.ts b/packages/opendata-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/opendata-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/packages/sti-protection-api/.gitignore b/packages/sti-protection-api/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0edb02e4649dd135b4e29028cf8c3506ebe4a88b
--- /dev/null
+++ b/packages/sti-protection-api/.gitignore
@@ -0,0 +1,2 @@
+# Generated files
+src
diff --git a/packages/sti-protection-api/build.gradle b/packages/sti-protection-api/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..53291e82bcd039e72b262fcdb46ce7f8b37be24f
--- /dev/null
+++ b/packages/sti-protection-api/build.gradle
@@ -0,0 +1,9 @@
+plugins {
+  id 'api-package'
+}
+
+def backendDir = rootProject.layout.projectDirectory.dir('backend')
+
+apiPackage {
+  inputSpec = backendDir.file('sti-protection/openApi.json')
+}
diff --git a/packages/sti-protection-api/buildscript-gradle.lockfile b/packages/sti-protection-api/buildscript-gradle.lockfile
new file mode 100644
index 0000000000000000000000000000000000000000..0d156738b209adc7660610a8d35b7e87ebdb8211
--- /dev/null
+++ b/packages/sti-protection-api/buildscript-gradle.lockfile
@@ -0,0 +1,4 @@
+# This is a Gradle generated file for dependency locking.
+# Manual edits can break the build and are not advised.
+# This file is expected to be part of source control.
+empty=classpath
diff --git a/packages/sti-protection-api/package.json b/packages/sti-protection-api/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..b6c46b2bbadaa02364e2bc0757603bf6c1620f35
--- /dev/null
+++ b/packages/sti-protection-api/package.json
@@ -0,0 +1,10 @@
+{
+  "name": "@eshg/sti-protection-api",
+  "version": "0.0.1",
+  "type": "module",
+  "private": true,
+  "exports": {
+    "types": "./build/types/src/index.d.ts",
+    "import": "./build/lib/index.js"
+  }
+}
diff --git a/packages/sti-protection-api/tsconfig.json b/packages/sti-protection-api/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fcfda752d49cedf996e3f64e21983c486c97189
--- /dev/null
+++ b/packages/sti-protection-api/tsconfig.json
@@ -0,0 +1,3 @@
+{
+  "extends": "../../config/tsconfig.lib.json"
+}
diff --git a/packages/sti-protection-api/tsup.config.ts b/packages/sti-protection-api/tsup.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b8cbfe047847392c88d7a0ad6616cecd6c4e383
--- /dev/null
+++ b/packages/sti-protection-api/tsup.config.ts
@@ -0,0 +1,8 @@
+/**
+ * Copyright 2025 cronn GmbH
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { defineApiConfig } from "../../config/tsup.base";
+
+export default defineApiConfig;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index fc22e853f0e17b1036a8c05fdbdcd3c5c82f9e1d..3439126d9cd7ab95d1e47c941150199852db723e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9,18 +9,21 @@ settings:
 
 catalogs:
   common:
+    '@keycloak/keycloak-admin-client':
+      specifier: 26.1.0
+      version: 26.1.0
     '@tanstack/eslint-plugin-query':
-      specifier: 5.62.16
-      version: 5.62.16
+      specifier: 5.66.0
+      version: 5.66.0
     '@tanstack/react-query':
-      specifier: 5.64.1
-      version: 5.64.1
+      specifier: 5.66.0
+      version: 5.66.0
     '@tanstack/react-table':
       specifier: 8.20.6
       version: 8.20.6
     '@types/node':
-      specifier: 22.10.5
-      version: 22.10.5
+      specifier: 22.13.0
+      version: 22.13.0
     date-fns:
       specifier: 4.1.0
       version: 4.1.0
@@ -34,8 +37,8 @@ catalogs:
       specifier: 5.0.0
       version: 5.0.0
     remeda:
-      specifier: 2.19.0
-      version: 2.19.0
+      specifier: 2.20.1
+      version: 2.20.1
     resolve-tspaths:
       specifier: 0.8.23
       version: 0.8.23
@@ -43,8 +46,8 @@ catalogs:
       specifier: 0.0.1
       version: 0.0.1
     tsup:
-      specifier: 8.3.5
-      version: 8.3.5
+      specifier: 8.3.6
+      version: 8.3.6
     typescript:
       specifier: 5.7.3
       version: 5.7.3
@@ -62,20 +65,20 @@ catalogs:
       version: 5.0.3
   eslint:
     '@eslint/compat':
-      specifier: 1.2.5
-      version: 1.2.5
+      specifier: 1.2.6
+      version: 1.2.6
     '@eslint/eslintrc':
       specifier: 3.2.0
       version: 3.2.0
     '@eslint/js':
-      specifier: 9.18.0
-      version: 9.18.0
+      specifier: 9.19.0
+      version: 9.19.0
     eslint:
-      specifier: 9.18.0
-      version: 9.18.0
+      specifier: 9.19.0
+      version: 9.19.0
     eslint-config-prettier:
-      specifier: 9.1.0
-      version: 9.1.0
+      specifier: 10.0.1
+      version: 10.0.1
     eslint-plugin-import:
       specifier: 2.31.0
       version: 2.31.0
@@ -86,8 +89,8 @@ catalogs:
       specifier: 4.1.4
       version: 4.1.4
     typescript-eslint:
-      specifier: 8.19.1
-      version: 8.19.1
+      specifier: 8.22.0
+      version: 8.22.0
   fullcalendar:
     '@fullcalendar/core':
       specifier: 6.1.15
@@ -109,8 +112,8 @@ catalogs:
       version: 6.1.15
   i18next:
     i18next:
-      specifier: 24.2.1
-      version: 24.2.1
+      specifier: 24.2.2
+      version: 24.2.2
     i18next-resources-to-backend:
       specifier: 1.2.1
       version: 1.2.1
@@ -151,8 +154,8 @@ catalogs:
       version: 14.2.14
   prettier:
     '@trivago/prettier-plugin-sort-imports':
-      specifier: 5.2.1
-      version: 5.2.1
+      specifier: 5.2.2
+      version: 5.2.2
     prettier:
       specifier: 3.4.2
       version: 3.4.2
@@ -174,91 +177,91 @@ catalogs:
       specifier: 4.3.4
       version: 4.3.4
     '@vitest/coverage-istanbul':
-      specifier: 2.1.8
-      version: 2.1.8
+      specifier: 3.0.4
+      version: 3.0.4
     vite-tsconfig-paths:
       specifier: 5.1.4
       version: 5.1.4
     vitest:
-      specifier: 2.1.8
-      version: 2.1.8
+      specifier: 3.0.4
+      version: 3.0.4
 
 importers:
 
   .:
     devDependencies:
       '@cyclonedx/cdxgen':
-        specifier: 11.0.10
-        version: 11.0.10
+        specifier: 11.1.7
+        version: 11.1.7
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
       '@eslint/js':
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       '@pnpm/lockfile.fs':
-        specifier: 1001.1.1
-        version: 1001.1.1(@pnpm/logger@5.2.0)
+        specifier: 1001.1.2
+        version: 1001.1.2(@pnpm/logger@5.2.0)
       '@pnpm/meta-updater':
         specifier: 2.0.3
         version: 2.0.3
       '@pnpm/types':
-        specifier: 1000.1.0
-        version: 1000.1.0
+        specifier: 1000.1.1
+        version: 1000.1.1
       '@tanstack/eslint-plugin-query':
         specifier: catalog:common
-        version: 5.62.16(eslint@9.18.0)(typescript@5.7.3)
+        version: 5.66.0(eslint@9.19.0)(typescript@5.7.3)
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       '@vitejs/plugin-react':
         specifier: catalog:vitest
-        version: 4.3.4(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 4.3.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       '@vitest/coverage-istanbul':
         specifier: catalog:vitest
-        version: 2.1.8(vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0))
+        version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0))
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       next:
         specifier: catalog:next
-        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
       tsup:
         specifier: catalog:common
-        version: 8.3.5(postcss@8.4.38)(tsx@4.19.2)(typescript@5.7.3)
+        version: 8.3.6(postcss@8.4.38)(tsx@4.19.2)(typescript@5.7.3)
       typescript:
         specifier: catalog:common
         version: 5.7.3
       typescript-eslint:
         specifier: catalog:eslint
-        version: 8.19.1(eslint@9.18.0)(typescript@5.7.3)
+        version: 8.22.0(eslint@9.19.0)(typescript@5.7.3)
       vite-tsconfig-paths:
         specifier: catalog:vitest
-        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       vitest:
         specifier: catalog:vitest
-        version: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
+        version: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
 
   admin-portal:
     dependencies:
@@ -288,7 +291,7 @@ importers:
         version: '@mui/joy@5.0.0-beta.51(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)'
       '@tanstack/react-query':
         specifier: catalog:common
-        version: 5.64.1(react@18.3.1)
+        version: 5.66.0(react@18.3.1)
       '@tanstack/react-table':
         specifier: catalog:common
         version: 8.20.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -300,13 +303,13 @@ importers:
         version: 2.4.6(react@18.3.1)
       i18next:
         specifier: catalog:i18next
-        version: 24.2.1(typescript@5.7.3)
+        version: 24.2.2(typescript@5.7.3)
       i18next-resources-to-backend:
         specifier: catalog:i18next
         version: 1.2.1
       next:
         specifier: catalog:next
-        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       pkijs:
         specifier: 3.2.4
         version: 3.2.4
@@ -318,10 +321,10 @@ importers:
         version: 18.3.1(react@18.3.1)
       react-i18next:
         specifier: catalog:i18next
-        version: 15.4.0(i18next@24.2.1(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 15.4.0(i18next@24.2.2(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       remeda:
         specifier: catalog:common
-        version: 2.19.0
+        version: 2.20.1
       use-debounce:
         specifier: catalog:common
         version: 10.0.4(react@18.3.1)
@@ -331,7 +334,7 @@ importers:
     devDependencies:
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
@@ -340,13 +343,13 @@ importers:
         version: 14.2.14
       '@tanstack/eslint-plugin-query':
         specifier: catalog:common
-        version: 5.62.16(eslint@9.18.0)(typescript@5.7.3)
+        version: 5.66.0(eslint@9.19.0)(typescript@5.7.3)
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       '@types/react':
         specifier: catalog:react
         version: 18.3.12
@@ -355,28 +358,28 @@ importers:
         version: 18.3.1
       '@vitejs/plugin-react':
         specifier: catalog:vitest
-        version: 4.3.4(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 4.3.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       '@vitest/coverage-istanbul':
         specifier: catalog:vitest
-        version: 2.1.8(vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0))
+        version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0))
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-next:
         specifier: catalog:next
-        version: 14.2.14(eslint@9.18.0)(typescript@5.7.3)
+        version: 14.2.14(eslint@9.19.0)(typescript@5.7.3)
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
@@ -385,10 +388,10 @@ importers:
         version: 5.7.3
       vite-tsconfig-paths:
         specifier: catalog:vitest
-        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       vitest:
         specifier: catalog:vitest
-        version: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
+        version: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
 
   citizen-portal:
     dependencies:
@@ -401,15 +404,24 @@ importers:
       '@eshg/base-api':
         specifier: workspace:*
         version: link:../packages/base-api
-      '@eshg/citizen-portal-api':
-        specifier: workspace:*
-        version: link:../citizen-portal-api
       '@eshg/lib-portal':
         specifier: workspace:*
         version: link:../lib-portal
+      '@eshg/lib-procedures-api':
+        specifier: workspace:*
+        version: link:../packages/lib-procedures-api
       '@eshg/measles-protection-api':
         specifier: workspace:*
         version: link:../packages/measles-protection-api
+      '@eshg/medical-registry-api':
+        specifier: workspace:*
+        version: link:../packages/medical-registry-api
+      '@eshg/official-medical-service-api':
+        specifier: workspace:*
+        version: link:../packages/official-medical-service-api
+      '@eshg/opendata-api':
+        specifier: workspace:*
+        version: link:../packages/opendata-api
       '@eshg/school-entry-api':
         specifier: workspace:*
         version: link:../packages/school-entry-api
@@ -445,7 +457,7 @@ importers:
         version: '@mui/joy@5.0.0-beta.51(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)'
       '@tanstack/react-query':
         specifier: catalog:common
-        version: 5.64.1(react@18.3.1)
+        version: 5.66.0(react@18.3.1)
       date-fns:
         specifier: catalog:common
         version: 4.1.0
@@ -457,7 +469,7 @@ importers:
         version: 2.4.6(react@18.3.1)
       i18next:
         specifier: catalog:i18next
-        version: 24.2.1(typescript@5.7.3)
+        version: 24.2.2(typescript@5.7.3)
       i18next-resources-to-backend:
         specifier: catalog:i18next
         version: 1.2.1
@@ -466,7 +478,7 @@ importers:
         version: 1.0.0
       next:
         specifier: catalog:next
-        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       react:
         specifier: catalog:react
         version: 18.3.1
@@ -475,10 +487,10 @@ importers:
         version: 18.3.1(react@18.3.1)
       react-i18next:
         specifier: catalog:i18next
-        version: 15.4.0(i18next@24.2.1(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 15.4.0(i18next@24.2.2(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       remeda:
         specifier: catalog:common
-        version: 2.19.0
+        version: 2.20.1
       server-only:
         specifier: catalog:common
         version: 0.0.1
@@ -491,7 +503,7 @@ importers:
     devDependencies:
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
@@ -500,10 +512,10 @@ importers:
         version: 14.2.14
       '@tanstack/eslint-plugin-query':
         specifier: catalog:common
-        version: 5.62.16(eslint@9.18.0)(typescript@5.7.3)
+        version: 5.66.0(eslint@9.19.0)(typescript@5.7.3)
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/mdx':
         specifier: 2.0.13
         version: 2.0.13
@@ -512,7 +524,7 @@ importers:
         version: 0.6.3
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       '@types/react':
         specifier: catalog:react
         version: 18.3.12
@@ -521,28 +533,28 @@ importers:
         version: 18.3.1
       '@vitejs/plugin-react':
         specifier: catalog:vitest
-        version: 4.3.4(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 4.3.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       '@vitest/coverage-istanbul':
         specifier: catalog:vitest
-        version: 2.1.8(vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0))
+        version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0))
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-next:
         specifier: catalog:next
-        version: 14.2.14(eslint@9.18.0)(typescript@5.7.3)
+        version: 14.2.14(eslint@9.19.0)(typescript@5.7.3)
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
@@ -551,36 +563,49 @@ importers:
         version: 5.7.3
       vite-tsconfig-paths:
         specifier: catalog:vitest
-        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       vitest:
         specifier: catalog:vitest
-        version: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
-
-  citizen-portal-api: {}
+        version: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
 
   e2e:
     devDependencies:
       '@axe-core/playwright':
         specifier: 4.10.1
-        version: 4.10.1(playwright-core@1.49.1)
+        version: 4.10.1(playwright-core@1.50.1)
+      '@eshg/auditlog-api':
+        specifier: workspace:*
+        version: link:../packages/auditlog-api
       '@eshg/base-api':
         specifier: workspace:*
         version: link:../packages/base-api
-      '@eshg/citizen-portal-api':
+      '@eshg/central-repository-api':
+        specifier: workspace:*
+        version: link:../packages/central-repository-api
+      '@eshg/chat-management-api':
         specifier: workspace:*
-        version: link:../citizen-portal-api
+        version: link:../packages/chat-management-api
       '@eshg/dental-api':
         specifier: workspace:*
         version: link:../packages/dental-api
-      '@eshg/e2e-api':
+      '@eshg/inspection-api':
         specifier: workspace:*
-        version: link:../e2e-api
-      '@eshg/employee-portal-api':
+        version: link:../packages/inspection-api
+      '@eshg/lib-procedures-api':
         specifier: workspace:*
-        version: link:../employee-portal-api
+        version: link:../packages/lib-procedures-api
       '@eshg/measles-protection-api':
         specifier: workspace:*
         version: link:../packages/measles-protection-api
+      '@eshg/medical-registry-api':
+        specifier: workspace:*
+        version: link:../packages/medical-registry-api
+      '@eshg/official-medical-service-api':
+        specifier: workspace:*
+        version: link:../packages/official-medical-service-api
+      '@eshg/opendata-api':
+        specifier: workspace:*
+        version: link:../packages/opendata-api
       '@eshg/school-entry-api':
         specifier: workspace:*
         version: link:../packages/school-entry-api
@@ -590,27 +615,30 @@ importers:
       '@eshg/statistics-api':
         specifier: workspace:*
         version: link:../packages/statistics-api
+      '@eshg/sti-protection-api':
+        specifier: workspace:*
+        version: link:../packages/sti-protection-api
       '@eshg/travel-medicine-api':
         specifier: workspace:*
         version: link:../packages/travel-medicine-api
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
       '@keycloak/keycloak-admin-client':
-        specifier: 26.0.7
-        version: 26.0.7
+        specifier: catalog:common
+        version: 26.1.0
       '@playwright/test':
-        specifier: 1.49.1
-        version: 1.49.1
+        specifier: 1.50.1
+        version: 1.50.1
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       axe-core:
         specifier: 4.10.2
         version: 4.10.2
@@ -622,25 +650,25 @@ importers:
         version: 4.1.0
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
       remeda:
         specifier: catalog:common
-        version: 2.19.0
+        version: 2.20.1
       tsx:
         specifier: 4.19.2
         version: 4.19.2
@@ -652,51 +680,76 @@ importers:
         version: 11.0.5
       vite-tsconfig-paths:
         specifier: catalog:vitest
-        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       vitest:
         specifier: catalog:vitest
-        version: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
-
-  e2e-api: {}
+        version: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
 
   employee-portal:
     dependencies:
       '@ducanh2912/next-pwa':
         specifier: 10.2.9
-        version: 10.2.9(@types/babel__core@7.20.5)(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.92.1)
+        version: 10.2.9(@types/babel__core@7.20.5)(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.92.1)
       '@emotion/react':
         specifier: catalog:joy
         version: 11.14.0(@types/react@18.3.12)(react@18.3.1)
       '@emotion/styled':
         specifier: catalog:joy
         version: 11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
+      '@eshg/auditlog-api':
+        specifier: workspace:*
+        version: link:../packages/auditlog-api
       '@eshg/base-api':
         specifier: workspace:*
         version: link:../packages/base-api
+      '@eshg/chat-management-api':
+        specifier: workspace:*
+        version: link:../packages/chat-management-api
       '@eshg/dental':
         specifier: workspace:*
         version: link:../packages/dental
       '@eshg/dental-api':
         specifier: workspace:*
         version: link:../packages/dental-api
-      '@eshg/employee-portal-api':
+      '@eshg/inspection-api':
         specifier: workspace:*
-        version: link:../employee-portal-api
+        version: link:../packages/inspection-api
+      '@eshg/lib-editor-api':
+        specifier: workspace:*
+        version: link:../packages/lib-editor-api
       '@eshg/lib-employee-portal':
         specifier: workspace:*
         version: link:../packages/lib-employee-portal
       '@eshg/lib-portal':
         specifier: workspace:*
         version: link:../lib-portal
+      '@eshg/lib-procedures-api':
+        specifier: workspace:*
+        version: link:../packages/lib-procedures-api
+      '@eshg/lib-statistics-api':
+        specifier: workspace:*
+        version: link:../packages/lib-statistics-api
       '@eshg/measles-protection-api':
         specifier: workspace:*
         version: link:../packages/measles-protection-api
+      '@eshg/medical-registry-api':
+        specifier: workspace:*
+        version: link:../packages/medical-registry-api
+      '@eshg/official-medical-service-api':
+        specifier: workspace:*
+        version: link:../packages/official-medical-service-api
+      '@eshg/opendata-api':
+        specifier: workspace:*
+        version: link:../packages/opendata-api
       '@eshg/school-entry-api':
         specifier: workspace:*
         version: link:../packages/school-entry-api
       '@eshg/statistics-api':
         specifier: workspace:*
         version: link:../packages/statistics-api
+      '@eshg/sti-protection-api':
+        specifier: workspace:*
+        version: link:../packages/sti-protection-api
       '@eshg/travel-medicine-api':
         specifier: workspace:*
         version: link:../packages/travel-medicine-api
@@ -741,7 +794,7 @@ importers:
         version: '@mui/joy@5.0.0-beta.51(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)'
       '@tanstack/react-query':
         specifier: catalog:common
-        version: 5.64.1(react@18.3.1)
+        version: 5.66.0(react@18.3.1)
       '@tanstack/react-table':
         specifier: catalog:common
         version: 8.20.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -774,7 +827,7 @@ importers:
         version: 34.13.0
       next:
         specifier: catalog:next
-        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       react:
         specifier: catalog:react
         version: 18.3.1
@@ -789,7 +842,7 @@ importers:
         version: 5.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       remeda:
         specifier: catalog:common
-        version: 2.19.0
+        version: 2.20.1
       server-only:
         specifier: catalog:common
         version: 0.0.1
@@ -817,7 +870,7 @@ importers:
     devDependencies:
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
@@ -826,16 +879,16 @@ importers:
         version: 14.2.14
       '@tanstack/eslint-plugin-query':
         specifier: catalog:common
-        version: 5.62.16(eslint@9.18.0)(typescript@5.7.3)
+        version: 5.66.0(eslint@9.19.0)(typescript@5.7.3)
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/mdx':
         specifier: 2.0.13
         version: 2.0.13
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       '@types/react':
         specifier: catalog:react
         version: 18.3.12
@@ -847,28 +900,28 @@ importers:
         version: 4.4.12(@types/react@18.3.12)
       '@vitejs/plugin-react':
         specifier: catalog:vitest
-        version: 4.3.4(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 4.3.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       '@vitest/coverage-istanbul':
         specifier: catalog:vitest
-        version: 2.1.8(vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0))
+        version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0))
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-next:
         specifier: catalog:next
-        version: 14.2.14(eslint@9.18.0)(typescript@5.7.3)
+        version: 14.2.14(eslint@9.19.0)(typescript@5.7.3)
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
@@ -877,21 +930,19 @@ importers:
         version: 5.7.3
       vite-tsconfig-paths:
         specifier: catalog:vitest
-        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       vitest:
         specifier: catalog:vitest
-        version: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
-
-  employee-portal-api: {}
+        version: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
 
   lib-portal:
     dependencies:
       '@eshg/base-api':
         specifier: workspace:*
         version: link:../packages/base-api
-      '@eshg/employee-portal-api':
+      '@eshg/medical-registry-api':
         specifier: workspace:*
-        version: link:../employee-portal-api
+        version: link:../packages/medical-registry-api
       '@mui/icons-material':
         specifier: catalog:joy
         version: 5.16.14(@mui/joy@5.0.0-beta.51(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)
@@ -903,7 +954,7 @@ importers:
         version: '@mui/joy@5.0.0-beta.51(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)'
       '@tanstack/react-query':
         specifier: catalog:common
-        version: 5.64.1(react@18.3.1)
+        version: 5.66.0(react@18.3.1)
       date-fns:
         specifier: catalog:common
         version: 4.1.0
@@ -912,7 +963,7 @@ importers:
         version: 2.4.6(react@18.3.1)
       next:
         specifier: catalog:next
-        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       react:
         specifier: catalog:react
         version: 18.3.1
@@ -921,7 +972,7 @@ importers:
         version: 18.3.1(react@18.3.1)
       remeda:
         specifier: catalog:common
-        version: 2.19.0
+        version: 2.20.1
       uuid:
         specifier: catalog:common
         version: 11.0.5
@@ -931,19 +982,19 @@ importers:
     devDependencies:
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
       '@tanstack/eslint-plugin-query':
         specifier: catalog:common
-        version: 5.62.16(eslint@9.18.0)(typescript@5.7.3)
+        version: 5.66.0(eslint@9.19.0)(typescript@5.7.3)
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       '@types/react':
         specifier: catalog:react
         version: 18.3.12
@@ -952,28 +1003,28 @@ importers:
         version: 18.3.1
       '@vitejs/plugin-react':
         specifier: catalog:vitest
-        version: 4.3.4(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 4.3.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       '@vitest/coverage-istanbul':
         specifier: catalog:vitest
-        version: 2.1.8(vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0))
+        version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0))
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-next:
         specifier: catalog:next
-        version: 14.2.14(eslint@9.18.0)(typescript@5.7.3)
+        version: 14.2.14(eslint@9.19.0)(typescript@5.7.3)
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
@@ -982,13 +1033,19 @@ importers:
         version: 5.7.3
       vite-tsconfig-paths:
         specifier: catalog:vitest
-        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       vitest:
         specifier: catalog:vitest
-        version: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
+        version: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
+
+  packages/auditlog-api: {}
 
   packages/base-api: {}
 
+  packages/central-repository-api: {}
+
+  packages/chat-management-api: {}
+
   packages/dental:
     dependencies:
       '@eshg/base-api':
@@ -1011,35 +1068,35 @@ importers:
         version: 5.0.0-beta.51(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       '@tanstack/react-query':
         specifier: catalog:common
-        version: 5.64.1(react@18.3.1)
+        version: 5.66.0(react@18.3.1)
       formik:
         specifier: catalog:common
         version: 2.4.6(react@18.3.1)
       next:
         specifier: catalog:next
-        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       react:
         specifier: catalog:react
         version: 18.3.1
       remeda:
         specifier: catalog:common
-        version: 2.19.0
+        version: 2.20.1
     devDependencies:
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
       '@tanstack/eslint-plugin-query':
         specifier: catalog:common
-        version: 5.62.16(eslint@9.18.0)(typescript@5.7.3)
+        version: 5.66.0(eslint@9.19.0)(typescript@5.7.3)
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       '@types/react':
         specifier: catalog:react
         version: 18.3.12
@@ -1048,28 +1105,28 @@ importers:
         version: 18.3.1
       '@vitejs/plugin-react':
         specifier: catalog:vitest
-        version: 4.3.4(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 4.3.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       '@vitest/coverage-istanbul':
         specifier: catalog:vitest
-        version: 2.1.8(vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0))
+        version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0))
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-next:
         specifier: catalog:next
-        version: 14.2.14(eslint@9.18.0)(typescript@5.7.3)
+        version: 14.2.14(eslint@9.19.0)(typescript@5.7.3)
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
@@ -1078,30 +1135,31 @@ importers:
         version: 0.8.23(typescript@5.7.3)
       tsup:
         specifier: catalog:common
-        version: 8.3.5(postcss@8.4.38)(tsx@4.19.2)(typescript@5.7.3)
+        version: 8.3.6(postcss@8.4.38)(tsx@4.19.2)(typescript@5.7.3)
       typescript:
         specifier: catalog:common
         version: 5.7.3
       typescript-eslint:
         specifier: catalog:eslint
-        version: 8.19.1(eslint@9.18.0)(typescript@5.7.3)
+        version: 8.22.0(eslint@9.19.0)(typescript@5.7.3)
       vite-tsconfig-paths:
         specifier: catalog:vitest
-        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       vitest:
         specifier: catalog:vitest
-        version: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
+        version: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
 
   packages/dental-api: {}
 
+  packages/inspection-api: {}
+
+  packages/lib-editor-api: {}
+
   packages/lib-employee-portal:
     dependencies:
       '@eshg/base-api':
         specifier: workspace:*
         version: link:../base-api
-      '@eshg/employee-portal-api':
-        specifier: workspace:*
-        version: link:../../employee-portal-api
       '@eshg/lib-portal':
         specifier: workspace:*
         version: link:../../lib-portal
@@ -1113,35 +1171,35 @@ importers:
         version: 5.0.0-beta.51(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       '@tanstack/react-query':
         specifier: catalog:common
-        version: 5.64.1(react@18.3.1)
+        version: 5.66.0(react@18.3.1)
       formik:
         specifier: catalog:common
         version: 2.4.6(react@18.3.1)
       next:
         specifier: catalog:next
-        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       react:
         specifier: catalog:react
         version: 18.3.1
       remeda:
         specifier: catalog:common
-        version: 2.19.0
+        version: 2.20.1
     devDependencies:
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
       '@tanstack/eslint-plugin-query':
         specifier: catalog:common
-        version: 5.62.16(eslint@9.18.0)(typescript@5.7.3)
+        version: 5.66.0(eslint@9.19.0)(typescript@5.7.3)
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       '@types/react':
         specifier: catalog:react
         version: 18.3.12
@@ -1150,28 +1208,28 @@ importers:
         version: 18.3.1
       '@vitejs/plugin-react':
         specifier: catalog:vitest
-        version: 4.3.4(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 4.3.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       '@vitest/coverage-istanbul':
         specifier: catalog:vitest
-        version: 2.1.8(vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0))
+        version: 3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0))
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-next:
         specifier: catalog:next
-        version: 14.2.14(eslint@9.18.0)(typescript@5.7.3)
+        version: 14.2.14(eslint@9.19.0)(typescript@5.7.3)
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
@@ -1179,29 +1237,41 @@ importers:
         specifier: catalog:common
         version: 0.8.23(typescript@5.7.3)
       tsup:
-        specifier: 8.3.5
-        version: 8.3.5(postcss@8.4.38)(tsx@4.19.2)(typescript@5.7.3)
+        specifier: catalog:common
+        version: 8.3.6(postcss@8.4.38)(tsx@4.19.2)(typescript@5.7.3)
       typescript:
         specifier: catalog:common
         version: 5.7.3
       typescript-eslint:
         specifier: catalog:eslint
-        version: 8.19.1(eslint@9.18.0)(typescript@5.7.3)
+        version: 8.22.0(eslint@9.19.0)(typescript@5.7.3)
       vite-tsconfig-paths:
         specifier: catalog:vitest
-        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
+        version: 5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
       vitest:
         specifier: catalog:vitest
-        version: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
+        version: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
+
+  packages/lib-procedures-api: {}
+
+  packages/lib-statistics-api: {}
 
   packages/measles-protection-api: {}
 
+  packages/medical-registry-api: {}
+
+  packages/official-medical-service-api: {}
+
+  packages/opendata-api: {}
+
   packages/school-entry-api: {}
 
   packages/service-directory-api: {}
 
   packages/statistics-api: {}
 
+  packages/sti-protection-api: {}
+
   packages/travel-medicine-api: {}
 
   performance-test:
@@ -1209,33 +1279,39 @@ importers:
       '@eshg/base-api':
         specifier: workspace:*
         version: link:../packages/base-api
-      '@eshg/citizen-portal-api':
+      '@eshg/dental-api':
         specifier: workspace:*
-        version: link:../citizen-portal-api
-      '@eshg/employee-portal-api':
+        version: link:../packages/dental-api
+      '@eshg/inspection-api':
         specifier: workspace:*
-        version: link:../employee-portal-api
+        version: link:../packages/inspection-api
       '@eshg/measles-protection-api':
         specifier: workspace:*
         version: link:../packages/measles-protection-api
+      '@eshg/medical-registry-api':
+        specifier: workspace:*
+        version: link:../packages/medical-registry-api
       '@eshg/school-entry-api':
         specifier: workspace:*
         version: link:../packages/school-entry-api
       '@eshg/statistics-api':
         specifier: workspace:*
         version: link:../packages/statistics-api
+      '@eshg/sti-protection-api':
+        specifier: workspace:*
+        version: link:../packages/sti-protection-api
       '@eshg/travel-medicine-api':
         specifier: workspace:*
         version: link:../packages/travel-medicine-api
       '@faker-js/faker':
-        specifier: 9.3.0
-        version: 9.3.0
+        specifier: 9.4.0
+        version: 9.4.0
       '@grafana/schema':
-        specifier: 11.4.0
-        version: 11.4.0
+        specifier: 11.5.0
+        version: 11.5.0
       '@keycloak/keycloak-admin-client':
-        specifier: 26.0.7
-        version: 26.0.7
+        specifier: catalog:common
+        version: 26.1.0
       '@types/k6':
         specifier: 0.54.2
         version: 0.54.2
@@ -1251,7 +1327,7 @@ importers:
     devDependencies:
       '@eslint/compat':
         specifier: catalog:eslint
-        version: 1.2.5(eslint@9.18.0)
+        version: 1.2.6(eslint@9.19.0)
       '@eslint/eslintrc':
         specifier: catalog:eslint
         version: 3.2.0
@@ -1260,25 +1336,25 @@ importers:
         version: 2.7.0
       '@trivago/prettier-plugin-sort-imports':
         specifier: catalog:prettier
-        version: 5.2.1(prettier@3.4.2)
+        version: 5.2.2(prettier@3.4.2)
       '@types/node':
         specifier: catalog:common
-        version: 22.10.5
+        version: 22.13.0
       eslint:
         specifier: catalog:eslint
-        version: 9.18.0
+        version: 9.19.0
       eslint-config-prettier:
         specifier: catalog:eslint
-        version: 9.1.0(eslint@9.18.0)
+        version: 10.0.1(eslint@9.19.0)
       eslint-plugin-import:
         specifier: catalog:eslint
-        version: 2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       eslint-plugin-promise:
         specifier: catalog:eslint
-        version: 7.2.1(eslint@9.18.0)
+        version: 7.2.1(eslint@9.19.0)
       eslint-plugin-unused-imports:
         specifier: catalog:eslint
-        version: 4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)
+        version: 4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)
       prettier:
         specifier: catalog:prettier
         version: 3.4.2
@@ -1298,8 +1374,8 @@ packages:
     peerDependencies:
       ajv: '>=8'
 
-  '@appthreat/atom@2.0.25':
-    resolution: {integrity: sha512-JrqAtI7iDOixEDr4hqMQRjWujD6y8HQqI5LgsCX3QNyDuS2aSscYJUoHRRQKWmhjjaS77mFhH+aV8KfvAXVU5Q==}
+  '@appthreat/atom@2.1.11':
+    resolution: {integrity: sha512-ZqDQNw4Fi5eq+Yh+m9SA/KnXJnXMD8JS3VRU9KQIqQKSn7AnP95+hLfmgqb249SwCzpM5CBxHm1ToQ2H9wHMeA==}
     engines: {node: '>=16.0.0'}
     hasBin: true
 
@@ -1316,30 +1392,14 @@ packages:
     resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/compat-data@7.24.7':
-    resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==}
-    engines: {node: '>=6.9.0'}
-
-  '@babel/compat-data@7.25.8':
-    resolution: {integrity: sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/compat-data@7.26.2':
     resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/core@7.25.8':
-    resolution: {integrity: sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/core@7.26.0':
     resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/generator@7.26.2':
-    resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/generator@7.26.5':
     resolution: {integrity: sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==}
     engines: {node: '>=6.9.0'}
@@ -1352,10 +1412,6 @@ packages:
     resolution: {integrity: sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helper-compilation-targets@7.25.7':
-    resolution: {integrity: sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/helper-compilation-targets@7.25.9':
     resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==}
     engines: {node: '>=6.9.0'}
@@ -1397,12 +1453,6 @@ packages:
     resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helper-module-transforms@7.25.7':
-    resolution: {integrity: sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0
-
   '@babel/helper-module-transforms@7.26.0':
     resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
     engines: {node: '>=6.9.0'}
@@ -1413,10 +1463,6 @@ packages:
     resolution: {integrity: sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helper-plugin-utils@7.24.7':
-    resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/helper-plugin-utils@7.25.9':
     resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==}
     engines: {node: '>=6.9.0'}
@@ -1433,10 +1479,6 @@ packages:
     peerDependencies:
       '@babel/core': ^7.0.0
 
-  '@babel/helper-simple-access@7.24.7':
-    resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/helper-simple-access@7.25.7':
     resolution: {integrity: sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==}
     engines: {node: '>=6.9.0'}
@@ -1449,30 +1491,14 @@ packages:
     resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helper-string-parser@7.25.7':
-    resolution: {integrity: sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/helper-string-parser@7.25.9':
     resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helper-validator-identifier@7.25.7':
-    resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/helper-validator-identifier@7.25.9':
     resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helper-validator-option@7.24.7':
-    resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==}
-    engines: {node: '>=6.9.0'}
-
-  '@babel/helper-validator-option@7.25.7':
-    resolution: {integrity: sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/helper-validator-option@7.25.9':
     resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
     engines: {node: '>=6.9.0'}
@@ -1481,26 +1507,12 @@ packages:
     resolution: {integrity: sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helpers@7.25.7':
-    resolution: {integrity: sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==}
-    engines: {node: '>=6.9.0'}
-
   '@babel/helpers@7.26.0':
     resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/parser@7.25.8':
-    resolution: {integrity: sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==}
-    engines: {node: '>=6.0.0'}
-    hasBin: true
-
-  '@babel/parser@7.26.2':
-    resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==}
-    engines: {node: '>=6.0.0'}
-    hasBin: true
-
-  '@babel/parser@7.26.5':
-    resolution: {integrity: sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==}
+  '@babel/parser@7.26.7':
+    resolution: {integrity: sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==}
     engines: {node: '>=6.0.0'}
     hasBin: true
 
@@ -1952,24 +1964,12 @@ packages:
     resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/traverse@7.25.9':
-    resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==}
-    engines: {node: '>=6.9.0'}
-
-  '@babel/traverse@7.26.5':
-    resolution: {integrity: sha512-rkOSPOw+AXbgtwUga3U4u8RpoK9FEFWBNAlTpcnkLFjL5CT+oyHNuUUC/xx6XefEJ16r38r8Bc/lfp6rYuHeJQ==}
-    engines: {node: '>=6.9.0'}
-
-  '@babel/types@7.25.8':
-    resolution: {integrity: sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==}
+  '@babel/traverse@7.26.7':
+    resolution: {integrity: sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/types@7.26.0':
-    resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==}
-    engines: {node: '>=6.9.0'}
-
-  '@babel/types@7.26.5':
-    resolution: {integrity: sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==}
+  '@babel/types@7.26.7':
+    resolution: {integrity: sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==}
     engines: {node: '>=6.9.0'}
 
   '@bufbuild/protobuf@1.7.2':
@@ -2014,8 +2014,8 @@ packages:
     resolution: {integrity: sha512-WGXpmuokvkCblmvvPxH8tvk5bC/Jq2Zgy/RVXrYYt51uW9vtA++GmPeWpMewMfgg/jto9pJY+twnDS2l4t/bCQ==}
     cpu: [x64]
 
-  '@cyclonedx/cdxgen@11.0.10':
-    resolution: {integrity: sha512-ny+dTpwhTBdberISDBqdaZbo00BQ7izFR9XWMdEFrttz5RJruXvqaGM0xVETawCmKHXWKl+hlD+oKIV2jT4RVQ==}
+  '@cyclonedx/cdxgen@11.1.7':
+    resolution: {integrity: sha512-Eyb0v3z+7uhmcgItaXpLs+lGFGJJeY6V8wFRMj6ZYqKaDyQBXvpQieVhzQ5OAqK6mhQDa9RgA6jC20W2WEkwmQ==}
     engines: {node: '>=20'}
     hasBin: true
 
@@ -2035,9 +2035,6 @@ packages:
   '@emotion/babel-plugin@11.13.5':
     resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==}
 
-  '@emotion/cache@11.13.5':
-    resolution: {integrity: sha512-Z3xbtJ+UcK76eWkagZ1onvn/wAVb1GOMuR15s30Fm2wrMgC7jzpnO2JZXr4eujTTqoQFUrZIw/rT0c6Zzjca1g==}
-
   '@emotion/cache@11.14.0':
     resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==}
 
@@ -2531,8 +2528,8 @@ packages:
     resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
     engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
 
-  '@eslint/compat@1.2.5':
-    resolution: {integrity: sha512-5iuG/StT+7OfvhoBHPlmxkPA9om6aDUFgmD4+mWKAGsYt4vCe8rypneG03AuseyRHBmcCLXQtIH5S26tIoggLg==}
+  '@eslint/compat@1.2.6':
+    resolution: {integrity: sha512-k7HNCqApoDHM6XzT30zGoETj+D+uUcZUb+IVAJmar3u6bvHf7hhHJcWx09QHj4/a2qrKZMWU0E16tvkiAdv06Q==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     peerDependencies:
       eslint: ^9.10.0
@@ -2552,8 +2549,8 @@ packages:
     resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  '@eslint/js@9.18.0':
-    resolution: {integrity: sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==}
+  '@eslint/js@9.19.0':
+    resolution: {integrity: sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
   '@eslint/object-schema@2.1.4':
@@ -2564,8 +2561,8 @@ packages:
     resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  '@faker-js/faker@9.3.0':
-    resolution: {integrity: sha512-r0tJ3ZOkMd9xsu3VRfqlFR6cz0V/jFYRswAIpC+m/DIfAUXq7g8N7wTAlhSANySXYGKzGryfDXwtwsY8TxEIDw==}
+  '@faker-js/faker@9.4.0':
+    resolution: {integrity: sha512-85+k0AxaZSTowL0gXp8zYWDIrWclTbRPg/pm/V0dSFZ6W6D4lhcG3uuZl4zLsEKfEvs69xDbLN2cHQudwp95JA==}
     engines: {node: '>=18.0.0', npm: '>=9.0.0'}
 
   '@floating-ui/core@1.6.2':
@@ -2622,8 +2619,8 @@ packages:
   '@gar/promisify@1.1.3':
     resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==}
 
-  '@grafana/schema@11.4.0':
-    resolution: {integrity: sha512-ZcUZtVdNSuBmTjwPAgWwQ/9/ilozAXggfXye797Odp3mXU9erQX7CqV9JV3y5pyj1+KMd+khzfjxEZotsjHWIA==}
+  '@grafana/schema@11.5.0':
+    resolution: {integrity: sha512-LLyrZeTEDvggzgG+4aKELRE3fY/GVOaU+L9qnBU1jlqZTKo3KTJ5fpUswRz2D7Gxt9b6viPIXJspMtLT5yr3bA==}
 
   '@gwhitney/detect-indent@7.0.1':
     resolution: {integrity: sha512-7bQW+gkKa2kKZPeJf6+c6gFK9ARxQfn+FKy9ScTBppyKRWH2KzsmweXUoklqeEiHiNVWaeP5csIdsNq6w7QhzA==}
@@ -2714,8 +2711,8 @@ packages:
   '@jridgewell/trace-mapping@0.3.25':
     resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
 
-  '@keycloak/keycloak-admin-client@26.0.7':
-    resolution: {integrity: sha512-2vdx04sxnTQavnE7zuztyfmf1l5opG1Bi76hh3Wj02m6vR+aSiHFxlTXJFHVZtE9Emko+qgU7a5kEFC+Il+EwQ==}
+  '@keycloak/keycloak-admin-client@26.1.0':
+    resolution: {integrity: sha512-dOC64QbdYkAp8tv8rwdyerQMovV1cE58C/t8LeBGzvFYrJf+aCOA30qKXu8hNu7fRVvP8AWJ3u45X3lAZFhSYA==}
     engines: {node: '>=18'}
 
   '@matrix-org/matrix-sdk-crypto-wasm@9.1.0':
@@ -2915,10 +2912,6 @@ packages:
     resolution: {integrity: sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==}
     engines: {node: ^14.21.3 || >=16}
 
-  '@noble/hashes@1.4.0':
-    resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==}
-    engines: {node: '>= 16'}
-
   '@noble/hashes@1.6.0':
     resolution: {integrity: sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==}
     engines: {node: ^14.21.3 || >=16}
@@ -3017,8 +3010,8 @@ packages:
     resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
     engines: {node: '>=14'}
 
-  '@playwright/test@1.49.1':
-    resolution: {integrity: sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==}
+  '@playwright/test@1.50.1':
+    resolution: {integrity: sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==}
     engines: {node: '>=18'}
     hasBin: true
 
@@ -3064,8 +3057,8 @@ packages:
     resolution: {integrity: sha512-dxIXcW1F1dxIGfye2JXE7Q8WVwYB0axVzdBOkvE1WKIVR4xjB8e6k/Dkjo7DpbyfW5Vu2k21p6dyM32YLSAWoQ==}
     engines: {node: '>=18.12'}
 
-  '@pnpm/constants@1001.0.0':
-    resolution: {integrity: sha512-yg+S/e8goJoUC4CxyKAplT2fuI94G/nynshPCNkLsi69bUMim5iDMuiiiMo/LeMoOjuyfByealD3u1mqNXrl+A==}
+  '@pnpm/constants@1001.1.0':
+    resolution: {integrity: sha512-xb9dfSGi1qfUKY3r4Zy9JdC9+ZeaDxwfE7HrrGIEsBVY1hvIn6ntbR7A97z3nk44yX7vwbINNf9sizTp0WEtEw==}
     engines: {node: '>=18.12'}
 
   '@pnpm/constants@9.0.0':
@@ -3108,16 +3101,16 @@ packages:
     peerDependencies:
       '@pnpm/logger': ^5.1.0
 
-  '@pnpm/dependency-path@1000.0.1':
-    resolution: {integrity: sha512-gnOe/pRm3oyHxhuxgXNZX/vw71lcL73VeZHWKHHtNr5BmM92Q1QOLZHtxaRCNOM+heg0T073iScPuRAgVjqceg==}
+  '@pnpm/dependency-path@1000.0.2':
+    resolution: {integrity: sha512-bBwgKCKYxVtKdfrQi6gYe3IU6spJIRLKG/l2S7r8CGRTmqpGwjk7mpeQuk+IBlHMT4DxI7KomKSdIf8EE64j+w==}
     engines: {node: '>=18.12'}
 
   '@pnpm/env.system-node-version@1.0.1':
     resolution: {integrity: sha512-oRNq2uMkKye/8ujRAVbcW4qGL99E6bXP6BTjpN7o3IN1nBHuQ4uj/8g3PFJJMzw+80vH3QDMQUF41ABXJN0sRQ==}
     engines: {node: '>=18.12'}
 
-  '@pnpm/error@1000.0.1':
-    resolution: {integrity: sha512-FdDMjp9ORXK/JlxwjlNF7mRohVKx5pvM01bxsVUSLFLZ9/oMBtDceWlntUTLhvr2MwYcr69mGilTojnXEbsjQA==}
+  '@pnpm/error@1000.0.2':
+    resolution: {integrity: sha512-2SfE4FFL73rE1WVIoESbqlj4sLy5nWW4M/RVdHvCRJPjlQHa9MH7m7CVJM204lz6I+eHoB+E7rL3zmpJR5wYnQ==}
     engines: {node: '>=18.12'}
 
   '@pnpm/error@6.0.2':
@@ -3156,26 +3149,26 @@ packages:
     resolution: {integrity: sha512-tiDFwNcqeFwXi+PIImZOaPxWc4fpS6msXTua+4vHQTit7xrRoUAJSq0cHzoAzRc1XaoHrlhl4D4nvCBU7rx4Aw==}
     engines: {node: '>=18.12'}
 
-  '@pnpm/lockfile.fs@1001.1.1':
-    resolution: {integrity: sha512-fw9/Sz7VplR1cw4EPXQvLA3z56kD2u0wtb87j2TzxNOr4OviRw2vK1Wq2RD8hPAdKhHZX6AtLMXTF23AOYh6mg==}
+  '@pnpm/lockfile.fs@1001.1.2':
+    resolution: {integrity: sha512-cInUJPvKpUYQ380mGJv9rBzKaQFM41e49uZhykMMR7a/9UPRm1OwcNoqn56zMiAUG1kQqZ4Um9QCwawNM4fBbA==}
     engines: {node: '>=18.12'}
     peerDependencies:
       '@pnpm/logger': '>=5.1.0 <1001.0.0'
 
-  '@pnpm/lockfile.merger@1001.0.1':
-    resolution: {integrity: sha512-wlTc1OgccPmpw8ZwazEyGz0x9KMX01pqavXYrclLoBH4qdR56JfZH1UwFIGs+UjdZBU97Jzidimrx3PmIiCkiw==}
+  '@pnpm/lockfile.merger@1001.0.2':
+    resolution: {integrity: sha512-qq11nCoKnOBhYNIaL2n6k6Jdl+Dd0XUtTrEzO0zF6T1hI/N/XkWKRl2zdwp/RaOOfSy+H8Cd9DUs8qrVW8JYjQ==}
     engines: {node: '>=18.12'}
 
   '@pnpm/lockfile.types@1.0.3':
     resolution: {integrity: sha512-A7vUWktnhDkrIs+WmXm7AdffJVyVYJpQUEouya/DYhB+Y+tQ3BXjZ6CV0KybqLgI/8AZErgCJqFxA0GJH6QDjA==}
     engines: {node: '>=18.12'}
 
-  '@pnpm/lockfile.types@1001.0.1':
-    resolution: {integrity: sha512-S2JSDaxN7NM+GEkuC3/5czI8JvuAZgIz4voWZxVXcCubYwRusbpaaGkuQw2dCMFaI9P9vGLPTk1QXTj7vR3POg==}
+  '@pnpm/lockfile.types@1001.0.2':
+    resolution: {integrity: sha512-drx2TRYPWriUQDvFHygJ/MuacQ7BRvGvptENNX2QXAsnHx8G5ZYnF21XDc6fCkPG6f83Rw1PcHOaUHObLZbEeA==}
     engines: {node: '>=18.12'}
 
-  '@pnpm/lockfile.utils@1001.0.1':
-    resolution: {integrity: sha512-fSBeni8HAwlaYNRUfQ1jbKA9dcYxFZOq+v0fp1JEDC3QaIe9W5R14LcBDQXy9UHLxaxl/+FvuvNnUl8/cTVMeg==}
+  '@pnpm/lockfile.utils@1001.0.2':
+    resolution: {integrity: sha512-yhtvSsS8kwEbY+g+IyBHiz61pcmdyqXIH8H2DV+/iSwZJf3llQztNYk8+xVgYdzsEFyvCuYicG/dlas2IHXegg==}
     engines: {node: '>=18.12'}
 
   '@pnpm/logger@5.2.0':
@@ -3246,8 +3239,8 @@ packages:
     resolution: {integrity: sha512-+w/ZSaCEOToZtQXniZoQnxwjgs6bL8R/8S1UOl6jnXrPr70ZtgAORfZle/vXVdbqef3T63ZiX9F9uGOMCNTghA==}
     engines: {node: '>=18.12'}
 
-  '@pnpm/resolver-base@1000.1.1':
-    resolution: {integrity: sha512-bODmHt5wMgYVU9U8Js+EM1QAKxv2lD/EIa156Ilayf6YZZ4bOAQGedKJDOIltgzAM4fKKrGkiUKWdgOmQrQ+6g==}
+  '@pnpm/resolver-base@1000.1.2':
+    resolution: {integrity: sha512-kU8vG7Tt18nIwzIpu0oWejdzg5uFPKSh6mPN/wvVNQZO1T3zcQtgILs28fY8u7ONZPHKV4lcbbEFI/KDiGewFg==}
     engines: {node: '>=18.12'}
 
   '@pnpm/resolver-base@13.0.4':
@@ -3262,8 +3255,8 @@ packages:
     resolution: {integrity: sha512-BSGvYd59kPKVTUk1InekEp+TiPnJ8650/bQyiOUFSvqHi61YipcR+E4H2i3xTnk2e+GHdGbXvEtAZbQmyxb0/g==}
     engines: {node: '>=18.12'}
 
-  '@pnpm/types@1000.1.0':
-    resolution: {integrity: sha512-+F58+ZHk9vJS4NKeVIzvPGCdU9tiPs7p1egqZRBiMN6Sc55LdDUEd/ArvyuooesY1hqmapUcDsgpU2krmNFMRQ==}
+  '@pnpm/types@1000.1.1':
+    resolution: {integrity: sha512-5zrv7B+4mW/6iiYS/BrFZWbMqLHjKmaBrMcw+F8LcuMQ7p4SQX4ANoycpr1VIQpn4+xQ0ckyuadfxBttpzicbg==}
     engines: {node: '>=18.12'}
 
   '@pnpm/types@11.1.0':
@@ -3361,41 +3354,21 @@ packages:
       rollup:
         optional: true
 
-  '@rollup/rollup-android-arm-eabi@4.18.0':
-    resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==}
-    cpu: [arm]
-    os: [android]
-
   '@rollup/rollup-android-arm-eabi@4.30.1':
     resolution: {integrity: sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==}
     cpu: [arm]
     os: [android]
 
-  '@rollup/rollup-android-arm64@4.18.0':
-    resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==}
-    cpu: [arm64]
-    os: [android]
-
   '@rollup/rollup-android-arm64@4.30.1':
     resolution: {integrity: sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==}
     cpu: [arm64]
     os: [android]
 
-  '@rollup/rollup-darwin-arm64@4.18.0':
-    resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==}
-    cpu: [arm64]
-    os: [darwin]
-
   '@rollup/rollup-darwin-arm64@4.30.1':
     resolution: {integrity: sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==}
     cpu: [arm64]
     os: [darwin]
 
-  '@rollup/rollup-darwin-x64@4.18.0':
-    resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==}
-    cpu: [x64]
-    os: [darwin]
-
   '@rollup/rollup-darwin-x64@4.30.1':
     resolution: {integrity: sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==}
     cpu: [x64]
@@ -3411,41 +3384,21 @@ packages:
     cpu: [x64]
     os: [freebsd]
 
-  '@rollup/rollup-linux-arm-gnueabihf@4.18.0':
-    resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==}
-    cpu: [arm]
-    os: [linux]
-
   '@rollup/rollup-linux-arm-gnueabihf@4.30.1':
     resolution: {integrity: sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==}
     cpu: [arm]
     os: [linux]
 
-  '@rollup/rollup-linux-arm-musleabihf@4.18.0':
-    resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==}
-    cpu: [arm]
-    os: [linux]
-
   '@rollup/rollup-linux-arm-musleabihf@4.30.1':
     resolution: {integrity: sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==}
     cpu: [arm]
     os: [linux]
 
-  '@rollup/rollup-linux-arm64-gnu@4.18.0':
-    resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==}
-    cpu: [arm64]
-    os: [linux]
-
   '@rollup/rollup-linux-arm64-gnu@4.30.1':
     resolution: {integrity: sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==}
     cpu: [arm64]
     os: [linux]
 
-  '@rollup/rollup-linux-arm64-musl@4.18.0':
-    resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==}
-    cpu: [arm64]
-    os: [linux]
-
   '@rollup/rollup-linux-arm64-musl@4.30.1':
     resolution: {integrity: sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==}
     cpu: [arm64]
@@ -3456,81 +3409,41 @@ packages:
     cpu: [loong64]
     os: [linux]
 
-  '@rollup/rollup-linux-powerpc64le-gnu@4.18.0':
-    resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==}
-    cpu: [ppc64]
-    os: [linux]
-
   '@rollup/rollup-linux-powerpc64le-gnu@4.30.1':
     resolution: {integrity: sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==}
     cpu: [ppc64]
     os: [linux]
 
-  '@rollup/rollup-linux-riscv64-gnu@4.18.0':
-    resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==}
-    cpu: [riscv64]
-    os: [linux]
-
   '@rollup/rollup-linux-riscv64-gnu@4.30.1':
     resolution: {integrity: sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==}
     cpu: [riscv64]
     os: [linux]
 
-  '@rollup/rollup-linux-s390x-gnu@4.18.0':
-    resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==}
-    cpu: [s390x]
-    os: [linux]
-
   '@rollup/rollup-linux-s390x-gnu@4.30.1':
     resolution: {integrity: sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==}
     cpu: [s390x]
     os: [linux]
 
-  '@rollup/rollup-linux-x64-gnu@4.18.0':
-    resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==}
-    cpu: [x64]
-    os: [linux]
-
   '@rollup/rollup-linux-x64-gnu@4.30.1':
     resolution: {integrity: sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==}
     cpu: [x64]
     os: [linux]
 
-  '@rollup/rollup-linux-x64-musl@4.18.0':
-    resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==}
-    cpu: [x64]
-    os: [linux]
-
   '@rollup/rollup-linux-x64-musl@4.30.1':
     resolution: {integrity: sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==}
     cpu: [x64]
     os: [linux]
 
-  '@rollup/rollup-win32-arm64-msvc@4.18.0':
-    resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==}
-    cpu: [arm64]
-    os: [win32]
-
   '@rollup/rollup-win32-arm64-msvc@4.30.1':
     resolution: {integrity: sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==}
     cpu: [arm64]
     os: [win32]
 
-  '@rollup/rollup-win32-ia32-msvc@4.18.0':
-    resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==}
-    cpu: [ia32]
-    os: [win32]
-
   '@rollup/rollup-win32-ia32-msvc@4.30.1':
     resolution: {integrity: sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==}
     cpu: [ia32]
     os: [win32]
 
-  '@rollup/rollup-win32-x64-msvc@4.18.0':
-    resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==}
-    cpu: [x64]
-    os: [win32]
-
   '@rollup/rollup-win32-x64-msvc@4.30.1':
     resolution: {integrity: sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==}
     cpu: [x64]
@@ -3586,16 +3499,16 @@ packages:
     resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
     engines: {node: '>=14.16'}
 
-  '@tanstack/eslint-plugin-query@5.62.16':
-    resolution: {integrity: sha512-VhnHSQ/hc62olLzGhlLJ4BJGWynwjs3cDMsByasKJ3zjW1YZ+6raxOv0gHHISm+VEnAY42pkMowmSWrXfL4NTw==}
+  '@tanstack/eslint-plugin-query@5.66.0':
+    resolution: {integrity: sha512-CzZhBxicLDuuSJbkZ4nPcuBqWnhLu72Zt9p/7qLQ93BepVnZJV6ZDlBLBuN5eg7YRACwECPLsntnwo1zuhgseQ==}
     peerDependencies:
       eslint: ^8.57.0 || ^9.0.0
 
-  '@tanstack/query-core@5.64.1':
-    resolution: {integrity: sha512-978Wx4Wl4UJZbmvU/rkaM9cQtXXrbhK0lsz/UZhYIbyKYA8E4LdomTwyh2GHZ4oU0BKKoDH4YlKk2VscCUgNmg==}
+  '@tanstack/query-core@5.66.0':
+    resolution: {integrity: sha512-J+JeBtthiKxrpzUu7rfIPDzhscXF2p5zE/hVdrqkACBP8Yu0M96mwJ5m/8cPPYQE9aRNvXztXHlNwIh4FEeMZw==}
 
-  '@tanstack/react-query@5.64.1':
-    resolution: {integrity: sha512-vW5ggHpIO2Yjj44b4sB+Fd3cdnlMJppXRBJkEHvld6FXh3j5dwWJoQo7mGtKI2RbSFyiyu/PhGAy0+Vv5ev9Eg==}
+  '@tanstack/react-query@5.66.0':
+    resolution: {integrity: sha512-z3sYixFQJe8hndFnXgWu7C79ctL+pI0KAelYyW+khaNJ1m22lWrhJU2QrsTcRKMuVPtoZvfBYrTStIdKo+x0Xw==}
     peerDependencies:
       react: ^18 || ^19
 
@@ -3617,8 +3530,8 @@ packages:
   '@tootallnate/quickjs-emscripten@0.23.0':
     resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
 
-  '@trivago/prettier-plugin-sort-imports@5.2.1':
-    resolution: {integrity: sha512-NDZndt0fmVThIx/8cExuJHLZagUVzfGCoVrwH9x6aZvwfBdkrDFTYujecek6X2WpG4uUFsVaPg5+aNQPSyjcmw==}
+  '@trivago/prettier-plugin-sort-imports@5.2.2':
+    resolution: {integrity: sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==}
     engines: {node: '>18.12'}
     peerDependencies:
       '@vue/compiler-sfc': 3.x
@@ -3671,9 +3584,6 @@ packages:
   '@types/estree@0.0.39':
     resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==}
 
-  '@types/estree@1.0.5':
-    resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
-
   '@types/estree@1.0.6':
     resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
 
@@ -3713,8 +3623,8 @@ packages:
   '@types/negotiator@0.6.3':
     resolution: {integrity: sha512-JkXTOdKs5MF086b/pt8C3+yVp3iDUwG635L7oCH6HvJvvr6lSUU5oe/gLXnPEfYRROHjJIPgCV6cuAg8gGkntQ==}
 
-  '@types/node@22.10.5':
-    resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==}
+  '@types/node@22.13.0':
+    resolution: {integrity: sha512-ClIbNe36lawluuvq3+YYhnIN2CELi+6q8NpnM7PYp4hBn/TatfboPgVSm2rwKRfnV2M+Ty9GWDFI64KEe+kysA==}
 
   '@types/normalize-package-data@2.4.4':
     resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
@@ -3763,108 +3673,51 @@ packages:
   '@types/yauzl@2.10.3':
     resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
 
-  '@typescript-eslint/eslint-plugin@8.10.0':
-    resolution: {integrity: sha512-phuB3hoP7FFKbRXxjl+DRlQDuJqhpOnm5MmtROXyWi3uS/Xg2ZXqiQfcG2BJHiN4QKyzdOJi3NEn/qTnjUlkmQ==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
-      eslint: ^8.57.0 || ^9.0.0
-      typescript: '*'
-    peerDependenciesMeta:
-      typescript:
-        optional: true
-
-  '@typescript-eslint/eslint-plugin@8.19.1':
-    resolution: {integrity: sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==}
+  '@typescript-eslint/eslint-plugin@8.22.0':
+    resolution: {integrity: sha512-4Uta6REnz/xEJMvwf72wdUnC3rr4jAQf5jnTkeRQ9b6soxLxhDEbS/pfMPoJLDfFPNVRdryqWUIV/2GZzDJFZw==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     peerDependencies:
       '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
       eslint: ^8.57.0 || ^9.0.0
       typescript: '>=4.8.4 <5.8.0'
 
-  '@typescript-eslint/parser@8.10.0':
-    resolution: {integrity: sha512-E24l90SxuJhytWJ0pTQydFT46Nk0Z+bsLKo/L8rtQSL93rQ6byd1V/QbDpHUTdLPOMsBCcYXZweADNCfOCmOAg==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      eslint: ^8.57.0 || ^9.0.0
-      typescript: '*'
-    peerDependenciesMeta:
-      typescript:
-        optional: true
-
-  '@typescript-eslint/parser@8.19.1':
-    resolution: {integrity: sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==}
+  '@typescript-eslint/parser@8.22.0':
+    resolution: {integrity: sha512-MqtmbdNEdoNxTPzpWiWnqNac54h8JDAmkWtJExBVVnSrSmi9z+sZUt0LfKqk9rjqmKOIeRhO4fHHJ1nQIjduIQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     peerDependencies:
       eslint: ^8.57.0 || ^9.0.0
       typescript: '>=4.8.4 <5.8.0'
 
-  '@typescript-eslint/scope-manager@8.10.0':
-    resolution: {integrity: sha512-AgCaEjhfql9MDKjMUxWvH7HjLeBqMCBfIaBbzzIcBbQPZE7CPh1m6FF+L75NUMJFMLYhCywJXIDEMa3//1A0dw==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
-  '@typescript-eslint/scope-manager@8.19.1':
-    resolution: {integrity: sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
-  '@typescript-eslint/type-utils@8.10.0':
-    resolution: {integrity: sha512-PCpUOpyQSpxBn230yIcK+LeCQaXuxrgCm2Zk1S+PTIRJsEfU6nJ0TtwyH8pIwPK/vJoA+7TZtzyAJSGBz+s/dg==}
+  '@typescript-eslint/scope-manager@8.22.0':
+    resolution: {integrity: sha512-/lwVV0UYgkj7wPSw0o8URy6YI64QmcOdwHuGuxWIYznO6d45ER0wXUbksr9pYdViAofpUCNJx/tAzNukgvaaiQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      typescript: '*'
-    peerDependenciesMeta:
-      typescript:
-        optional: true
 
-  '@typescript-eslint/type-utils@8.19.1':
-    resolution: {integrity: sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==}
+  '@typescript-eslint/type-utils@8.22.0':
+    resolution: {integrity: sha512-NzE3aB62fDEaGjaAYZE4LH7I1MUwHooQ98Byq0G0y3kkibPJQIXVUspzlFOmOfHhiDLwKzMlWxaNv+/qcZurJA==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     peerDependencies:
       eslint: ^8.57.0 || ^9.0.0
       typescript: '>=4.8.4 <5.8.0'
 
-  '@typescript-eslint/types@8.10.0':
-    resolution: {integrity: sha512-k/E48uzsfJCRRbGLapdZgrX52csmWJ2rcowwPvOZ8lwPUv3xW6CcFeJAXgx4uJm+Ge4+a4tFOkdYvSpxhRhg1w==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
-  '@typescript-eslint/types@8.19.1':
-    resolution: {integrity: sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
-  '@typescript-eslint/typescript-estree@8.10.0':
-    resolution: {integrity: sha512-3OE0nlcOHaMvQ8Xu5gAfME3/tWVDpb/HxtpUZ1WeOAksZ/h/gwrBzCklaGzwZT97/lBbbxJ16dMA98JMEngW4w==}
+  '@typescript-eslint/types@8.22.0':
+    resolution: {integrity: sha512-0S4M4baNzp612zwpD4YOieP3VowOARgK2EkN/GBn95hpyF8E2fbMT55sRHWBq+Huaqk3b3XK+rxxlM8sPgGM6A==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      typescript: '*'
-    peerDependenciesMeta:
-      typescript:
-        optional: true
 
-  '@typescript-eslint/typescript-estree@8.19.1':
-    resolution: {integrity: sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==}
+  '@typescript-eslint/typescript-estree@8.22.0':
+    resolution: {integrity: sha512-SJX99NAS2ugGOzpyhMza/tX+zDwjvwAtQFLsBo3GQxiGcvaKlqGBkmZ+Y1IdiSi9h4Q0Lr5ey+Cp9CGWNY/F/w==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     peerDependencies:
       typescript: '>=4.8.4 <5.8.0'
 
-  '@typescript-eslint/utils@8.10.0':
-    resolution: {integrity: sha512-Oq4uZ7JFr9d1ZunE/QKy5egcDRXT/FrS2z/nlxzPua2VHFtmMvFNDvpq1m/hq0ra+T52aUezfcjGRIB7vNJF9w==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      eslint: ^8.57.0 || ^9.0.0
-
-  '@typescript-eslint/utils@8.19.1':
-    resolution: {integrity: sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==}
+  '@typescript-eslint/utils@8.22.0':
+    resolution: {integrity: sha512-T8oc1MbF8L+Bk2msAvCUzjxVB2Z2f+vXYfcucE2wOmYs7ZUwco5Ep0fYZw8quNwOiw9K8GYVL+Kgc2pETNTLOg==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     peerDependencies:
       eslint: ^8.57.0 || ^9.0.0
       typescript: '>=4.8.4 <5.8.0'
 
-  '@typescript-eslint/visitor-keys@8.10.0':
-    resolution: {integrity: sha512-k8nekgqwr7FadWk548Lfph6V3r9OVqjzAIVskE7orMZR23cGJjAOVazsZSJW+ElyjfTM4wx/1g88Mi70DDtG9A==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
-  '@typescript-eslint/visitor-keys@8.19.1':
-    resolution: {integrity: sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==}
+  '@typescript-eslint/visitor-keys@8.22.0':
+    resolution: {integrity: sha512-AWpYAXnUgvLNabGTy3uBylkgZoosva/miNd1I8Bz3SjotmQPbVqhO4Cczo8AsZ44XVErEBPr/CRSgaj8sG7g0w==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
   '@ungap/structured-clone@1.2.0':
@@ -3876,39 +3729,39 @@ packages:
     peerDependencies:
       vite: ^4.2.0 || ^5.0.0 || ^6.0.0
 
-  '@vitest/coverage-istanbul@2.1.8':
-    resolution: {integrity: sha512-cSaCd8KcWWvgDwEJSXm0NEWZ1YTiJzjicKHy+zOEbUm0gjbbkz+qJf1p8q71uBzSlS7vdnZA8wRLeiwVE3fFTA==}
+  '@vitest/coverage-istanbul@3.0.4':
+    resolution: {integrity: sha512-a+SgPMom0PlRTuDasoucL2V7FDpS8j7p6jpHLNgt3d7oOSWYwtAFVCfZ3iQ+a+cOnh76g4mOftVR5Y9HokB/GQ==}
     peerDependencies:
-      vitest: 2.1.8
+      vitest: 3.0.4
 
-  '@vitest/expect@2.1.8':
-    resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==}
+  '@vitest/expect@3.0.4':
+    resolution: {integrity: sha512-Nm5kJmYw6P2BxhJPkO3eKKhGYKRsnqJqf+r0yOGRKpEP+bSCBDsjXgiu1/5QFrnPMEgzfC38ZEjvCFgaNBC0Eg==}
 
-  '@vitest/mocker@2.1.8':
-    resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==}
+  '@vitest/mocker@3.0.4':
+    resolution: {integrity: sha512-gEef35vKafJlfQbnyOXZ0Gcr9IBUsMTyTLXsEQwuyYAerpHqvXhzdBnDFuHLpFqth3F7b6BaFr4qV/Cs1ULx5A==}
     peerDependencies:
       msw: ^2.4.9
-      vite: ^5.0.0
+      vite: ^5.0.0 || ^6.0.0
     peerDependenciesMeta:
       msw:
         optional: true
       vite:
         optional: true
 
-  '@vitest/pretty-format@2.1.8':
-    resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==}
+  '@vitest/pretty-format@3.0.4':
+    resolution: {integrity: sha512-ts0fba+dEhK2aC9PFuZ9LTpULHpY/nd6jhAQ5IMU7Gaj7crPCTdCFfgvXxruRBLFS+MLraicCuFXxISEq8C93g==}
 
-  '@vitest/runner@2.1.8':
-    resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==}
+  '@vitest/runner@3.0.4':
+    resolution: {integrity: sha512-dKHzTQ7n9sExAcWH/0sh1elVgwc7OJ2lMOBrAm73J7AH6Pf9T12Zh3lNE1TETZaqrWFXtLlx3NVrLRb5hCK+iw==}
 
-  '@vitest/snapshot@2.1.8':
-    resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==}
+  '@vitest/snapshot@3.0.4':
+    resolution: {integrity: sha512-+p5knMLwIk7lTQkM3NonZ9zBewzVp9EVkVpvNta0/PlFWpiqLaRcF4+33L1it3uRUCh0BGLOaXPPGEjNKfWb4w==}
 
-  '@vitest/spy@2.1.8':
-    resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==}
+  '@vitest/spy@3.0.4':
+    resolution: {integrity: sha512-sXIMF0oauYyUy2hN49VFTYodzEAu744MmGcPR3ZBsPM20G+1/cSW/n1U+3Yu/zHxX2bIDe1oJASOkml+osTU6Q==}
 
-  '@vitest/utils@2.1.8':
-    resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==}
+  '@vitest/utils@3.0.4':
+    resolution: {integrity: sha512-8BqC1ksYsHtbWH+DfpOAKrFw3jl3Uf9J7yeFh85Pz52IWuh1hBBtyfEbRNNZNjl8H8A5yMLH9/t+k7HIKzQcZQ==}
 
   '@webassemblyjs/ast@1.12.1':
     resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==}
@@ -3995,11 +3848,6 @@ packages:
     resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==}
     engines: {node: '>=0.4.0'}
 
-  acorn@8.13.0:
-    resolution: {integrity: sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==}
-    engines: {node: '>=0.4.0'}
-    hasBin: true
-
   acorn@8.14.0:
     resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
     engines: {node: '>=0.4.0'}
@@ -4009,10 +3857,6 @@ packages:
     resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
     engines: {node: '>= 6.0.0'}
 
-  agent-base@7.1.1:
-    resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==}
-    engines: {node: '>= 14'}
-
   agent-base@7.1.3:
     resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==}
     engines: {node: '>= 14'}
@@ -4655,15 +4499,6 @@ packages:
       supports-color:
         optional: true
 
-  debug@4.3.7:
-    resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
-    engines: {node: '>=6.0'}
-    peerDependencies:
-      supports-color: '*'
-    peerDependenciesMeta:
-      supports-color:
-        optional: true
-
   debug@4.4.0:
     resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
     engines: {node: '>=6.0'}
@@ -4875,8 +4710,8 @@ packages:
     resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==}
     engines: {node: '>= 0.4'}
 
-  es-module-lexer@1.5.4:
-    resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
+  es-module-lexer@1.6.0:
+    resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==}
 
   es-object-atoms@1.0.0:
     resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
@@ -4942,8 +4777,8 @@ packages:
       typescript:
         optional: true
 
-  eslint-config-prettier@9.1.0:
-    resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==}
+  eslint-config-prettier@10.0.1:
+    resolution: {integrity: sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==}
     hasBin: true
     peerDependencies:
       eslint: '>=7.0.0'
@@ -5044,8 +4879,8 @@ packages:
     resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  eslint@9.18.0:
-    resolution: {integrity: sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==}
+  eslint@9.19.0:
+    resolution: {integrity: sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     hasBin: true
     peerDependencies:
@@ -5486,10 +5321,6 @@ packages:
     resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
     engines: {node: '>= 6'}
 
-  https-proxy-agent@7.0.5:
-    resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==}
-    engines: {node: '>= 14'}
-
   https-proxy-agent@7.0.6:
     resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
     engines: {node: '>= 14'}
@@ -5504,8 +5335,8 @@ packages:
   i18next-resources-to-backend@1.2.1:
     resolution: {integrity: sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw==}
 
-  i18next@24.2.1:
-    resolution: {integrity: sha512-Q2wC1TjWcSikn1VAJg13UGIjc+okpFxQTxjVAymOnSA3RpttBQNMPf2ovcgoFVsV4QNxTfNZMAxorXZXsk4fBA==}
+  i18next@24.2.2:
+    resolution: {integrity: sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ==}
     peerDependencies:
       typescript: ^5
     peerDependenciesMeta:
@@ -6037,8 +5868,8 @@ packages:
   magic-string@0.25.9:
     resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
 
-  magic-string@0.30.12:
-    resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==}
+  magic-string@0.30.17:
+    resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
 
   magicast@0.3.5:
     resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==}
@@ -6722,8 +6553,8 @@ packages:
     resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
     engines: {node: '>=8'}
 
-  pathe@1.1.2:
-    resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
+  pathe@2.0.2:
+    resolution: {integrity: sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==}
 
   pathval@2.0.0:
     resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
@@ -6739,9 +6570,6 @@ packages:
   pg-connection-string@2.6.4:
     resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==}
 
-  picocolors@1.1.0:
-    resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
-
   picocolors@1.1.1:
     resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
 
@@ -6761,13 +6589,13 @@ packages:
     resolution: {integrity: sha512-Et9V5QpvBilPFgagJcaKBqXjKrrgF5JL2mSDELk1vvbOTt4fuBhSSsGn9Tcz0TQTfS5GCpXQ31Whrpqeqp0VRg==}
     engines: {node: '>=12.0.0'}
 
-  playwright-core@1.49.1:
-    resolution: {integrity: sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==}
+  playwright-core@1.50.1:
+    resolution: {integrity: sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==}
     engines: {node: '>=18'}
     hasBin: true
 
-  playwright@1.49.1:
-    resolution: {integrity: sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==}
+  playwright@1.50.1:
+    resolution: {integrity: sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==}
     engines: {node: '>=18'}
     hasBin: true
 
@@ -7117,8 +6945,8 @@ packages:
   remark-rehype@11.1.1:
     resolution: {integrity: sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==}
 
-  remeda@2.19.0:
-    resolution: {integrity: sha512-B/2+zHNPXu0BAopJU8ZrqMjA0u56M/l6BUxDq8AcU+3LWlOYVuf98I6qpYrB5BeeEICunpmXPcQl2ReGXkiQyw==}
+  remeda@2.20.1:
+    resolution: {integrity: sha512-gsEsSmjE0CHkNp6xEsWsU/6JVNWq7rqw+ZfzNMbVV4YFIPtTj/i0FfxurTRI6Z9sAnQufU9de2Cb3xHsUTFTMA==}
 
   require-directory@2.1.1:
     resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
@@ -7196,11 +7024,6 @@ packages:
     engines: {node: '>=10.0.0'}
     hasBin: true
 
-  rollup@4.18.0:
-    resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==}
-    engines: {node: '>=18.0.0', npm: '>=8.0.0'}
-    hasBin: true
-
   rollup@4.30.1:
     resolution: {integrity: sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==}
     engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -7256,6 +7079,11 @@ packages:
     engines: {node: '>=10'}
     hasBin: true
 
+  semver@7.7.0:
+    resolution: {integrity: sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==}
+    engines: {node: '>=10'}
+    hasBin: true
+
   sequelize-pool@7.1.0:
     resolution: {integrity: sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==}
     engines: {node: '>= 10.0.0'}
@@ -7375,10 +7203,6 @@ packages:
     resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==}
     engines: {node: '>= 10'}
 
-  socks-proxy-agent@8.0.4:
-    resolution: {integrity: sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==}
-    engines: {node: '>= 14'}
-
   socks-proxy-agent@8.0.5:
     resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==}
     engines: {node: '>= 14'}
@@ -7657,11 +7481,6 @@ packages:
       uglify-js:
         optional: true
 
-  terser@5.31.1:
-    resolution: {integrity: sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==}
-    engines: {node: '>=10'}
-    hasBin: true
-
   terser@5.36.0:
     resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==}
     engines: {node: '>=10'}
@@ -7696,29 +7515,25 @@ packages:
   tinybench@2.9.0:
     resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
 
-  tinyexec@0.3.1:
-    resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==}
+  tinyexec@0.3.2:
+    resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
 
   tinyglobby@0.2.10:
     resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==}
     engines: {node: '>=12.0.0'}
 
-  tinypool@1.0.1:
-    resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==}
+  tinypool@1.0.2:
+    resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==}
     engines: {node: ^18.0.0 || >=20.0.0}
 
-  tinyrainbow@1.2.0:
-    resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
+  tinyrainbow@2.0.0:
+    resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
     engines: {node: '>=14.0.0'}
 
   tinyspy@3.0.2:
     resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
     engines: {node: '>=14.0.0'}
 
-  to-fast-properties@2.0.0:
-    resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
-    engines: {node: '>=4'}
-
   to-regex-range@5.0.1:
     resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
     engines: {node: '>=8.0'}
@@ -7755,12 +7570,6 @@ packages:
   trough@2.2.0:
     resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
 
-  ts-api-utils@1.3.0:
-    resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
-    engines: {node: '>=16'}
-    peerDependencies:
-      typescript: '>=4.2.0'
-
   ts-api-utils@2.0.0:
     resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==}
     engines: {node: '>=18.12'}
@@ -7786,14 +7595,11 @@ packages:
   tslib@2.3.0:
     resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
 
-  tslib@2.6.3:
-    resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
+  tslib@2.8.1:
+    resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
 
-  tslib@2.7.0:
-    resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
-
-  tsup@8.3.5:
-    resolution: {integrity: sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==}
+  tsup@8.3.6:
+    resolution: {integrity: sha512-XkVtlDV/58S9Ye0JxUUTcrQk4S+EqlOHKzg6Roa62rdjL1nGWNUstG0xgI4vanHdfIpjP448J8vlN0oK6XOJ5g==}
     engines: {node: '>=18'}
     hasBin: true
     peerDependencies:
@@ -7851,14 +7657,14 @@ packages:
     resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==}
     engines: {node: '>=14.16'}
 
-  type-fest@4.29.0:
-    resolution: {integrity: sha512-RPYt6dKyemXJe7I6oNstcH24myUGSReicxcHTvCLgzm4e0n8y05dGvcGB15/SoPRBmhlMthWQ9pvKyL81ko8nQ==}
-    engines: {node: '>=16'}
-
   type-fest@4.32.0:
     resolution: {integrity: sha512-rfgpoi08xagF3JSdtJlCwMq9DGNDE0IMh3Mkpc1wUypg9vPi786AiqeBBKcqvIkq42azsBM85N490fyZjeUftw==}
     engines: {node: '>=16'}
 
+  type-fest@4.33.0:
+    resolution: {integrity: sha512-s6zVrxuyKbbAsSAD5ZPTB77q4YIdRctkTbJ2/Dqlinwz+8ooH2gd+YA7VA6Pa93KML9GockVvoxjZ2vHP+mu8g==}
+    engines: {node: '>=16'}
+
   type-is@1.6.18:
     resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
     engines: {node: '>= 0.6'}
@@ -7882,8 +7688,8 @@ packages:
   typedarray-to-buffer@3.1.5:
     resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==}
 
-  typescript-eslint@8.19.1:
-    resolution: {integrity: sha512-LKPUQpdEMVOeKluHi8md7rwLcoXHhwvWp3x+sJkMuq3gGm9yaYJtPo8sRZSblMFJ5pcOGCAak/scKf1mvZDlQw==}
+  typescript-eslint@8.22.0:
+    resolution: {integrity: sha512-Y2rj210FW1Wb6TWXzQc5+P+EWI9/zdS57hLEc0gnyuvdzWo8+Y8brKlbj0muejonhMI/xAZCnZZwjbIfv1CkOw==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     peerDependencies:
       eslint: ^8.57.0 || ^9.0.0
@@ -8029,10 +7835,6 @@ packages:
     resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
     engines: {node: '>= 0.4.0'}
 
-  uuid@11.0.3:
-    resolution: {integrity: sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==}
-    hasBin: true
-
   uuid@11.0.5:
     resolution: {integrity: sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==}
     hasBin: true
@@ -8077,9 +7879,9 @@ packages:
   vfile@6.0.3:
     resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
 
-  vite-node@2.1.8:
-    resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==}
-    engines: {node: ^18.0.0 || >=20.0.0}
+  vite-node@3.0.4:
+    resolution: {integrity: sha512-7JZKEzcYV2Nx3u6rlvN8qdo3QV7Fxyt6hx+CCKz9fbWxdX5IvUOmTWEAxMrWxaiSf7CKGLJQ5rFu8prb/jBjOA==}
+    engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
     hasBin: true
 
   vite-tsconfig-paths@5.1.4:
@@ -8118,20 +7920,23 @@ packages:
       terser:
         optional: true
 
-  vitest@2.1.8:
-    resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==}
-    engines: {node: ^18.0.0 || >=20.0.0}
+  vitest@3.0.4:
+    resolution: {integrity: sha512-6XG8oTKy2gnJIFTHP6LD7ExFeNLxiTkK3CfMvT7IfR8IN+BYICCf0lXUQmX7i7JoxUP8QmeP4mTnWXgflu4yjw==}
+    engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
     hasBin: true
     peerDependencies:
       '@edge-runtime/vm': '*'
-      '@types/node': ^18.0.0 || >=20.0.0
-      '@vitest/browser': 2.1.8
-      '@vitest/ui': 2.1.8
+      '@types/debug': ^4.1.12
+      '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+      '@vitest/browser': 3.0.4
+      '@vitest/ui': 3.0.4
       happy-dom: '*'
       jsdom: '*'
     peerDependenciesMeta:
       '@edge-runtime/vm':
         optional: true
+      '@types/debug':
+        optional: true
       '@types/node':
         optional: true
       '@vitest/browser':
@@ -8432,9 +8237,9 @@ snapshots:
       jsonpointer: 5.0.1
       leven: 3.1.0
 
-  '@appthreat/atom@2.0.25':
+  '@appthreat/atom@2.1.11':
     dependencies:
-      '@babel/parser': 7.26.5
+      '@babel/parser': 7.26.7
       typescript: 5.7.3
       yargs: 17.7.2
     optional: true
@@ -8444,98 +8249,58 @@ snapshots:
       '@bufbuild/protobuf': 1.7.2
     optional: true
 
-  '@axe-core/playwright@4.10.1(playwright-core@1.49.1)':
+  '@axe-core/playwright@4.10.1(playwright-core@1.50.1)':
     dependencies:
       axe-core: 4.10.2
-      playwright-core: 1.49.1
+      playwright-core: 1.50.1
 
   '@babel/code-frame@7.26.2':
     dependencies:
       '@babel/helper-validator-identifier': 7.25.9
       js-tokens: 4.0.0
-      picocolors: 1.1.0
-
-  '@babel/compat-data@7.24.7': {}
-
-  '@babel/compat-data@7.25.8': {}
+      picocolors: 1.1.1
 
   '@babel/compat-data@7.26.2': {}
 
-  '@babel/core@7.25.8':
-    dependencies:
-      '@ampproject/remapping': 2.3.0
-      '@babel/code-frame': 7.26.2
-      '@babel/generator': 7.26.2
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8)
-      '@babel/helpers': 7.25.7
-      '@babel/parser': 7.26.2
-      '@babel/template': 7.25.9
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
-      convert-source-map: 2.0.0
-      debug: 4.3.7
-      gensync: 1.0.0-beta.2
-      json5: 2.2.3
-      semver: 6.3.1
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/core@7.26.0':
     dependencies:
       '@ampproject/remapping': 2.3.0
       '@babel/code-frame': 7.26.2
-      '@babel/generator': 7.26.2
+      '@babel/generator': 7.26.5
       '@babel/helper-compilation-targets': 7.25.9
       '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
       '@babel/helpers': 7.26.0
-      '@babel/parser': 7.26.2
+      '@babel/parser': 7.26.7
       '@babel/template': 7.25.9
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
+      '@babel/traverse': 7.26.7
+      '@babel/types': 7.26.7
       convert-source-map: 2.0.0
-      debug: 4.3.7
+      debug: 4.4.0
       gensync: 1.0.0-beta.2
       json5: 2.2.3
       semver: 6.3.1
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/generator@7.26.2':
-    dependencies:
-      '@babel/parser': 7.26.2
-      '@babel/types': 7.26.0
-      '@jridgewell/gen-mapping': 0.3.5
-      '@jridgewell/trace-mapping': 0.3.25
-      jsesc: 3.0.2
-
   '@babel/generator@7.26.5':
     dependencies:
-      '@babel/parser': 7.26.5
-      '@babel/types': 7.26.5
+      '@babel/parser': 7.26.7
+      '@babel/types': 7.26.7
       '@jridgewell/gen-mapping': 0.3.5
       '@jridgewell/trace-mapping': 0.3.25
       jsesc: 3.0.2
 
   '@babel/helper-annotate-as-pure@7.24.7':
     dependencies:
-      '@babel/types': 7.26.0
+      '@babel/types': 7.26.7
 
   '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7':
     dependencies:
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
+      '@babel/traverse': 7.26.7
+      '@babel/types': 7.26.7
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helper-compilation-targets@7.25.7':
-    dependencies:
-      '@babel/compat-data': 7.25.8
-      '@babel/helper-validator-option': 7.25.7
-      browserslist: 4.24.0
-      lru-cache: 5.1.1
-      semver: 6.3.1
-
   '@babel/helper-compilation-targets@7.25.9':
     dependencies:
       '@babel/compat-data': 7.26.2
@@ -8544,21 +8309,6 @@ snapshots:
       lru-cache: 5.1.1
       semver: 6.3.1
 
-  '@babel/helper-create-class-features-plugin@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-annotate-as-pure': 7.24.7
-      '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-function-name': 7.24.7
-      '@babel/helper-member-expression-to-functions': 7.24.7
-      '@babel/helper-optimise-call-expression': 7.24.7
-      '@babel/helper-replace-supers': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
-      '@babel/helper-split-export-declaration': 7.24.7
-      semver: 6.3.1
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/helper-create-class-features-plugin@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
@@ -8574,13 +8324,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helper-create-regexp-features-plugin@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-annotate-as-pure': 7.24.7
-      regexpu-core: 5.3.2
-      semver: 6.3.1
-
   '@babel/helper-create-regexp-features-plugin@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
@@ -8588,22 +8331,11 @@ snapshots:
       regexpu-core: 5.3.2
       semver: 6.3.1
 
-  '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-plugin-utils': 7.24.7
-      debug: 4.4.0
-      lodash.debounce: 4.0.8
-      resolve: 1.22.8
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-compilation-targets': 7.25.9
+      '@babel/helper-plugin-utils': 7.25.9
       debug: 4.4.0
       lodash.debounce: 4.0.8
       resolve: 1.22.8
@@ -8612,48 +8344,28 @@ snapshots:
 
   '@babel/helper-environment-visitor@7.24.7':
     dependencies:
-      '@babel/types': 7.26.0
+      '@babel/types': 7.26.7
 
   '@babel/helper-function-name@7.24.7':
     dependencies:
       '@babel/template': 7.25.9
-      '@babel/types': 7.26.0
+      '@babel/types': 7.26.7
 
   '@babel/helper-hoist-variables@7.24.7':
     dependencies:
-      '@babel/types': 7.26.0
+      '@babel/types': 7.26.7
 
   '@babel/helper-member-expression-to-functions@7.24.7':
     dependencies:
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
+      '@babel/traverse': 7.26.7
+      '@babel/types': 7.26.7
     transitivePeerDependencies:
       - supports-color
 
   '@babel/helper-module-imports@7.25.9':
     dependencies:
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
-    transitivePeerDependencies:
-      - supports-color
-
-  '@babel/helper-module-transforms@7.25.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-module-imports': 7.25.9
-      '@babel/helper-simple-access': 7.25.7
-      '@babel/helper-validator-identifier': 7.25.9
-      '@babel/traverse': 7.25.9
-    transitivePeerDependencies:
-      - supports-color
-
-  '@babel/helper-module-transforms@7.25.7(@babel/core@7.26.0)':
-    dependencies:
-      '@babel/core': 7.26.0
-      '@babel/helper-module-imports': 7.25.9
-      '@babel/helper-simple-access': 7.25.7
-      '@babel/helper-validator-identifier': 7.25.9
-      '@babel/traverse': 7.25.9
+      '@babel/traverse': 7.26.7
+      '@babel/types': 7.26.7
     transitivePeerDependencies:
       - supports-color
 
@@ -8662,27 +8374,16 @@ snapshots:
       '@babel/core': 7.26.0
       '@babel/helper-module-imports': 7.25.9
       '@babel/helper-validator-identifier': 7.25.9
-      '@babel/traverse': 7.25.9
+      '@babel/traverse': 7.26.7
     transitivePeerDependencies:
       - supports-color
 
   '@babel/helper-optimise-call-expression@7.24.7':
     dependencies:
-      '@babel/types': 7.26.0
-
-  '@babel/helper-plugin-utils@7.24.7': {}
+      '@babel/types': 7.26.7
 
   '@babel/helper-plugin-utils@7.25.9': {}
 
-  '@babel/helper-remap-async-to-generator@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-annotate-as-pure': 7.24.7
-      '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-wrap-function': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/helper-remap-async-to-generator@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
@@ -8692,15 +8393,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helper-replace-supers@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-member-expression-to-functions': 7.24.7
-      '@babel/helper-optimise-call-expression': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/helper-replace-supers@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
@@ -8710,408 +8402,208 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helper-simple-access@7.24.7':
-    dependencies:
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/helper-simple-access@7.25.7':
     dependencies:
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
+      '@babel/traverse': 7.26.7
+      '@babel/types': 7.26.7
     transitivePeerDependencies:
       - supports-color
 
   '@babel/helper-skip-transparent-expression-wrappers@7.24.7':
     dependencies:
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
+      '@babel/traverse': 7.26.7
+      '@babel/types': 7.26.7
     transitivePeerDependencies:
       - supports-color
 
   '@babel/helper-split-export-declaration@7.24.7':
     dependencies:
-      '@babel/types': 7.26.0
-
-  '@babel/helper-string-parser@7.25.7': {}
+      '@babel/types': 7.26.7
 
   '@babel/helper-string-parser@7.25.9': {}
 
-  '@babel/helper-validator-identifier@7.25.7': {}
-
   '@babel/helper-validator-identifier@7.25.9': {}
 
-  '@babel/helper-validator-option@7.24.7': {}
-
-  '@babel/helper-validator-option@7.25.7': {}
-
   '@babel/helper-validator-option@7.25.9': {}
 
   '@babel/helper-wrap-function@7.24.7':
     dependencies:
       '@babel/helper-function-name': 7.24.7
       '@babel/template': 7.25.9
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
+      '@babel/traverse': 7.26.7
+      '@babel/types': 7.26.7
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helpers@7.25.7':
-    dependencies:
-      '@babel/template': 7.25.9
-      '@babel/types': 7.26.0
-
   '@babel/helpers@7.26.0':
     dependencies:
       '@babel/template': 7.25.9
-      '@babel/types': 7.26.0
-
-  '@babel/parser@7.25.8':
-    dependencies:
-      '@babel/types': 7.26.0
-
-  '@babel/parser@7.26.2':
-    dependencies:
-      '@babel/types': 7.26.0
-
-  '@babel/parser@7.26.5':
-    dependencies:
-      '@babel/types': 7.26.5
+      '@babel/types': 7.26.7
 
-  '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.7(@babel/core@7.25.8)':
+  '@babel/parser@7.26.7':
     dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/types': 7.26.7
 
   '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
-      '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.25.8)
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
       '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
 
-  '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-async-generator-functions@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.8)
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-async-generator-functions@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.26.0)
       '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-async-to-generator@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-module-imports': 7.25.9
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.25.8)
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/plugin-transform-async-to-generator@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-module-imports': 7.25.9
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-block-scoping@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-block-scoping@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-class-properties@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-class-properties@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
-  '@babel/plugin-transform-class-static-block@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.8)
+      '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
@@ -9119,238 +8611,118 @@ snapshots:
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-classes@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-annotate-as-pure': 7.24.7
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-environment-visitor': 7.24.7
-      '@babel/helper-function-name': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-replace-supers': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-split-export-declaration': 7.24.7
-      globals: 11.12.0
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/plugin-transform-classes@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-annotate-as-pure': 7.24.7
-      '@babel/helper-compilation-targets': 7.25.7
+      '@babel/helper-compilation-targets': 7.25.9
       '@babel/helper-environment-visitor': 7.24.7
       '@babel/helper-function-name': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-replace-supers': 7.24.7(@babel/core@7.26.0)
       '@babel/helper-split-export-declaration': 7.24.7
       globals: 11.12.0
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-computed-properties@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/template': 7.25.9
-
   '@babel/plugin-transform-computed-properties@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/template': 7.25.9
 
-  '@babel/plugin-transform-destructuring@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-destructuring@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.8)
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-exponentiation-operator@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/plugin-transform-exponentiation-operator@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-export-namespace-from@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.25.8)
-
   '@babel/plugin-transform-export-namespace-from@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-for-of@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/plugin-transform-for-of@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-function-name@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-function-name': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-function-name@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-compilation-targets': 7.25.7
+      '@babel/helper-compilation-targets': 7.25.9
       '@babel/helper-function-name': 7.24.7
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-json-strings@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.8)
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-json-strings@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-literals@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-literals@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.8)
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
-  '@babel/plugin-transform-modules-commonjs@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-simple-access': 7.24.7
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+      '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
   '@babel/plugin-transform-modules-commonjs@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-simple-access': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
-  '@babel/plugin-transform-modules-systemjs@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-hoist-variables': 7.24.7
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-validator-identifier': 7.25.9
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+      '@babel/helper-plugin-utils': 7.25.9
+      '@babel/helper-simple-access': 7.25.7
     transitivePeerDependencies:
       - supports-color
 
@@ -9358,169 +8730,84 @@ snapshots:
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-hoist-variables': 7.24.7
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-validator-identifier': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-modules-umd@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/plugin-transform-modules-umd@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-module-transforms': 7.25.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+      '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-new-target@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-new-target@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.8)
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.8)
-
   '@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-object-rest-spread@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.8)
-      '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.8)
-
   '@babel/plugin-transform-object-rest-spread@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-compilation-targets': 7.25.9
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.0)
       '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-object-super@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-replace-supers': 7.24.7(@babel/core@7.25.8)
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/plugin-transform-object-super@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-replace-supers': 7.24.7(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-optional-catch-binding@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.8)
-
   '@babel/plugin-transform-optional-catch-binding@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-optional-chaining@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
-      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.8)
-    transitivePeerDependencies:
-      - supports-color
-
   '@babel/plugin-transform-optional-chaining@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
       '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-parameters@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-parameters@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-private-methods@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-private-methods@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
-
-  '@babel/plugin-transform-private-property-in-object@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-annotate-as-pure': 7.24.7
-      '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.8)
+      '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
@@ -9529,20 +8816,15 @@ snapshots:
       '@babel/core': 7.26.0
       '@babel/helper-annotate-as-pure': 7.24.7
       '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)':
     dependencies:
@@ -9554,224 +8836,75 @@ snapshots:
       '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      regenerator-transform: 0.15.2
-
   '@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       regenerator-transform: 0.15.2
 
-  '@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-spread@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-spread@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-
   '@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-typeof-symbol@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-typeof-symbol@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/plugin-transform-unicode-sets-regex@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.25.8)
-      '@babel/helper-plugin-utils': 7.24.7
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/plugin-transform-unicode-sets-regex@7.24.7(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.26.0)
-      '@babel/helper-plugin-utils': 7.24.7
-
-  '@babel/preset-env@7.24.7(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/compat-data': 7.24.7
-      '@babel/core': 7.25.8
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-validator-option': 7.24.7
-      '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.8)
-      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.8)
-      '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.8)
-      '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.8)
-      '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.8)
-      '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.25.8)
-      '@babel/plugin-syntax-import-assertions': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.8)
-      '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.8)
-      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.8)
-      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.8)
-      '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.8)
-      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.8)
-      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.8)
-      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.8)
-      '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.8)
-      '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.8)
-      '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.25.8)
-      '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-async-generator-functions': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-async-to-generator': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-block-scoped-functions': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-block-scoping': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-class-static-block': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-classes': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-computed-properties': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-destructuring': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-dotall-regex': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-duplicate-keys': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-dynamic-import': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-exponentiation-operator': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-export-namespace-from': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-for-of': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-function-name': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-json-strings': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-literals': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-logical-assignment-operators': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-member-expression-literals': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-modules-amd': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-modules-commonjs': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-modules-systemjs': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-modules-umd': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-named-capturing-groups-regex': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-new-target': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-numeric-separator': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-object-rest-spread': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-object-super': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-optional-catch-binding': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-private-property-in-object': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-property-literals': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-regenerator': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-reserved-words': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-shorthand-properties': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-spread': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-sticky-regex': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-template-literals': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-typeof-symbol': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-unicode-escapes': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-unicode-property-regex': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-unicode-regex': 7.24.7(@babel/core@7.25.8)
-      '@babel/plugin-transform-unicode-sets-regex': 7.24.7(@babel/core@7.25.8)
-      '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.25.8)
-      babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.8)
-      babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.25.8)
-      babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.8)
-      core-js-compat: 3.37.1
-      semver: 6.3.1
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-plugin-utils': 7.25.9
 
   '@babel/preset-env@7.24.7(@babel/core@7.26.0)':
     dependencies:
-      '@babel/compat-data': 7.24.7
+      '@babel/compat-data': 7.26.2
       '@babel/core': 7.26.0
-      '@babel/helper-compilation-targets': 7.25.7
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/helper-validator-option': 7.24.7
+      '@babel/helper-compilation-targets': 7.25.9
+      '@babel/helper-plugin-utils': 7.25.9
+      '@babel/helper-validator-option': 7.25.9
       '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.7(@babel/core@7.26.0)
       '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.7(@babel/core@7.26.0)
       '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.7(@babel/core@7.26.0)
@@ -9852,18 +8985,11 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.25.8)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/types': 7.26.0
-      esutils: 2.0.3
-
   '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0)':
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/helper-plugin-utils': 7.24.7
-      '@babel/types': 7.26.0
+      '@babel/helper-plugin-utils': 7.25.9
+      '@babel/types': 7.26.7
       esutils: 2.0.3
 
   '@babel/regjsgen@0.8.0': {}
@@ -9875,45 +9001,22 @@ snapshots:
   '@babel/template@7.25.9':
     dependencies:
       '@babel/code-frame': 7.26.2
-      '@babel/parser': 7.26.2
-      '@babel/types': 7.26.0
-
-  '@babel/traverse@7.25.9':
-    dependencies:
-      '@babel/code-frame': 7.26.2
-      '@babel/generator': 7.26.2
-      '@babel/parser': 7.26.2
-      '@babel/template': 7.25.9
-      '@babel/types': 7.26.0
-      debug: 4.3.7
-      globals: 11.12.0
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/parser': 7.26.7
+      '@babel/types': 7.26.7
 
-  '@babel/traverse@7.26.5':
+  '@babel/traverse@7.26.7':
     dependencies:
       '@babel/code-frame': 7.26.2
       '@babel/generator': 7.26.5
-      '@babel/parser': 7.26.5
+      '@babel/parser': 7.26.7
       '@babel/template': 7.25.9
-      '@babel/types': 7.26.5
-      debug: 4.3.7
+      '@babel/types': 7.26.7
+      debug: 4.4.0
       globals: 11.12.0
     transitivePeerDependencies:
-      - supports-color
-
-  '@babel/types@7.25.8':
-    dependencies:
-      '@babel/helper-string-parser': 7.25.7
-      '@babel/helper-validator-identifier': 7.25.7
-      to-fast-properties: 2.0.0
-
-  '@babel/types@7.26.0':
-    dependencies:
-      '@babel/helper-string-parser': 7.25.9
-      '@babel/helper-validator-identifier': 7.25.9
+      - supports-color
 
-  '@babel/types@7.26.5':
+  '@babel/types@7.26.7':
     dependencies:
       '@babel/helper-string-parser': 7.25.9
       '@babel/helper-validator-identifier': 7.25.9
@@ -9945,10 +9048,10 @@ snapshots:
   '@cyclonedx/cdxgen-plugins-bin@1.6.9':
     optional: true
 
-  '@cyclonedx/cdxgen@11.0.10':
+  '@cyclonedx/cdxgen@11.1.7':
     dependencies:
-      '@babel/parser': 7.26.5
-      '@babel/traverse': 7.26.5
+      '@babel/parser': 7.26.7
+      '@babel/traverse': 7.26.7
       '@iarna/toml': 2.2.5
       '@npmcli/arborist': 9.0.0
       ajv: 8.17.1
@@ -9966,16 +9069,16 @@ snapshots:
       packageurl-js: 1.0.2
       prettify-xml: 1.2.0
       properties-reader: 2.3.0
-      semver: 7.6.3
+      semver: 7.7.0
       ssri: 12.0.0
       table: 6.9.0
       tar: 7.4.3
-      uuid: 11.0.3
+      uuid: 11.0.5
       validate-iri: 1.0.1
       xml-js: 1.6.11
       yargs: 17.7.2
     optionalDependencies:
-      '@appthreat/atom': 2.0.25
+      '@appthreat/atom': 2.1.11
       '@appthreat/cdx-proto': 1.0.1
       '@cyclonedx/cdxgen-plugins-bin': 1.6.9
       '@cyclonedx/cdxgen-plugins-bin-arm': 1.6.9
@@ -10007,10 +9110,10 @@ snapshots:
 
   '@drauu/core@0.4.2': {}
 
-  '@ducanh2912/next-pwa@10.2.9(@types/babel__core@7.20.5)(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.92.1)':
+  '@ducanh2912/next-pwa@10.2.9(@types/babel__core@7.20.5)(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.92.1)':
     dependencies:
       fast-glob: 3.3.2
-      next: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+      next: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
       semver: 7.6.3
       webpack: 5.92.1
       workbox-build: 7.1.1(@types/babel__core@7.20.5)
@@ -10037,14 +9140,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@emotion/cache@11.13.5':
-    dependencies:
-      '@emotion/memoize': 0.9.0
-      '@emotion/sheet': 1.4.0
-      '@emotion/utils': 1.4.2
-      '@emotion/weak-memoize': 0.4.0
-      stylis: 4.2.0
-
   '@emotion/cache@11.14.0':
     dependencies:
       '@emotion/memoize': 0.9.0
@@ -10328,21 +9423,21 @@ snapshots:
   '@esbuild/win32-x64@0.24.2':
     optional: true
 
-  '@eslint-community/eslint-utils@4.4.0(eslint@9.18.0)':
+  '@eslint-community/eslint-utils@4.4.0(eslint@9.19.0)':
     dependencies:
-      eslint: 9.18.0
+      eslint: 9.19.0
       eslint-visitor-keys: 3.4.3
 
   '@eslint-community/regexpp@4.12.1': {}
 
-  '@eslint/compat@1.2.5(eslint@9.18.0)':
+  '@eslint/compat@1.2.6(eslint@9.19.0)':
     optionalDependencies:
-      eslint: 9.18.0
+      eslint: 9.19.0
 
   '@eslint/config-array@0.19.0':
     dependencies:
       '@eslint/object-schema': 2.1.4
-      debug: 4.3.7
+      debug: 4.4.0
       minimatch: 3.1.2
     transitivePeerDependencies:
       - supports-color
@@ -10354,7 +9449,7 @@ snapshots:
   '@eslint/eslintrc@3.2.0':
     dependencies:
       ajv: 6.12.6
-      debug: 4.3.7
+      debug: 4.4.0
       espree: 10.3.0
       globals: 14.0.0
       ignore: 5.3.1
@@ -10365,7 +9460,7 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@eslint/js@9.18.0': {}
+  '@eslint/js@9.19.0': {}
 
   '@eslint/object-schema@2.1.4': {}
 
@@ -10374,7 +9469,7 @@ snapshots:
       '@eslint/core': 0.10.0
       levn: 0.4.1
 
-  '@faker-js/faker@9.3.0': {}
+  '@faker-js/faker@9.4.0': {}
 
   '@floating-ui/core@1.6.2':
     dependencies:
@@ -10427,9 +9522,9 @@ snapshots:
   '@gar/promisify@1.1.3':
     optional: true
 
-  '@grafana/schema@11.4.0':
+  '@grafana/schema@11.5.0':
     dependencies:
-      tslib: 2.7.0
+      tslib: 2.8.1
 
   '@gwhitney/detect-indent@7.0.1': {}
 
@@ -10524,7 +9619,7 @@ snapshots:
       '@jridgewell/resolve-uri': 3.1.2
       '@jridgewell/sourcemap-codec': 1.5.0
 
-  '@keycloak/keycloak-admin-client@26.0.7':
+  '@keycloak/keycloak-admin-client@26.1.0':
     dependencies:
       camelize-ts: 3.0.0
       url-join: 5.0.0
@@ -10646,7 +9741,7 @@ snapshots:
   '@mui/styled-engine@5.16.14(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1))(react@18.3.1)':
     dependencies:
       '@babel/runtime': 7.25.6
-      '@emotion/cache': 11.13.5
+      '@emotion/cache': 11.14.0
       csstype: 3.1.3
       prop-types: 15.8.1
       react: 18.3.1
@@ -10732,8 +9827,6 @@ snapshots:
     dependencies:
       '@noble/hashes': 1.6.0
 
-  '@noble/hashes@1.4.0': {}
-
   '@noble/hashes@1.6.0': {}
 
   '@nodelib/fs.scandir@2.1.5':
@@ -10752,21 +9845,21 @@ snapshots:
 
   '@npmcli/agent@2.2.2':
     dependencies:
-      agent-base: 7.1.1
+      agent-base: 7.1.3
       http-proxy-agent: 7.0.2
-      https-proxy-agent: 7.0.5
+      https-proxy-agent: 7.0.6
       lru-cache: 10.2.2
-      socks-proxy-agent: 8.0.4
+      socks-proxy-agent: 8.0.5
     transitivePeerDependencies:
       - supports-color
 
   '@npmcli/agent@3.0.0':
     dependencies:
-      agent-base: 7.1.1
+      agent-base: 7.1.3
       http-proxy-agent: 7.0.2
-      https-proxy-agent: 7.0.5
+      https-proxy-agent: 7.0.6
       lru-cache: 10.2.2
-      socks-proxy-agent: 8.0.4
+      socks-proxy-agent: 8.0.5
     transitivePeerDependencies:
       - supports-color
 
@@ -10802,7 +9895,7 @@ snapshots:
       promise-all-reject-late: 1.0.1
       promise-call-limit: 3.0.1
       read-package-json-fast: 4.0.0
-      semver: 7.6.3
+      semver: 7.7.0
       ssri: 12.0.0
       treeverse: 3.0.0
       walk-up-path: 4.0.0
@@ -10813,16 +9906,16 @@ snapshots:
   '@npmcli/fs@1.1.1':
     dependencies:
       '@gar/promisify': 1.1.3
-      semver: 7.6.3
+      semver: 7.7.0
     optional: true
 
   '@npmcli/fs@3.1.1':
     dependencies:
-      semver: 7.6.3
+      semver: 7.7.0
 
   '@npmcli/fs@4.0.0':
     dependencies:
-      semver: 7.6.3
+      semver: 7.7.0
 
   '@npmcli/git@6.0.1':
     dependencies:
@@ -10833,7 +9926,7 @@ snapshots:
       proc-log: 5.0.0
       promise-inflight: 1.0.1
       promise-retry: 2.0.1
-      semver: 7.6.3
+      semver: 7.7.0
       which: 5.0.0
     transitivePeerDependencies:
       - bluebird
@@ -10858,7 +9951,7 @@ snapshots:
       json-parse-even-better-errors: 4.0.0
       pacote: 21.0.0
       proc-log: 5.0.0
-      semver: 7.6.3
+      semver: 7.7.0
     transitivePeerDependencies:
       - bluebird
       - supports-color
@@ -10881,7 +9974,7 @@ snapshots:
       json-parse-even-better-errors: 4.0.0
       normalize-package-data: 7.0.0
       proc-log: 5.0.0
-      semver: 7.6.3
+      semver: 7.7.0
     transitivePeerDependencies:
       - bluebird
 
@@ -10910,9 +10003,9 @@ snapshots:
   '@pkgjs/parseargs@0.11.0':
     optional: true
 
-  '@playwright/test@1.49.1':
+  '@playwright/test@1.50.1':
     dependencies:
-      playwright: 1.49.1
+      playwright: 1.50.1
 
   '@pnpm/catalogs.config@0.1.1':
     dependencies:
@@ -10982,7 +10075,7 @@ snapshots:
 
   '@pnpm/constants@10.0.0': {}
 
-  '@pnpm/constants@1001.0.0': {}
+  '@pnpm/constants@1001.1.0': {}
 
   '@pnpm/constants@9.0.0': {}
 
@@ -11032,14 +10125,14 @@ snapshots:
       pretty-ms: 7.0.1
       ramda: '@pnpm/ramda@0.28.1'
       rxjs: 7.8.1
-      semver: 7.6.3
+      semver: 7.7.0
       stacktracey: 2.1.8
       string-length: 4.0.2
 
-  '@pnpm/dependency-path@1000.0.1':
+  '@pnpm/dependency-path@1000.0.2':
     dependencies:
       '@pnpm/crypto.hash': 1000.0.0
-      '@pnpm/types': 1000.1.0
+      '@pnpm/types': 1000.1.1
       semver: 7.6.3
 
   '@pnpm/env.system-node-version@1.0.1':
@@ -11048,9 +10141,9 @@ snapshots:
       execa: safe-execa@0.1.2
       mem: 8.1.1
 
-  '@pnpm/error@1000.0.1':
+  '@pnpm/error@1000.0.2':
     dependencies:
-      '@pnpm/constants': 1001.0.0
+      '@pnpm/constants': 1001.1.0
 
   '@pnpm/error@6.0.2':
     dependencies:
@@ -11096,17 +10189,17 @@ snapshots:
       '@pnpm/lockfile.types': 1.0.3
       '@pnpm/types': 12.2.0
 
-  '@pnpm/lockfile.fs@1001.1.1(@pnpm/logger@5.2.0)':
+  '@pnpm/lockfile.fs@1001.1.2(@pnpm/logger@5.2.0)':
     dependencies:
-      '@pnpm/constants': 1001.0.0
-      '@pnpm/dependency-path': 1000.0.1
-      '@pnpm/error': 1000.0.1
+      '@pnpm/constants': 1001.1.0
+      '@pnpm/dependency-path': 1000.0.2
+      '@pnpm/error': 1000.0.2
       '@pnpm/git-utils': 1000.0.0
-      '@pnpm/lockfile.merger': 1001.0.1
-      '@pnpm/lockfile.types': 1001.0.1
-      '@pnpm/lockfile.utils': 1001.0.1
+      '@pnpm/lockfile.merger': 1001.0.2
+      '@pnpm/lockfile.types': 1001.0.2
+      '@pnpm/lockfile.utils': 1001.0.2
       '@pnpm/logger': 5.2.0
-      '@pnpm/types': 1000.1.0
+      '@pnpm/types': 1000.1.1
       '@pnpm/util.lex-comparator': 3.0.0
       '@zkochan/rimraf': 3.0.2
       comver-to-semver: 1.0.0
@@ -11118,10 +10211,10 @@ snapshots:
       strip-bom: 4.0.0
       write-file-atomic: 5.0.1
 
-  '@pnpm/lockfile.merger@1001.0.1':
+  '@pnpm/lockfile.merger@1001.0.2':
     dependencies:
-      '@pnpm/lockfile.types': 1001.0.1
-      '@pnpm/types': 1000.1.0
+      '@pnpm/lockfile.types': 1001.0.2
+      '@pnpm/types': 1000.1.1
       comver-to-semver: 1.0.0
       ramda: '@pnpm/ramda@0.28.1'
       semver: 7.6.3
@@ -11131,18 +10224,18 @@ snapshots:
       '@pnpm/patching.types': 1.0.0
       '@pnpm/types': 12.2.0
 
-  '@pnpm/lockfile.types@1001.0.1':
+  '@pnpm/lockfile.types@1001.0.2':
     dependencies:
       '@pnpm/patching.types': 1000.0.0
-      '@pnpm/types': 1000.1.0
+      '@pnpm/types': 1000.1.1
 
-  '@pnpm/lockfile.utils@1001.0.1':
+  '@pnpm/lockfile.utils@1001.0.2':
     dependencies:
-      '@pnpm/dependency-path': 1000.0.1
-      '@pnpm/lockfile.types': 1001.0.1
+      '@pnpm/dependency-path': 1000.0.2
+      '@pnpm/lockfile.types': 1001.0.2
       '@pnpm/pick-fetcher': 1000.0.0
-      '@pnpm/resolver-base': 1000.1.1
-      '@pnpm/types': 1000.1.0
+      '@pnpm/resolver-base': 1000.1.2
+      '@pnpm/types': 1000.1.1
       get-npm-tarball-url: 2.1.0
       ramda: '@pnpm/ramda@0.28.1'
 
@@ -11197,7 +10290,7 @@ snapshots:
       detect-libc: 2.0.3
       execa: safe-execa@0.1.2
       mem: 8.1.1
-      semver: 7.6.3
+      semver: 7.7.0
 
   '@pnpm/parse-overrides@5.1.1':
     dependencies:
@@ -11257,11 +10350,11 @@ snapshots:
       archy: 1.0.0
       chalk: 4.1.2
       cli-columns: 4.0.0
-      semver: 7.6.3
+      semver: 7.7.0
 
-  '@pnpm/resolver-base@1000.1.1':
+  '@pnpm/resolver-base@1000.1.2':
     dependencies:
-      '@pnpm/types': 1000.1.0
+      '@pnpm/types': 1000.1.1
 
   '@pnpm/resolver-base@13.0.4':
     dependencies:
@@ -11277,7 +10370,7 @@ snapshots:
     dependencies:
       strip-comments-strings: 1.2.0
 
-  '@pnpm/types@1000.1.0': {}
+  '@pnpm/types@1000.1.1': {}
 
   '@pnpm/types@11.1.0': {}
 
@@ -11334,17 +10427,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@rollup/plugin-babel@5.3.1(@babel/core@7.25.8)(@types/babel__core@7.20.5)(rollup@2.79.1)':
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-module-imports': 7.25.9
-      '@rollup/pluginutils': 3.1.0(rollup@2.79.1)
-      rollup: 2.79.1
-    optionalDependencies:
-      '@types/babel__core': 7.20.5
-    transitivePeerDependencies:
-      - supports-color
-
   '@rollup/plugin-babel@5.3.1(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@2.79.1)':
     dependencies:
       '@babel/core': 7.26.0
@@ -11377,7 +10459,7 @@ snapshots:
     dependencies:
       serialize-javascript: 6.0.2
       smob: 1.5.0
-      terser: 5.31.1
+      terser: 5.36.0
     optionalDependencies:
       rollup: 2.79.1
 
@@ -11396,27 +10478,15 @@ snapshots:
     optionalDependencies:
       rollup: 2.79.1
 
-  '@rollup/rollup-android-arm-eabi@4.18.0':
-    optional: true
-
   '@rollup/rollup-android-arm-eabi@4.30.1':
     optional: true
 
-  '@rollup/rollup-android-arm64@4.18.0':
-    optional: true
-
   '@rollup/rollup-android-arm64@4.30.1':
     optional: true
 
-  '@rollup/rollup-darwin-arm64@4.18.0':
-    optional: true
-
   '@rollup/rollup-darwin-arm64@4.30.1':
     optional: true
 
-  '@rollup/rollup-darwin-x64@4.18.0':
-    optional: true
-
   '@rollup/rollup-darwin-x64@4.30.1':
     optional: true
 
@@ -11426,78 +10496,42 @@ snapshots:
   '@rollup/rollup-freebsd-x64@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-arm-gnueabihf@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-arm-gnueabihf@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-arm-musleabihf@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-arm-musleabihf@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-arm64-gnu@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-arm64-gnu@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-arm64-musl@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-arm64-musl@4.30.1':
     optional: true
 
   '@rollup/rollup-linux-loongarch64-gnu@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-powerpc64le-gnu@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-powerpc64le-gnu@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-riscv64-gnu@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-riscv64-gnu@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-s390x-gnu@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-s390x-gnu@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-x64-gnu@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-x64-gnu@4.30.1':
     optional: true
 
-  '@rollup/rollup-linux-x64-musl@4.18.0':
-    optional: true
-
   '@rollup/rollup-linux-x64-musl@4.30.1':
     optional: true
 
-  '@rollup/rollup-win32-arm64-msvc@4.18.0':
-    optional: true
-
   '@rollup/rollup-win32-arm64-msvc@4.30.1':
     optional: true
 
-  '@rollup/rollup-win32-ia32-msvc@4.18.0':
-    optional: true
-
   '@rollup/rollup-win32-ia32-msvc@4.30.1':
     optional: true
 
-  '@rollup/rollup-win32-x64-msvc@4.18.0':
-    optional: true
-
   '@rollup/rollup-win32-x64-msvc@4.30.1':
     optional: true
 
@@ -11553,25 +10587,25 @@ snapshots:
   '@swc/helpers@0.5.5':
     dependencies:
       '@swc/counter': 0.1.3
-      tslib: 2.6.3
+      tslib: 2.8.1
 
   '@szmarczak/http-timer@5.0.1':
     dependencies:
       defer-to-connect: 2.0.1
 
-  '@tanstack/eslint-plugin-query@5.62.16(eslint@9.18.0)(typescript@5.7.3)':
+  '@tanstack/eslint-plugin-query@5.66.0(eslint@9.19.0)(typescript@5.7.3)':
     dependencies:
-      '@typescript-eslint/utils': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      eslint: 9.18.0
+      '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
+      eslint: 9.19.0
     transitivePeerDependencies:
       - supports-color
       - typescript
 
-  '@tanstack/query-core@5.64.1': {}
+  '@tanstack/query-core@5.66.0': {}
 
-  '@tanstack/react-query@5.64.1(react@18.3.1)':
+  '@tanstack/react-query@5.66.0(react@18.3.1)':
     dependencies:
-      '@tanstack/query-core': 5.64.1
+      '@tanstack/query-core': 5.66.0
       react: 18.3.1
 
   '@tanstack/react-table@8.20.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
@@ -11587,12 +10621,12 @@ snapshots:
 
   '@tootallnate/quickjs-emscripten@0.23.0': {}
 
-  '@trivago/prettier-plugin-sort-imports@5.2.1(prettier@3.4.2)':
+  '@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.4.2)':
     dependencies:
-      '@babel/generator': 7.26.2
-      '@babel/parser': 7.26.2
-      '@babel/traverse': 7.25.9
-      '@babel/types': 7.26.0
+      '@babel/generator': 7.26.5
+      '@babel/parser': 7.26.7
+      '@babel/traverse': 7.26.7
+      '@babel/types': 7.26.7
       javascript-natural-sort: 0.7.1
       lodash: 4.17.21
       prettier: 3.4.2
@@ -11612,24 +10646,24 @@ snapshots:
 
   '@types/babel__core@7.20.5':
     dependencies:
-      '@babel/parser': 7.25.8
-      '@babel/types': 7.25.8
+      '@babel/parser': 7.26.7
+      '@babel/types': 7.26.7
       '@types/babel__generator': 7.6.8
       '@types/babel__template': 7.4.4
       '@types/babel__traverse': 7.20.6
 
   '@types/babel__generator@7.6.8':
     dependencies:
-      '@babel/types': 7.26.0
+      '@babel/types': 7.26.7
 
   '@types/babel__template@7.4.4':
     dependencies:
-      '@babel/parser': 7.26.2
-      '@babel/types': 7.26.0
+      '@babel/parser': 7.26.7
+      '@babel/types': 7.26.7
 
   '@types/babel__traverse@7.20.6':
     dependencies:
-      '@babel/types': 7.26.0
+      '@babel/types': 7.26.7
 
   '@types/debug@4.1.12':
     dependencies:
@@ -11651,8 +10685,6 @@ snapshots:
 
   '@types/estree@0.0.39': {}
 
-  '@types/estree@1.0.5': {}
-
   '@types/estree@1.0.6': {}
 
   '@types/events@3.0.3': {}
@@ -11686,7 +10718,7 @@ snapshots:
 
   '@types/negotiator@0.6.3': {}
 
-  '@types/node@22.10.5':
+  '@types/node@22.13.0':
     dependencies:
       undici-types: 6.20.0
 
@@ -11715,7 +10747,7 @@ snapshots:
 
   '@types/ssri@7.1.5':
     dependencies:
-      '@types/node': 22.10.5
+      '@types/node': 22.13.0
 
   '@types/trusted-types@2.0.7': {}
 
@@ -11730,54 +10762,18 @@ snapshots:
 
   '@types/yauzl@2.10.3':
     dependencies:
-      '@types/node': 22.10.5
-    optional: true
-
-  '@typescript-eslint/eslint-plugin@8.10.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3)':
-    dependencies:
-      '@eslint-community/regexpp': 4.12.1
-      '@typescript-eslint/parser': 8.10.0(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/scope-manager': 8.10.0
-      '@typescript-eslint/type-utils': 8.10.0(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/utils': 8.10.0(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/visitor-keys': 8.10.0
-      eslint: 9.18.0
-      graphemer: 1.4.0
-      ignore: 5.3.1
-      natural-compare: 1.4.0
-      ts-api-utils: 1.3.0(typescript@5.7.3)
-    optionalDependencies:
-      typescript: 5.7.3
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3)':
-    dependencies:
-      '@eslint-community/regexpp': 4.12.1
-      '@typescript-eslint/parser': 8.10.0(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/scope-manager': 8.19.1
-      '@typescript-eslint/type-utils': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/utils': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/visitor-keys': 8.19.1
-      eslint: 9.18.0
-      graphemer: 1.4.0
-      ignore: 5.3.1
-      natural-compare: 1.4.0
-      ts-api-utils: 2.0.0(typescript@5.7.3)
-      typescript: 5.7.3
-    transitivePeerDependencies:
-      - supports-color
+      '@types/node': 22.13.0
     optional: true
 
-  '@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3)':
+  '@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3)':
     dependencies:
       '@eslint-community/regexpp': 4.12.1
-      '@typescript-eslint/parser': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/scope-manager': 8.19.1
-      '@typescript-eslint/type-utils': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/utils': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/visitor-keys': 8.19.1
-      eslint: 9.18.0
+      '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
+      '@typescript-eslint/scope-manager': 8.22.0
+      '@typescript-eslint/type-utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
+      '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
+      '@typescript-eslint/visitor-keys': 8.22.0
+      eslint: 9.19.0
       graphemer: 1.4.0
       ignore: 5.3.1
       natural-compare: 1.4.0
@@ -11786,88 +10782,41 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3)':
-    dependencies:
-      '@typescript-eslint/scope-manager': 8.10.0
-      '@typescript-eslint/types': 8.10.0
-      '@typescript-eslint/typescript-estree': 8.10.0(typescript@5.7.3)
-      '@typescript-eslint/visitor-keys': 8.10.0
-      debug: 4.3.7
-      eslint: 9.18.0
-    optionalDependencies:
-      typescript: 5.7.3
-    transitivePeerDependencies:
-      - supports-color
-
-  '@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3)':
+  '@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3)':
     dependencies:
-      '@typescript-eslint/scope-manager': 8.19.1
-      '@typescript-eslint/types': 8.19.1
-      '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.7.3)
-      '@typescript-eslint/visitor-keys': 8.19.1
+      '@typescript-eslint/scope-manager': 8.22.0
+      '@typescript-eslint/types': 8.22.0
+      '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3)
+      '@typescript-eslint/visitor-keys': 8.22.0
       debug: 4.4.0
-      eslint: 9.18.0
+      eslint: 9.19.0
       typescript: 5.7.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/scope-manager@8.10.0':
-    dependencies:
-      '@typescript-eslint/types': 8.10.0
-      '@typescript-eslint/visitor-keys': 8.10.0
-
-  '@typescript-eslint/scope-manager@8.19.1':
-    dependencies:
-      '@typescript-eslint/types': 8.19.1
-      '@typescript-eslint/visitor-keys': 8.19.1
-
-  '@typescript-eslint/type-utils@8.10.0(eslint@9.18.0)(typescript@5.7.3)':
+  '@typescript-eslint/scope-manager@8.22.0':
     dependencies:
-      '@typescript-eslint/typescript-estree': 8.10.0(typescript@5.7.3)
-      '@typescript-eslint/utils': 8.10.0(eslint@9.18.0)(typescript@5.7.3)
-      debug: 4.3.7
-      ts-api-utils: 1.3.0(typescript@5.7.3)
-    optionalDependencies:
-      typescript: 5.7.3
-    transitivePeerDependencies:
-      - eslint
-      - supports-color
+      '@typescript-eslint/types': 8.22.0
+      '@typescript-eslint/visitor-keys': 8.22.0
 
-  '@typescript-eslint/type-utils@8.19.1(eslint@9.18.0)(typescript@5.7.3)':
+  '@typescript-eslint/type-utils@8.22.0(eslint@9.19.0)(typescript@5.7.3)':
     dependencies:
-      '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.7.3)
-      '@typescript-eslint/utils': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
+      '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3)
+      '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
       debug: 4.4.0
-      eslint: 9.18.0
+      eslint: 9.19.0
       ts-api-utils: 2.0.0(typescript@5.7.3)
       typescript: 5.7.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/types@8.10.0': {}
-
-  '@typescript-eslint/types@8.19.1': {}
-
-  '@typescript-eslint/typescript-estree@8.10.0(typescript@5.7.3)':
-    dependencies:
-      '@typescript-eslint/types': 8.10.0
-      '@typescript-eslint/visitor-keys': 8.10.0
-      debug: 4.3.7
-      fast-glob: 3.3.2
-      is-glob: 4.0.3
-      minimatch: 9.0.5
-      semver: 7.6.3
-      ts-api-utils: 1.3.0(typescript@5.7.3)
-    optionalDependencies:
-      typescript: 5.7.3
-    transitivePeerDependencies:
-      - supports-color
+  '@typescript-eslint/types@8.22.0': {}
 
-  '@typescript-eslint/typescript-estree@8.19.1(typescript@5.7.3)':
+  '@typescript-eslint/typescript-estree@8.22.0(typescript@5.7.3)':
     dependencies:
-      '@typescript-eslint/types': 8.19.1
-      '@typescript-eslint/visitor-keys': 8.19.1
-      debug: 4.3.7
+      '@typescript-eslint/types': 8.22.0
+      '@typescript-eslint/visitor-keys': 8.22.0
+      debug: 4.4.0
       fast-glob: 3.3.2
       is-glob: 4.0.3
       minimatch: 9.0.5
@@ -11877,55 +10826,39 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/utils@8.10.0(eslint@9.18.0)(typescript@5.7.3)':
-    dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.18.0)
-      '@typescript-eslint/scope-manager': 8.10.0
-      '@typescript-eslint/types': 8.10.0
-      '@typescript-eslint/typescript-estree': 8.10.0(typescript@5.7.3)
-      eslint: 9.18.0
-    transitivePeerDependencies:
-      - supports-color
-      - typescript
-
-  '@typescript-eslint/utils@8.19.1(eslint@9.18.0)(typescript@5.7.3)':
+  '@typescript-eslint/utils@8.22.0(eslint@9.19.0)(typescript@5.7.3)':
     dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.18.0)
-      '@typescript-eslint/scope-manager': 8.19.1
-      '@typescript-eslint/types': 8.19.1
-      '@typescript-eslint/typescript-estree': 8.19.1(typescript@5.7.3)
-      eslint: 9.18.0
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.19.0)
+      '@typescript-eslint/scope-manager': 8.22.0
+      '@typescript-eslint/types': 8.22.0
+      '@typescript-eslint/typescript-estree': 8.22.0(typescript@5.7.3)
+      eslint: 9.19.0
       typescript: 5.7.3
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/visitor-keys@8.10.0':
-    dependencies:
-      '@typescript-eslint/types': 8.10.0
-      eslint-visitor-keys: 3.4.3
-
-  '@typescript-eslint/visitor-keys@8.19.1':
+  '@typescript-eslint/visitor-keys@8.22.0':
     dependencies:
-      '@typescript-eslint/types': 8.19.1
+      '@typescript-eslint/types': 8.22.0
       eslint-visitor-keys: 4.2.0
 
   '@ungap/structured-clone@1.2.0': {}
 
-  '@vitejs/plugin-react@4.3.4(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))':
+  '@vitejs/plugin-react@4.3.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))':
     dependencies:
       '@babel/core': 7.26.0
       '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
       '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
       '@types/babel__core': 7.20.5
       react-refresh: 0.14.2
-      vite: 5.3.1(@types/node@22.10.5)(terser@5.36.0)
+      vite: 5.3.1(@types/node@22.13.0)(terser@5.36.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@vitest/coverage-istanbul@2.1.8(vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0))':
+  '@vitest/coverage-istanbul@3.0.4(vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0))':
     dependencies:
       '@istanbuljs/schema': 0.1.3
-      debug: 4.3.7
+      debug: 4.4.0
       istanbul-lib-coverage: 3.2.2
       istanbul-lib-instrument: 6.0.3
       istanbul-lib-report: 3.0.1
@@ -11933,50 +10866,50 @@ snapshots:
       istanbul-reports: 3.1.7
       magicast: 0.3.5
       test-exclude: 7.0.1
-      tinyrainbow: 1.2.0
-      vitest: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
+      tinyrainbow: 2.0.0
+      vitest: 3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@vitest/expect@2.1.8':
+  '@vitest/expect@3.0.4':
     dependencies:
-      '@vitest/spy': 2.1.8
-      '@vitest/utils': 2.1.8
+      '@vitest/spy': 3.0.4
+      '@vitest/utils': 3.0.4
       chai: 5.1.2
-      tinyrainbow: 1.2.0
+      tinyrainbow: 2.0.0
 
-  '@vitest/mocker@2.1.8(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))':
+  '@vitest/mocker@3.0.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))':
     dependencies:
-      '@vitest/spy': 2.1.8
+      '@vitest/spy': 3.0.4
       estree-walker: 3.0.3
-      magic-string: 0.30.12
+      magic-string: 0.30.17
     optionalDependencies:
-      vite: 5.3.1(@types/node@22.10.5)(terser@5.36.0)
+      vite: 5.3.1(@types/node@22.13.0)(terser@5.36.0)
 
-  '@vitest/pretty-format@2.1.8':
+  '@vitest/pretty-format@3.0.4':
     dependencies:
-      tinyrainbow: 1.2.0
+      tinyrainbow: 2.0.0
 
-  '@vitest/runner@2.1.8':
+  '@vitest/runner@3.0.4':
     dependencies:
-      '@vitest/utils': 2.1.8
-      pathe: 1.1.2
+      '@vitest/utils': 3.0.4
+      pathe: 2.0.2
 
-  '@vitest/snapshot@2.1.8':
+  '@vitest/snapshot@3.0.4':
     dependencies:
-      '@vitest/pretty-format': 2.1.8
-      magic-string: 0.30.12
-      pathe: 1.1.2
+      '@vitest/pretty-format': 3.0.4
+      magic-string: 0.30.17
+      pathe: 2.0.2
 
-  '@vitest/spy@2.1.8':
+  '@vitest/spy@3.0.4':
     dependencies:
       tinyspy: 3.0.2
 
-  '@vitest/utils@2.1.8':
+  '@vitest/utils@3.0.4':
     dependencies:
-      '@vitest/pretty-format': 2.1.8
+      '@vitest/pretty-format': 3.0.4
       loupe: 3.1.2
-      tinyrainbow: 1.2.0
+      tinyrainbow: 2.0.0
 
   '@webassemblyjs/ast@1.12.1':
     dependencies:
@@ -12083,9 +11016,7 @@ snapshots:
 
   acorn-walk@8.3.3:
     dependencies:
-      acorn: 8.13.0
-
-  acorn@8.13.0: {}
+      acorn: 8.14.0
 
   acorn@8.14.0: {}
 
@@ -12096,12 +11027,6 @@ snapshots:
       - supports-color
     optional: true
 
-  agent-base@7.1.1:
-    dependencies:
-      debug: 4.4.0
-    transitivePeerDependencies:
-      - supports-color
-
   agent-base@7.1.3: {}
 
   agentkeepalive@4.5.0:
@@ -12264,7 +11189,7 @@ snapshots:
     dependencies:
       pvtsutils: 1.3.5
       pvutils: 1.1.3
-      tslib: 2.6.3
+      tslib: 2.8.1
 
   assertion-error@2.0.1: {}
 
@@ -12272,7 +11197,7 @@ snapshots:
 
   ast-types@0.13.4:
     dependencies:
-      tslib: 2.7.0
+      tslib: 2.8.1
 
   astral-regex@2.0.0: {}
 
@@ -12303,32 +11228,15 @@ snapshots:
       cosmiconfig: 7.1.0
       resolve: 1.22.8
 
-  babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.25.8):
-    dependencies:
-      '@babel/compat-data': 7.25.8
-      '@babel/core': 7.25.8
-      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.8)
-      semver: 6.3.1
-    transitivePeerDependencies:
-      - supports-color
-
   babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.26.0):
     dependencies:
-      '@babel/compat-data': 7.25.8
+      '@babel/compat-data': 7.26.2
       '@babel/core': 7.26.0
       '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0)
       semver: 6.3.1
     transitivePeerDependencies:
       - supports-color
 
-  babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.25.8):
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.8)
-      core-js-compat: 3.37.1
-    transitivePeerDependencies:
-      - supports-color
-
   babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.26.0):
     dependencies:
       '@babel/core': 7.26.0
@@ -12337,13 +11245,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.25.8):
-    dependencies:
-      '@babel/core': 7.25.8
-      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.8)
-    transitivePeerDependencies:
-      - supports-color
-
   babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.26.0):
     dependencies:
       '@babel/core': 7.26.0
@@ -12485,7 +11386,7 @@ snapshots:
 
   builtins@5.1.0:
     dependencies:
-      semver: 7.6.3
+      semver: 7.7.0
 
   bundle-require@5.1.0(esbuild@0.24.2):
     dependencies:
@@ -12855,10 +11756,6 @@ snapshots:
     dependencies:
       ms: 2.1.3
 
-  debug@4.3.7:
-    dependencies:
-      ms: 2.1.3
-
   debug@4.4.0:
     dependencies:
       ms: 2.1.3
@@ -13111,7 +12008,7 @@ snapshots:
       iterator.prototype: 1.1.2
       safe-array-concat: 1.1.2
 
-  es-module-lexer@1.5.4: {}
+  es-module-lexer@1.6.0: {}
 
   es-object-atoms@1.0.0:
     dependencies:
@@ -13245,19 +12142,19 @@ snapshots:
     optionalDependencies:
       source-map: 0.6.1
 
-  eslint-config-next@14.2.14(eslint@9.18.0)(typescript@5.7.3):
+  eslint-config-next@14.2.14(eslint@9.19.0)(typescript@5.7.3):
     dependencies:
       '@next/eslint-plugin-next': 14.2.14
       '@rushstack/eslint-patch': 1.10.3
-      '@typescript-eslint/eslint-plugin': 8.10.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/parser': 8.10.0(eslint@9.18.0)(typescript@5.7.3)
-      eslint: 9.18.0
+      '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3)
+      '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
+      eslint: 9.19.0
       eslint-import-resolver-node: 0.3.9
-      eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.18.0)
-      eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0)
-      eslint-plugin-jsx-a11y: 6.10.2(eslint@9.18.0)
-      eslint-plugin-react: 7.34.2(eslint@9.18.0)
-      eslint-plugin-react-hooks: 4.6.2(eslint@9.18.0)
+      eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.19.0)
+      eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
+      eslint-plugin-jsx-a11y: 6.10.2(eslint@9.19.0)
+      eslint-plugin-react: 7.34.2(eslint@9.19.0)
+      eslint-plugin-react-hooks: 4.6.2(eslint@9.19.0)
     optionalDependencies:
       typescript: 5.7.3
     transitivePeerDependencies:
@@ -13265,9 +12162,9 @@ snapshots:
       - eslint-plugin-import-x
       - supports-color
 
-  eslint-config-prettier@9.1.0(eslint@9.18.0):
+  eslint-config-prettier@10.0.1(eslint@9.19.0):
     dependencies:
-      eslint: 9.18.0
+      eslint: 9.19.0
 
   eslint-import-resolver-node@0.3.9:
     dependencies:
@@ -13277,76 +12174,37 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.18.0):
+  eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.19.0):
     dependencies:
       '@nolyfill/is-core-module': 1.0.39
-      debug: 4.3.7
+      debug: 4.4.0
       enhanced-resolve: 5.17.1
-      eslint: 9.18.0
-      eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0)
+      eslint: 9.19.0
+      eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       fast-glob: 3.3.2
       get-tsconfig: 4.7.5
       is-bun-module: 1.1.0
       is-glob: 4.0.3
     optionalDependencies:
-      eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0)
+      eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
     transitivePeerDependencies:
       - '@typescript-eslint/parser'
       - eslint-import-resolver-node
       - eslint-import-resolver-webpack
       - supports-color
 
-  eslint-module-utils@2.12.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0):
-    dependencies:
-      debug: 3.2.7
-    optionalDependencies:
-      '@typescript-eslint/parser': 8.10.0(eslint@9.18.0)(typescript@5.7.3)
-      eslint: 9.18.0
-      eslint-import-resolver-node: 0.3.9
-      eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.18.0)
-    transitivePeerDependencies:
-      - supports-color
-
-  eslint-module-utils@2.12.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.18.0):
+  eslint-module-utils@2.12.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0):
     dependencies:
       debug: 3.2.7
     optionalDependencies:
-      '@typescript-eslint/parser': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      eslint: 9.18.0
-      eslint-import-resolver-node: 0.3.9
-    transitivePeerDependencies:
-      - supports-color
-
-  eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0):
-    dependencies:
-      '@rtsao/scc': 1.1.0
-      array-includes: 3.1.8
-      array.prototype.findlastindex: 1.2.5
-      array.prototype.flat: 1.3.2
-      array.prototype.flatmap: 1.3.2
-      debug: 3.2.7
-      doctrine: 2.1.0
-      eslint: 9.18.0
+      '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
+      eslint: 9.19.0
       eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.18.0)
-      hasown: 2.0.2
-      is-core-module: 2.15.1
-      is-glob: 4.0.3
-      minimatch: 3.1.2
-      object.fromentries: 2.0.8
-      object.groupby: 1.0.3
-      object.values: 1.2.0
-      semver: 6.3.1
-      string.prototype.trimend: 1.0.8
-      tsconfig-paths: 3.15.0
-    optionalDependencies:
-      '@typescript-eslint/parser': 8.10.0(eslint@9.18.0)(typescript@5.7.3)
+      eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.31.0)(eslint@9.19.0)
     transitivePeerDependencies:
-      - eslint-import-resolver-typescript
-      - eslint-import-resolver-webpack
       - supports-color
 
-  eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0):
+  eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0):
     dependencies:
       '@rtsao/scc': 1.1.0
       array-includes: 3.1.8
@@ -13355,9 +12213,9 @@ snapshots:
       array.prototype.flatmap: 1.3.2
       debug: 3.2.7
       doctrine: 2.1.0
-      eslint: 9.18.0
+      eslint: 9.19.0
       eslint-import-resolver-node: 0.3.9
-      eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@9.18.0)
+      eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@9.19.0)
       hasown: 2.0.2
       is-core-module: 2.15.1
       is-glob: 4.0.3
@@ -13369,13 +12227,13 @@ snapshots:
       string.prototype.trimend: 1.0.8
       tsconfig-paths: 3.15.0
     optionalDependencies:
-      '@typescript-eslint/parser': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
+      '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
     transitivePeerDependencies:
       - eslint-import-resolver-typescript
       - eslint-import-resolver-webpack
       - supports-color
 
-  eslint-plugin-jsx-a11y@6.10.2(eslint@9.18.0):
+  eslint-plugin-jsx-a11y@6.10.2(eslint@9.19.0):
     dependencies:
       aria-query: 5.3.2
       array-includes: 3.1.8
@@ -13385,7 +12243,7 @@ snapshots:
       axobject-query: 4.1.0
       damerau-levenshtein: 1.0.8
       emoji-regex: 9.2.2
-      eslint: 9.18.0
+      eslint: 9.19.0
       hasown: 2.0.2
       jsx-ast-utils: 3.3.5
       language-tags: 1.0.9
@@ -13394,16 +12252,16 @@ snapshots:
       safe-regex-test: 1.0.3
       string.prototype.includes: 2.0.1
 
-  eslint-plugin-promise@7.2.1(eslint@9.18.0):
+  eslint-plugin-promise@7.2.1(eslint@9.19.0):
     dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.18.0)
-      eslint: 9.18.0
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.19.0)
+      eslint: 9.19.0
 
-  eslint-plugin-react-hooks@4.6.2(eslint@9.18.0):
+  eslint-plugin-react-hooks@4.6.2(eslint@9.19.0):
     dependencies:
-      eslint: 9.18.0
+      eslint: 9.19.0
 
-  eslint-plugin-react@7.34.2(eslint@9.18.0):
+  eslint-plugin-react@7.34.2(eslint@9.19.0):
     dependencies:
       array-includes: 3.1.8
       array.prototype.findlast: 1.2.5
@@ -13412,7 +12270,7 @@ snapshots:
       array.prototype.tosorted: 1.1.4
       doctrine: 2.1.0
       es-iterator-helpers: 1.0.19
-      eslint: 9.18.0
+      eslint: 9.19.0
       estraverse: 5.3.0
       jsx-ast-utils: 3.3.5
       minimatch: 3.1.2
@@ -13425,17 +12283,11 @@ snapshots:
       semver: 6.3.1
       string.prototype.matchall: 4.0.11
 
-  eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0):
-    dependencies:
-      eslint: 9.18.0
-    optionalDependencies:
-      '@typescript-eslint/eslint-plugin': 8.19.1(@typescript-eslint/parser@8.10.0(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3)
-
-  eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0):
+  eslint-plugin-unused-imports@4.1.4(@typescript-eslint/eslint-plugin@8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0):
     dependencies:
-      eslint: 9.18.0
+      eslint: 9.19.0
     optionalDependencies:
-      '@typescript-eslint/eslint-plugin': 8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3)
+      '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3)
 
   eslint-scope@5.1.1:
     dependencies:
@@ -13451,14 +12303,14 @@ snapshots:
 
   eslint-visitor-keys@4.2.0: {}
 
-  eslint@9.18.0:
+  eslint@9.19.0:
     dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.18.0)
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.19.0)
       '@eslint-community/regexpp': 4.12.1
       '@eslint/config-array': 0.19.0
       '@eslint/core': 0.10.0
       '@eslint/eslintrc': 3.2.0
-      '@eslint/js': 9.18.0
+      '@eslint/js': 9.19.0
       '@eslint/plugin-kit': 0.2.5
       '@humanfs/node': 0.16.6
       '@humanwhocodes/module-importer': 1.0.1
@@ -13468,7 +12320,7 @@ snapshots:
       ajv: 6.12.6
       chalk: 4.1.2
       cross-spawn: 7.0.6
-      debug: 4.3.7
+      debug: 4.4.0
       escape-string-regexp: 4.0.0
       eslint-scope: 8.2.0
       eslint-visitor-keys: 4.2.0
@@ -13688,7 +12540,7 @@ snapshots:
       react: 18.3.1
       react-fast-compare: 2.0.4
       tiny-warning: 1.0.3
-      tslib: 2.7.0
+      tslib: 2.8.1
 
   fs-constants@1.0.0:
     optional: true
@@ -13849,7 +12701,7 @@ snapshots:
       es6-error: 4.1.1
       matcher: 3.0.0
       roarr: 2.15.4
-      semver: 7.6.3
+      semver: 7.7.0
       serialize-error: 7.0.1
 
   globals@11.12.0: {}
@@ -13879,7 +12731,7 @@ snapshots:
       lowercase-keys: 3.0.0
       p-cancelable: 4.0.1
       responselike: 3.0.0
-      type-fest: 4.29.0
+      type-fest: 4.32.0
 
   graceful-fs@4.2.10: {}
 
@@ -14039,13 +12891,6 @@ snapshots:
       - supports-color
     optional: true
 
-  https-proxy-agent@7.0.5:
-    dependencies:
-      agent-base: 7.1.1
-      debug: 4.4.0
-    transitivePeerDependencies:
-      - supports-color
-
   https-proxy-agent@7.0.6:
     dependencies:
       agent-base: 7.1.3
@@ -14064,7 +12909,7 @@ snapshots:
     dependencies:
       '@babel/runtime': 7.25.6
 
-  i18next@24.2.1(typescript@5.7.3):
+  i18next@24.2.2(typescript@5.7.3):
     dependencies:
       '@babel/runtime': 7.25.6
     optionalDependencies:
@@ -14292,10 +13137,10 @@ snapshots:
   istanbul-lib-instrument@6.0.3:
     dependencies:
       '@babel/core': 7.26.0
-      '@babel/parser': 7.26.2
+      '@babel/parser': 7.26.7
       '@istanbuljs/schema': 0.1.3
       istanbul-lib-coverage: 3.2.2
-      semver: 7.6.3
+      semver: 7.7.0
     transitivePeerDependencies:
       - supports-color
 
@@ -14308,7 +13153,7 @@ snapshots:
   istanbul-lib-source-maps@5.0.6:
     dependencies:
       '@jridgewell/trace-mapping': 0.3.25
-      debug: 4.3.7
+      debug: 4.4.0
       istanbul-lib-coverage: 3.2.2
     transitivePeerDependencies:
       - supports-color
@@ -14355,7 +13200,7 @@ snapshots:
 
   jest-worker@27.5.1:
     dependencies:
-      '@types/node': 22.10.5
+      '@types/node': 22.13.0
       merge-stream: 2.0.0
       supports-color: 8.1.1
 
@@ -14522,19 +13367,19 @@ snapshots:
     dependencies:
       sourcemap-codec: 1.4.8
 
-  magic-string@0.30.12:
+  magic-string@0.30.17:
     dependencies:
       '@jridgewell/sourcemap-codec': 1.5.0
 
   magicast@0.3.5:
     dependencies:
-      '@babel/parser': 7.26.2
-      '@babel/types': 7.26.0
+      '@babel/parser': 7.26.7
+      '@babel/types': 7.26.7
       source-map-js: 1.2.0
 
   make-dir@4.0.0:
     dependencies:
-      semver: 7.6.3
+      semver: 7.7.0
 
   make-fetch-happen@13.0.1:
     dependencies:
@@ -15128,7 +13973,7 @@ snapshots:
 
   netmask@2.0.2: {}
 
-  next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.50.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
     dependencies:
       '@next/env': 14.2.14
       '@swc/helpers': 0.5.5
@@ -15149,14 +13994,14 @@ snapshots:
       '@next/swc-win32-arm64-msvc': 14.2.14
       '@next/swc-win32-ia32-msvc': 14.2.14
       '@next/swc-win32-x64-msvc': 14.2.14
-      '@playwright/test': 1.49.1
+      '@playwright/test': 1.50.1
     transitivePeerDependencies:
       - '@babel/core'
       - babel-plugin-macros
 
   node-abi@3.65.0:
     dependencies:
-      semver: 7.6.3
+      semver: 7.7.0
     optional: true
 
   node-addon-api@7.1.0:
@@ -15173,7 +14018,7 @@ snapshots:
       make-fetch-happen: 13.0.1
       nopt: 7.2.1
       proc-log: 3.0.0
-      semver: 7.6.3
+      semver: 7.7.0
       tar: 6.2.1
       which: 4.0.0
     transitivePeerDependencies:
@@ -15188,7 +14033,7 @@ snapshots:
       nopt: 5.0.0
       npmlog: 6.0.2
       rimraf: 3.0.2
-      semver: 7.6.3
+      semver: 7.7.0
       tar: 6.2.1
       which: 2.0.2
     transitivePeerDependencies:
@@ -15217,20 +14062,20 @@ snapshots:
     dependencies:
       hosted-git-info: 4.1.0
       is-core-module: 2.15.1
-      semver: 7.6.3
+      semver: 7.7.0
       validate-npm-package-license: 3.0.4
 
   normalize-package-data@4.0.1:
     dependencies:
       hosted-git-info: 5.2.1
       is-core-module: 2.15.1
-      semver: 7.6.3
+      semver: 7.7.0
       validate-npm-package-license: 3.0.4
 
   normalize-package-data@7.0.0:
     dependencies:
       hosted-git-info: 8.0.0
-      semver: 7.6.3
+      semver: 7.7.0
       validate-npm-package-license: 3.0.4
 
   normalize-path@3.0.0: {}
@@ -15245,7 +14090,7 @@ snapshots:
 
   npm-install-checks@7.1.0:
     dependencies:
-      semver: 7.6.3
+      semver: 7.7.0
 
   npm-normalize-package-bin@4.0.0: {}
 
@@ -15253,7 +14098,7 @@ snapshots:
     dependencies:
       hosted-git-info: 8.0.0
       proc-log: 5.0.0
-      semver: 7.6.3
+      semver: 7.7.0
       validate-npm-package-name: 6.0.0
 
   npm-packlist@10.0.0:
@@ -15265,7 +14110,7 @@ snapshots:
       npm-install-checks: 7.1.0
       npm-normalize-package-bin: 4.0.0
       npm-package-arg: 12.0.0
-      semver: 7.6.3
+      semver: 7.7.0
 
   npm-registry-fetch@18.0.2:
     dependencies:
@@ -15534,13 +14379,13 @@ snapshots:
 
   path-type@4.0.0: {}
 
-  pathe@1.1.2: {}
+  pathe@2.0.2: {}
 
   pathval@2.0.0: {}
 
   pdf-parse-new@1.3.9:
     dependencies:
-      debug: 4.3.7
+      debug: 4.4.0
       node-ensure: 0.0.0
     transitivePeerDependencies:
       - supports-color
@@ -15550,8 +14395,6 @@ snapshots:
   pg-connection-string@2.6.4:
     optional: true
 
-  picocolors@1.1.0: {}
-
   picocolors@1.1.1: {}
 
   picomatch@2.3.1: {}
@@ -15562,18 +14405,18 @@ snapshots:
 
   pkijs@3.2.4:
     dependencies:
-      '@noble/hashes': 1.4.0
+      '@noble/hashes': 1.6.0
       asn1js: 3.0.5
       bytestreamjs: 2.0.1
       pvtsutils: 1.3.5
       pvutils: 1.1.3
-      tslib: 2.6.3
+      tslib: 2.8.1
 
-  playwright-core@1.49.1: {}
+  playwright-core@1.50.1: {}
 
-  playwright@1.49.1:
+  playwright@1.50.1:
     dependencies:
-      playwright-core: 1.49.1
+      playwright-core: 1.50.1
     optionalDependencies:
       fsevents: 2.3.2
 
@@ -15594,13 +14437,13 @@ snapshots:
   postcss@8.4.31:
     dependencies:
       nanoid: 3.3.7
-      picocolors: 1.1.0
+      picocolors: 1.1.1
       source-map-js: 1.2.0
 
   postcss@8.4.38:
     dependencies:
       nanoid: 3.3.7
-      picocolors: 1.1.0
+      picocolors: 1.1.1
       source-map-js: 1.2.0
 
   preact@10.12.1: {}
@@ -15698,7 +14541,7 @@ snapshots:
 
   pvtsutils@1.3.5:
     dependencies:
-      tslib: 2.6.3
+      tslib: 2.8.1
 
   pvutils@1.1.3: {}
 
@@ -15754,11 +14597,11 @@ snapshots:
 
   react-fast-compare@2.0.4: {}
 
-  react-i18next@15.4.0(i18next@24.2.1(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-i18next@15.4.0(i18next@24.2.2(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
     dependencies:
       '@babel/runtime': 7.25.6
       html-parse-stringify: 3.0.1
-      i18next: 24.2.1(typescript@5.7.3)
+      i18next: 24.2.2(typescript@5.7.3)
       react: 18.3.1
     optionalDependencies:
       react-dom: 18.3.1(react@18.3.1)
@@ -15953,9 +14796,9 @@ snapshots:
       unified: 11.0.5
       vfile: 6.0.3
 
-  remeda@2.19.0:
+  remeda@2.20.1:
     dependencies:
-      type-fest: 4.32.0
+      type-fest: 4.33.0
 
   require-directory@2.1.1: {}
 
@@ -16025,28 +14868,6 @@ snapshots:
     optionalDependencies:
       fsevents: 2.3.3
 
-  rollup@4.18.0:
-    dependencies:
-      '@types/estree': 1.0.5
-    optionalDependencies:
-      '@rollup/rollup-android-arm-eabi': 4.18.0
-      '@rollup/rollup-android-arm64': 4.18.0
-      '@rollup/rollup-darwin-arm64': 4.18.0
-      '@rollup/rollup-darwin-x64': 4.18.0
-      '@rollup/rollup-linux-arm-gnueabihf': 4.18.0
-      '@rollup/rollup-linux-arm-musleabihf': 4.18.0
-      '@rollup/rollup-linux-arm64-gnu': 4.18.0
-      '@rollup/rollup-linux-arm64-musl': 4.18.0
-      '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0
-      '@rollup/rollup-linux-riscv64-gnu': 4.18.0
-      '@rollup/rollup-linux-s390x-gnu': 4.18.0
-      '@rollup/rollup-linux-x64-gnu': 4.18.0
-      '@rollup/rollup-linux-x64-musl': 4.18.0
-      '@rollup/rollup-win32-arm64-msvc': 4.18.0
-      '@rollup/rollup-win32-ia32-msvc': 4.18.0
-      '@rollup/rollup-win32-x64-msvc': 4.18.0
-      fsevents: 2.3.3
-
   rollup@4.30.1:
     dependencies:
       '@types/estree': 1.0.6
@@ -16078,7 +14899,7 @@ snapshots:
 
   rxjs@7.8.1:
     dependencies:
-      tslib: 2.7.0
+      tslib: 2.8.1
 
   safe-array-concat@1.1.2:
     dependencies:
@@ -16123,6 +14944,8 @@ snapshots:
 
   semver@7.6.3: {}
 
+  semver@7.7.0: {}
+
   sequelize-pool@7.1.0:
     optional: true
 
@@ -16130,7 +14953,7 @@ snapshots:
     dependencies:
       '@types/debug': 4.1.12
       '@types/validator': 13.12.0
-      debug: 4.3.7
+      debug: 4.4.0
       dottie: 2.0.6
       inflection: 1.13.4
       lodash: 4.17.21
@@ -16138,7 +14961,7 @@ snapshots:
       moment-timezone: 0.5.45
       pg-connection-string: 2.6.4
       retry-as-promised: 7.0.4
-      semver: 7.6.3
+      semver: 7.7.0
       sequelize-pool: 7.1.0
       toposort-class: 1.0.1
       uuid: 8.3.2
@@ -16255,14 +15078,6 @@ snapshots:
       - supports-color
     optional: true
 
-  socks-proxy-agent@8.0.4:
-    dependencies:
-      agent-base: 7.1.1
-      debug: 4.4.0
-      socks: 2.8.3
-    transitivePeerDependencies:
-      - supports-color
-
   socks-proxy-agent@8.0.5:
     dependencies:
       agent-base: 7.1.3
@@ -16591,13 +15406,6 @@ snapshots:
       terser: 5.36.0
       webpack: 5.92.1
 
-  terser@5.31.1:
-    dependencies:
-      '@jridgewell/source-map': 0.3.6
-      acorn: 8.14.0
-      commander: 2.20.3
-      source-map-support: 0.5.21
-
   terser@5.36.0:
     dependencies:
       '@jridgewell/source-map': 0.3.6
@@ -16633,21 +15441,19 @@ snapshots:
 
   tinybench@2.9.0: {}
 
-  tinyexec@0.3.1: {}
+  tinyexec@0.3.2: {}
 
   tinyglobby@0.2.10:
     dependencies:
       fdir: 6.4.3(picomatch@4.0.2)
       picomatch: 4.0.2
 
-  tinypool@1.0.1: {}
+  tinypool@1.0.2: {}
 
-  tinyrainbow@1.2.0: {}
+  tinyrainbow@2.0.0: {}
 
   tinyspy@3.0.2: {}
 
-  to-fast-properties@2.0.0: {}
-
   to-regex-range@5.0.1:
     dependencies:
       is-number: 7.0.0
@@ -16674,10 +15480,6 @@ snapshots:
 
   trough@2.2.0: {}
 
-  ts-api-utils@1.3.0(typescript@5.7.3):
-    dependencies:
-      typescript: 5.7.3
-
   ts-api-utils@2.0.0(typescript@5.7.3):
     dependencies:
       typescript: 5.7.3
@@ -16697,11 +15499,9 @@ snapshots:
 
   tslib@2.3.0: {}
 
-  tslib@2.6.3: {}
-
-  tslib@2.7.0: {}
+  tslib@2.8.1: {}
 
-  tsup@8.3.5(postcss@8.4.38)(tsx@4.19.2)(typescript@5.7.3):
+  tsup@8.3.6(postcss@8.4.38)(tsx@4.19.2)(typescript@5.7.3):
     dependencies:
       bundle-require: 5.1.0(esbuild@0.24.2)
       cac: 6.7.14
@@ -16716,7 +15516,7 @@ snapshots:
       rollup: 4.30.1
       source-map: 0.8.0-beta.0
       sucrase: 3.35.0
-      tinyexec: 0.3.1
+      tinyexec: 0.3.2
       tinyglobby: 0.2.10
       tree-kill: 1.2.2
     optionalDependencies:
@@ -16764,10 +15564,10 @@ snapshots:
 
   type-fest@3.13.1: {}
 
-  type-fest@4.29.0: {}
-
   type-fest@4.32.0: {}
 
+  type-fest@4.33.0: {}
+
   type-is@1.6.18:
     dependencies:
       media-typer: 0.3.0
@@ -16810,12 +15610,12 @@ snapshots:
     dependencies:
       is-typedarray: 1.0.0
 
-  typescript-eslint@8.19.1(eslint@9.18.0)(typescript@5.7.3):
+  typescript-eslint@8.22.0(eslint@9.19.0)(typescript@5.7.3):
     dependencies:
-      '@typescript-eslint/eslint-plugin': 8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@5.7.3))(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/parser': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      '@typescript-eslint/utils': 8.19.1(eslint@9.18.0)(typescript@5.7.3)
-      eslint: 9.18.0
+      '@typescript-eslint/eslint-plugin': 8.22.0(@typescript-eslint/parser@8.22.0(eslint@9.19.0)(typescript@5.7.3))(eslint@9.19.0)(typescript@5.7.3)
+      '@typescript-eslint/parser': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
+      '@typescript-eslint/utils': 8.22.0(eslint@9.19.0)(typescript@5.7.3)
+      eslint: 9.19.0
       typescript: 5.7.3
     transitivePeerDependencies:
       - supports-color
@@ -16931,7 +15731,7 @@ snapshots:
     dependencies:
       browserslist: 4.24.0
       escalade: 3.2.0
-      picocolors: 1.1.0
+      picocolors: 1.1.1
 
   uri-js@4.4.1:
     dependencies:
@@ -16958,8 +15758,6 @@ snapshots:
   utils-merge@1.0.1:
     optional: true
 
-  uuid@11.0.3: {}
-
   uuid@11.0.5: {}
 
   uuid@8.3.2:
@@ -16998,13 +15796,13 @@ snapshots:
       '@types/unist': 3.0.3
       vfile-message: 4.0.2
 
-  vite-node@2.1.8(@types/node@22.10.5)(terser@5.36.0):
+  vite-node@3.0.4(@types/node@22.13.0)(terser@5.36.0):
     dependencies:
       cac: 6.7.14
-      debug: 4.3.7
-      es-module-lexer: 1.5.4
-      pathe: 1.1.2
-      vite: 5.3.1(@types/node@22.10.5)(terser@5.36.0)
+      debug: 4.4.0
+      es-module-lexer: 1.6.0
+      pathe: 2.0.2
+      vite: 5.3.1(@types/node@22.13.0)(terser@5.36.0)
     transitivePeerDependencies:
       - '@types/node'
       - less
@@ -17015,51 +15813,52 @@ snapshots:
       - supports-color
       - terser
 
-  vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0)):
+  vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0)):
     dependencies:
-      debug: 4.3.7
+      debug: 4.4.0
       globrex: 0.1.2
       tsconfck: 3.1.0(typescript@5.7.3)
     optionalDependencies:
-      vite: 5.3.1(@types/node@22.10.5)(terser@5.36.0)
+      vite: 5.3.1(@types/node@22.13.0)(terser@5.36.0)
     transitivePeerDependencies:
       - supports-color
       - typescript
 
-  vite@5.3.1(@types/node@22.10.5)(terser@5.36.0):
+  vite@5.3.1(@types/node@22.13.0)(terser@5.36.0):
     dependencies:
       esbuild: 0.21.5
       postcss: 8.4.38
-      rollup: 4.18.0
+      rollup: 4.30.1
     optionalDependencies:
-      '@types/node': 22.10.5
+      '@types/node': 22.13.0
       fsevents: 2.3.3
       terser: 5.36.0
 
-  vitest@2.1.8(@types/node@22.10.5)(terser@5.36.0):
+  vitest@3.0.4(@types/debug@4.1.12)(@types/node@22.13.0)(terser@5.36.0):
     dependencies:
-      '@vitest/expect': 2.1.8
-      '@vitest/mocker': 2.1.8(vite@5.3.1(@types/node@22.10.5)(terser@5.36.0))
-      '@vitest/pretty-format': 2.1.8
-      '@vitest/runner': 2.1.8
-      '@vitest/snapshot': 2.1.8
-      '@vitest/spy': 2.1.8
-      '@vitest/utils': 2.1.8
+      '@vitest/expect': 3.0.4
+      '@vitest/mocker': 3.0.4(vite@5.3.1(@types/node@22.13.0)(terser@5.36.0))
+      '@vitest/pretty-format': 3.0.4
+      '@vitest/runner': 3.0.4
+      '@vitest/snapshot': 3.0.4
+      '@vitest/spy': 3.0.4
+      '@vitest/utils': 3.0.4
       chai: 5.1.2
-      debug: 4.3.7
+      debug: 4.4.0
       expect-type: 1.1.0
-      magic-string: 0.30.12
-      pathe: 1.1.2
+      magic-string: 0.30.17
+      pathe: 2.0.2
       std-env: 3.8.0
       tinybench: 2.9.0
-      tinyexec: 0.3.1
-      tinypool: 1.0.1
-      tinyrainbow: 1.2.0
-      vite: 5.3.1(@types/node@22.10.5)(terser@5.36.0)
-      vite-node: 2.1.8(@types/node@22.10.5)(terser@5.36.0)
+      tinyexec: 0.3.2
+      tinypool: 1.0.2
+      tinyrainbow: 2.0.0
+      vite: 5.3.1(@types/node@22.13.0)(terser@5.36.0)
+      vite-node: 3.0.4(@types/node@22.13.0)(terser@5.36.0)
       why-is-node-running: 2.3.0
     optionalDependencies:
-      '@types/node': 22.10.5
+      '@types/debug': 4.1.12
+      '@types/node': 22.13.0
     transitivePeerDependencies:
       - less
       - lightningcss
@@ -17088,7 +15887,7 @@ snapshots:
   webpack-bundle-analyzer@4.10.1:
     dependencies:
       '@discoveryjs/json-ext': 0.5.7
-      acorn: 8.13.0
+      acorn: 8.14.0
       acorn-walk: 8.3.3
       commander: 7.2.0
       debounce: 1.2.1
@@ -17097,7 +15896,7 @@ snapshots:
       html-escaper: 2.0.2
       is-plain-object: 5.0.0
       opener: 1.5.2
-      picocolors: 1.1.0
+      picocolors: 1.1.1
       sirv: 2.0.4
       ws: 7.5.10
     transitivePeerDependencies:
@@ -17123,7 +15922,7 @@ snapshots:
       browserslist: 4.24.0
       chrome-trace-event: 1.0.4
       enhanced-resolve: 5.17.1
-      es-module-lexer: 1.5.4
+      es-module-lexer: 1.6.0
       eslint-scope: 5.1.1
       events: 3.3.0
       glob-to-regexp: 0.4.1
@@ -17220,7 +16019,7 @@ snapshots:
 
   wkx@0.5.0:
     dependencies:
-      '@types/node': 22.10.5
+      '@types/node': 22.13.0
     optional: true
 
   word-wrap@1.2.5: {}
@@ -17285,10 +16084,10 @@ snapshots:
   workbox-build@7.1.1(@types/babel__core@7.20.5):
     dependencies:
       '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1)
-      '@babel/core': 7.25.8
-      '@babel/preset-env': 7.24.7(@babel/core@7.25.8)
+      '@babel/core': 7.26.0
+      '@babel/preset-env': 7.24.7(@babel/core@7.26.0)
       '@babel/runtime': 7.25.6
-      '@rollup/plugin-babel': 5.3.1(@babel/core@7.25.8)(@types/babel__core@7.20.5)(rollup@2.79.1)
+      '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@2.79.1)
       '@rollup/plugin-node-resolve': 15.2.3(rollup@2.79.1)
       '@rollup/plugin-replace': 2.4.2(rollup@2.79.1)
       '@rollup/plugin-terser': 0.4.4(rollup@2.79.1)
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index b7f933c5c91ae01e949e181d54b02a5e1d621685..ded4df4f79601a591d251a4732bdb524109f06e1 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -3,12 +3,9 @@
 
 packages:
   - "employee-portal"
-  - "employee-portal-api"
   - "citizen-portal"
-  - "citizen-portal-api"
   - "admin-portal"
   - "e2e"
-  - "e2e-api"
   - "lib-portal"
   - "performance-test"
   - "packages/*"
@@ -36,7 +33,7 @@ catalogs:
     "@fontsource/source-code-pro": "5.1.1"
 
   i18next:
-    "i18next": "24.2.1"
+    "i18next": "24.2.2"
     "i18next-resources-to-backend": "1.2.1"
     "react-i18next": "15.4.0"
 
@@ -49,41 +46,42 @@ catalogs:
     "@fullcalendar/timegrid": "6.1.15"
 
   eslint:
-    "eslint": "9.18.0"
-    "typescript-eslint": "8.19.1"
-    "@eslint/compat": "1.2.5"
+    "eslint": "9.19.0"
+    "typescript-eslint": "8.22.0"
+    "@eslint/compat": "1.2.6"
     "@eslint/eslintrc": "3.2.0"
-    "@eslint/js": "9.18.0"
-    "eslint-config-prettier": "9.1.0"
+    "@eslint/js": "9.19.0"
+    "eslint-config-prettier": "10.0.1"
     "eslint-plugin-import": "2.31.0"
     "eslint-plugin-unused-imports": "4.1.4"
     "eslint-plugin-promise": "7.2.1"
 
   prettier:
     "prettier": "3.4.2"
-    "@trivago/prettier-plugin-sort-imports": "5.2.1"
+    "@trivago/prettier-plugin-sort-imports": "5.2.2"
 
   vitest:
-    "vitest": "2.1.8"
-    "@vitest/coverage-istanbul": "2.1.8"
+    "vitest": "3.0.4"
+    "@vitest/coverage-istanbul": "3.0.4"
     "@vitejs/plugin-react": "4.3.4"
     "vite-tsconfig-paths": "5.1.4"
 
   common:
     "typescript": "5.7.3"
-    "@types/node": "22.10.5"
-    "@tanstack/react-query": "5.64.1"
-    "@tanstack/eslint-plugin-query": "5.62.16"
+    "@types/node": "22.13.0"
+    "@tanstack/react-query": "5.66.0"
+    "@tanstack/eslint-plugin-query": "5.66.0"
     "@tanstack/react-table": "8.20.6"
     "date-fns": "4.1.0"
     "formik": "2.4.6"
     "react-error-boundary": "5.0.0"
-    "remeda": "2.19.0"
+    "remeda": "2.20.1"
     "server-only": "0.0.1"
     "valibot": "0.42.1"
     "use-debounce": "10.0.4"
     "uuid": "11.0.5"
     "drauu": "0.4.2"
-    "tsup": "8.3.5"
+    "tsup": "8.3.6"
     "zustand": "5.0.3"
     "resolve-tspaths": "0.8.23"
+    "@keycloak/keycloak-admin-client": "26.1.0"
diff --git a/reverse-proxy/citizen-portal.conf b/reverse-proxy/citizen-portal.conf
index 84cf08732011c8cec1bddc302d45eb075e793b43..45feb0aef975f97ee475c17c0d5b25b32b578df2 100644
--- a/reverse-proxy/citizen-portal.conf
+++ b/reverse-proxy/citizen-portal.conf
@@ -1,3 +1,4 @@
+
 server {
     listen       4001;
     server_name  reverse-proxy;
@@ -183,7 +184,7 @@ server {
         proxy_pass http://host.docker.internal:3001;
     }
 
-    location ~ ^/((en|de)/)?(einschulungsuntersuchung/.+|(?:unternehmen/)?mein-bereich/.+|impfberatung/meine-termine(?:/.+)?)$ {
+    location ~ ^/((en|de)/)?(einschulungsuntersuchung/.+|(?:unternehmen/)?mein-bereich/.+|impfberatung/meine-termine(?:/.+)?|sexuellegesundheit/.+/termin)$ {
         include auth_request.conf;
 
         auth_request_set $resolved_location $upstream_http_location;
diff --git a/settings.gradle b/settings.gradle
index 750d6046d438628ae160aa76a0de38a5bc70f64a..3be9a450005807476d56d6e11342b599b9e68f9e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -3,12 +3,9 @@ rootProject.name = 'ga-lotse-code'
 includeBuild 'backend'
 
 include 'employee-portal'
-include 'employee-portal-api'
 include 'citizen-portal'
-include 'citizen-portal-api'
 include 'admin-portal'
 include 'e2e'
-include 'e2e-api'
 include 'lib-portal'
 include 'performance-test'
 include 'k8s'
diff --git a/vitest.config.ts b/vitest.config.ts
index 9d7c948631c463177d13e2cceb075861d0c7f89f..45bde8e4a33d0387b61a743cd775edb5dc9bd001 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -11,8 +11,15 @@ import { VITEST_COVERAGE_EXCLUDES, VITEST_OUT_DIR } from "./config/vitest.base";
 // https://vitejs.dev/config/
 export default defineConfig({
   test: {
+    workspace: [
+      "employee-portal",
+      "citizen-portal",
+      "admin-portal",
+      "lib-portal",
+      "packages/*",
+    ],
     environment: "node",
-    reporters: ["basic", "junit"],
+    reporters: ["default", "junit"],
     outputFile: {
       junit: `${VITEST_OUT_DIR}/junit.xml`,
     },
@@ -23,9 +30,11 @@ export default defineConfig({
       reporter: ["text", "html", "cobertura"],
       include: ["**/src/**/*"],
       exclude: [
-        "*-api",
+        "packages/*-api",
         "e2e",
         "performance-test",
+        "**/build",
+        "**/.next",
         ...VITEST_COVERAGE_EXCLUDES,
       ],
     },
diff --git a/vitest.workspace.ts b/vitest.workspace.ts
deleted file mode 100644
index 0654eca6e03872af9059686d200431e997f1b9e2..0000000000000000000000000000000000000000
--- a/vitest.workspace.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Copyright 2025 cronn GmbH
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-
-import { defineWorkspace } from "vitest/config";
-
-export default defineWorkspace([
-  "employee-portal",
-  "citizen-portal",
-  "admin-portal",
-  "lib-portal",
-]);