diff --git a/Jenkinsfile b/Jenkinsfile
index ef44d538b0f0f4cf970a4f323f586c31d43b6f5c..c28bf0d2fa1f10b024edee98db52ddecd73f2b6b 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -44,6 +44,7 @@ pipeline {
                 }
             }
         }
+   
         stage('Client') {
             environment {
                 FORCE_COLOR = 'false'
@@ -83,7 +84,29 @@ pipeline {
 //                }
 //            }
         }
-        stage('Server') {
+
+        stage('Set Version') {
+          when {
+            not {
+                anyOf {
+                    branch 'master'
+                    branch 'release'
+                }
+            }
+          }
+          steps {
+                script {
+                    FAILED_STAGE=env.STAGE_NAME
+                    JAR_TAG = getRootPomVersion().replace("SNAPSHOT", "${env.BRANCH_NAME}-SNAPSHOT")
+                }
+                configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) {
+                    sh "mvn -s $MAVEN_SETTINGS versions:set -DnewVersion=${JAR_TAG} -DprocessAllModules=true"
+                    
+                }
+          }
+        }
+
+        stage('Build Server artefacts, build and push docker image') {
             steps {
                 script {
                     FAILED_STAGE=env.STAGE_NAME
@@ -120,12 +143,6 @@ pipeline {
             }
         }
         stage('Deploy Maven Artifacts to Nexus') {
-            when {
-                anyOf {
-                    branch 'master'
-                    branch 'release'
-                }
-            }
             steps {
                 script {
                     FAILED_STAGE = env.STAGE_NAME
@@ -133,6 +150,7 @@ pipeline {
 
                 configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) {
                     sh 'mvn --no-transfer-progress -s $MAVEN_SETTINGS -pl -alfa-client -DskipTests deploy'
+                    sh "mvn -s $MAVEN_SETTINGS versions:revert"
                 }
             }
         }
@@ -143,6 +161,7 @@ pipeline {
                     branch 'release'
                 }
             }
+         
             steps {
                 script {
                     FAILED_STAGE = env.STAGE_NAME
diff --git a/alfa-client/Jenkinsfile.storybook b/alfa-client/Jenkinsfile.storybook
new file mode 100644
index 0000000000000000000000000000000000000000..b589706023ff460ecc9ec5c164b431b464c8c610
--- /dev/null
+++ b/alfa-client/Jenkinsfile.storybook
@@ -0,0 +1,248 @@
+pipeline {
+  agent {
+    node {
+      label 'ozgcloud-jenkins-build-agent'
+    }
+  }
+
+  environment {
+        BLUE_OCEAN_URL = "https://jenkins.infra.ozg-cloud.systems/job/storybook/job/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/"
+        RELEASE_REGEX = /\d+.\d+.\d+/
+        SNAPSHOT_REGEX = /\d+.\d+.\d+-SNAPSHOT/
+        FAILED_STAGE = ""
+        SH_SUCCESS_STATUS_CODE = 0
+
+    }
+
+    options {
+        timeout(time: 1, unit: 'HOURS')
+        disableConcurrentBuilds()
+        buildDiscarder(logRotator(numToKeepStr: '5'))
+    }
+
+    stages {
+        stage('Check Version') {
+            steps {
+                script {
+                    FAILED_STAGE = env.STAGE_NAME 
+                     dir('alfa-client') { 
+                    VERSION = getPackagejsonVersion()
+                     }
+                }
+            }
+        }
+    
+        stage('build storybook and its docker image') {
+            steps {
+                script {
+	                FAILED_STAGE=env.STAGE_NAME
+	
+	                dir('alfa-client') {
+
+                    withNPM(npmrcConfig: 'a4272a20-bb67-4cf7-8ce5-a1c3ac66613c') {
+                        sh 'npm cache verify'
+	                    sh 'npm install'
+	                    sh 'npm run ci-storybook'
+                     }
+	                  
+	
+	                    
+	    
+	                }
+
+                }
+            }
+        }
+
+        stage('Tag and Push Docker image') {
+            steps {
+                script {
+                    FAILED_STAGE=env.STAGE_NAME
+                    IMAGE_TAG = generateImageTag()
+
+                    tagAndPushDockerImage(IMAGE_TAG)
+
+                    if (isMasterBranch()) {
+                        tagAndPushDockerImage('snapshot-latest')
+                    }
+                }
+            }
+        }
+
+        stage('Test, build and deploy Helm Chart') {
+            steps {
+                script {
+                   HELM_CHART_VERSION = generateHelmChartVersion()
+                   
+                   dir('alfa-client/libs/design-system') {
+                    sh "./run_helm_test.sh"
+                   } 
+
+                    dir('alfa-client/libs/design-system/main/helm') {                    
+
+                        sh "helm package --version=${HELM_CHART_VERSION} ."
+
+                        deployHelmChart(HELM_CHART_VERSION)
+                    }
+                }
+            }
+        }
+
+        stage('Trigger Dev rollout') {
+            when {
+                branch 'master'
+            }
+            steps {
+                script {
+                    FAILED_STAGE = env.STAGE_NAME
+
+                    cloneGitopsRepo()
+
+                    setNewGitopsVersion()
+                    pushGitopsRepo()
+                }
+            }
+        }
+    }
+
+    post { 
+        failure {
+            script {    
+                if (isMasterBranch()) {
+                    sendFailureMessage()
+                }
+            }
+        }
+    }
+}
+
+
+
+String generateImageTag() {
+    def imageTag = "${env.BRANCH_NAME}-${VERSION}"
+
+    if (isMasterBranch()) {
+        imageTag += "-${env.GIT_COMMIT.take(7)}"
+    }
+
+    return imageTag
+}
+
+Void cloneGitopsRepo() {
+    withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) {
+        sh 'git clone https://${USER}:${TOKEN}@git.ozg-sh.de/ozgcloud-devops/gitops.git'
+    }
+    configureGit()
+}
+
+Void configureGit() {
+    final email = "jenkins@ozg-sh.de"
+    final name = "jenkins"
+
+    dir("gitops") {
+        sh "git config user.email '${email}'"
+        sh "git config user.name '${name}'"
+    }
+}
+
+
+
+Void setNewGitopsVersion() {
+    dir("gitops") {
+        def envFile = "dev/application/values/storybook-values.yaml"
+
+        def envVersions = readYaml file: envFile
+
+        envVersions.storybook.image.tag = IMAGE_TAG
+        envVersions.storybook.helm.version = HELM_CHART_VERSION
+
+        writeYaml file: envFile, data: envVersions, overwrite: true
+
+        if (hasValuesFileChanged()) {
+            sh "git add ${envFile}"
+            sh "git commit -m 'jenkins rollout dev storybook version ${IMAGE_TAG}'"
+        }
+    }
+}
+
+Boolean hasValuesFileChanged() {
+    return sh (script: "git status | grep 'dev/application/values/storybook-values.yaml'", returnStatus: true) == env.SH_SUCCESS_STATUS_CODE as Integer
+}
+
+
+Void pushGitopsRepo() {
+    withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) {
+        dir("gitops") {
+            if (hasUnpushedCommits()) {
+                sh 'git push https://${USER}:${TOKEN}@git.ozg-sh.de/ozgcloud-devops/gitops.git'
+            }
+        }
+    }
+}
+
+Boolean hasUnpushedCommits() {
+    return sh (script: "git cherry -v | grep .", returnStatus: true) == env.SH_SUCCESS_STATUS_CODE as Integer
+}
+
+Void tagAndPushDockerImage(String newTag){
+    withCredentials([usernamePassword(credentialsId: 'jenkins-nexus-login', usernameVariable: 'USER', passwordVariable: 'PASSWORD')]) {
+        sh 'docker login docker.ozg-sh.de -u ${USER} -p ${PASSWORD}'
+
+        sh "docker tag docker.ozg-sh.de/storybook:build-latest docker.ozg-sh.de/storybook:${newTag}"
+        sh "docker push docker.ozg-sh.de/storybook:${newTag}"
+    }
+}
+String getPackagejsonVersion() {
+    def packageJSON = readJSON file: 'package.json'
+    def packageJSONVersion = packageJSON.version
+    echo packageJSONVersion
+    return packageJSONVersion
+}
+
+Void deployHelmChart(String helmChartVersion) {
+    withCredentials([usernamePassword(credentialsId: 'jenkins-nexus-login', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]){
+       
+        result = sh script: '''curl -u $USERNAME:$PASSWORD https://nexus.ozg-sh.de/service/rest/v1/components?repository=ozg-base-apps-snapshot -F file=@storybook-'''+helmChartVersion+'''.tgz''', returnStdout: true
+
+        if (result != '') {
+            error(result)
+        }
+    }
+}
+String generateHelmChartVersion() {
+    def chartVersion = "${VERSION}"
+
+    if (isMasterBranch()) {
+        chartVersion += "-${env.GIT_COMMIT.take(7)}"
+    }
+    else {
+        chartVersion += "-${env.BRANCH_NAME}"
+    }
+
+    return chartVersion.replaceAll("_", "-")
+}
+
+Boolean isMasterBranch() {
+    return env.BRANCH_NAME == 'master'
+}
+
+Void sendFailureMessage() {
+    def room = ''
+    def data = """{"msgtype":"m.text", \
+                    "body":"storybook: Build Failed. Stage: ${FAILED_STAGE} Build-ID: ${env.BUILD_NUMBER} Link: ${BLUE_OCEAN_URL}", \
+                    "format": "org.matrix.custom.html", \
+                    "formatted_body":"storybook: Build Failed. Stage: ${FAILED_STAGE} Build-ID: <a href='${BLUE_OCEAN_URL}'>${env.BUILD_NUMBER}</a>"}"""
+
+    if (isMasterBranch()) {
+        room = "!iQPAvQIiRwRpNOszjw:matrix.ozg-sh.de"
+    }
+
+    sh "curl -XPOST -H 'authorization: Bearer ${getElementAccessToken()}' -d '${data}' https://matrix.ozg-sh.de/_matrix/client/v3/rooms/$room/send/m.room.message"
+}
+
+
+String getElementAccessToken() {
+    withCredentials([string(credentialsId: 'element-login-json', variable: 'LOGIN_JSON')]) {
+        return readJSON ( text: sh (script: '''curl -XPOST -d \"$LOGIN_JSON\" https://matrix.ozg-sh.de/_matrix/client/v3/login''', returnStdout: true)).access_token
+    }
+}
diff --git a/alfa-client/apps/admin/project.json b/alfa-client/apps/admin/project.json
index e369bed13cdc4d079e36c28c7ed0d5b52b6552a7..9c6af90763bf5aec332dd62f254377b6de58f77a 100644
--- a/alfa-client/apps/admin/project.json
+++ b/alfa-client/apps/admin/project.json
@@ -29,6 +29,7 @@
         "scripts": [],
         "stylePreprocessorOptions": {
           "includePaths": [
+            "apps/alfa/src/styles/abstracts",
             "node_modules/@angular",
             "node_modules/include-media",
             "node_modules/typeface-roboto"
diff --git a/alfa-client/apps/admin/src/test/helm/network_policy_test.yaml b/alfa-client/apps/admin/src/test/helm/network_policy_test.yaml
index 7f7cedbca17f4c24972c206bf45d4d079cf771c7..2032db88a659c5b7fcf67aa199d6dba893bf5397 100644
--- a/alfa-client/apps/admin/src/test/helm/network_policy_test.yaml
+++ b/alfa-client/apps/admin/src/test/helm/network_policy_test.yaml
@@ -28,20 +28,26 @@ release:
   namespace: by-helm-test
 templates:
   - templates/network_policy.yaml
-set:
-  networkPolicy:
-    dnsServerNamespace: kube-system
-    ssoPublicIp: 1.1.1.1/32
+
 tests:
   - it: should match apiVersion
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
     asserts:
       - isAPIVersion:
           of: networking.k8s.io/v1
   - it: should match kind
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
     asserts:
       - isKind:
           of: NetworkPolicy
   - it: validate metadata
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
     asserts:
       - equal:
           path: metadata
@@ -50,6 +56,9 @@ tests:
             namespace: by-helm-test
 
   - it: should add egress rule to administration service
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
     asserts:
       - contains:
           path: spec.egress
@@ -84,7 +93,6 @@ tests:
   - it: should add additionalIngressConfig local
     set:
       networkPolicy:
-        ssoPublicIp: 51.89.117.53/32
         dnsServerNamespace: test-namespace-dns
         additionalIngressConfigLocal:
         - from:
@@ -102,7 +110,6 @@ tests:
   - it: should add additionalIngressConfig global
     set:
       networkPolicy:
-        ssoPublicIp: 51.89.117.53/32
         dnsServerNamespace: test-namespace-dns
         additionalIngressConfigGlobal:
         - from:
@@ -121,7 +128,6 @@ tests:
   - it: should add additionalEgressConfig local
     set:
       networkPolicy:
-        ssoPublicIp: 51.89.117.53/32
         dnsServerNamespace: test-dns-namespace
         additionalEgressConfigLocal:
         - to:
@@ -138,7 +144,6 @@ tests:
   - it: should add additionalEgressConfig global
     set:
       networkPolicy:
-        ssoPublicIp: 51.89.117.53/32
         dnsServerNamespace: test-dns-namespace
         additionalEgressConfigGlobal:
         - to:
@@ -164,9 +169,23 @@ tests:
   - it: test network policy unset should be disabled
     set:
       networkPolicy:
-        ssoPublicIp: 1.1.1.1
         disabled: false
         dnsServerNamespace: test-dns-server-namespace
     asserts:
       - hasDocuments:
           count: 1
+  - it: test network policy dnsServerNamespace must be set message
+    set:
+      networkPolicy:
+        disabled: false
+    asserts:
+      - failedTemplate:
+          errorMessage: networkPolicy.dnsServerNamespace must be set
+
+  - it: test network policy should be enabled by default
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-server-namespace
+    asserts:
+      - hasDocuments:
+          count: 1
\ No newline at end of file
diff --git a/alfa-client/apps/alfa-e2e/Jenkinsfile b/alfa-client/apps/alfa-e2e/Jenkinsfile
index 55255bd3130fbca4cff8452df6fa7ae5e6957928..4d9192728334431b0219afb7c8ac6372cf9bdaab 100644
--- a/alfa-client/apps/alfa-e2e/Jenkinsfile
+++ b/alfa-client/apps/alfa-e2e/Jenkinsfile
@@ -15,7 +15,7 @@ pipeline {
     }
 
     environment {
-        BLUE_OCEAN_URL = "https://jenkins.ozg-sh.de/job/E2E%20Tests/job/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/"
+        BLUE_OCEAN_URL = "https://jenkins.infra.ozg-cloud.systems/job/E2E%20Tests/job/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/"
         BUNDESLAND = "by"
         SSO_URL = "sso.dev.by.ozg-cloud.de"
         CLUSTER_BASE_URL = "dev.by.ozg-cloud.de"
@@ -325,7 +325,7 @@ pipeline {
         failure {
             script {
                 if (isMasterBranch() || isReleaseBranch()) {
-                    //sendFailureMessage()
+                    sendFailureMessage()
                 }
             }
         }
diff --git a/alfa-client/apps/alfa-e2e/docker-compose.yml b/alfa-client/apps/alfa-e2e/docker-compose.yml
index 552a59c14cb9264c1e1c090cf624ca9303f2566f..e87654d697b9a340f65e9a666dff2fcca1b5ad98 100644
--- a/alfa-client/apps/alfa-e2e/docker-compose.yml
+++ b/alfa-client/apps/alfa-e2e/docker-compose.yml
@@ -94,8 +94,6 @@ services:
       - LOGGING_CONFIG=classpath:log4j2-local.xml
       - BPL_DEBUG_ENABLED=true
       - BPL_DEBUG_PORT=5000
-      # bescheid-wizard
-      - OZGCLOUD_FEATURE_BESCHEID-WIZARD=true
       - OZGCLOUD_VORGANG_BESCHEID_0_FORM_ENGINE_NAME=FormSolutions
       - OZGCLOUD_VORGANG_BESCHEID_0_FORM_ID=KFAS_STAGE_KI_10_Haltverbot_LANDESHACKATHON
     ports:
diff --git a/alfa-client/apps/alfa-e2e/src/components/attachment/attachment.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/attachment/attachment.e2e.component.ts
index 005abef8cb58c8fb185e7b7855173fae2e27f5c7..c9fa056dfbab2bc5a36c3d600cbc7c135a78db99 100644
--- a/alfa-client/apps/alfa-e2e/src/components/attachment/attachment.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/attachment/attachment.e2e.component.ts
@@ -38,6 +38,7 @@ export class AttachmentContainerE2EComponent {
 
 export class AttachmentListE2EComponent {
   private readonly locatorRoot: string = 'file-list';
+  private readonly downloadAttachmentsButton: string = 'download-archive-file-button';
 
   public getRoot() {
     return cy.getTestElement(this.locatorRoot);
@@ -46,6 +47,14 @@ export class AttachmentListE2EComponent {
   public getItem(fileName: string): AttachmentE2EItem {
     return new AttachmentE2EItem(fileName);
   }
+
+  public getDownloadAttachmentsButton(): Cypress.Chainable<JQuery<HTMLElement>> {
+    return this.getRoot().findTestElementWithClass(this.downloadAttachmentsButton);
+  }
+
+  public downloadAttachments(): Cypress.Chainable<any> {
+    return this.getDownloadAttachmentsButton().click();
+  }
 }
 
 class AttachmentE2EItem {
diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component.ts
index 17d751a99d64ce4c1fac63beb76ee18f4f365346..5884ec6fe2f829351178b820cfc5a96e8752c343 100644
--- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component.ts
@@ -22,6 +22,10 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 
+import { contains, enterWith } from '../../support/cypress.util';
+import { uploadFile } from '../../support/file-upload';
+import { getAdjustedDateGerman } from '../../support/tech.util';
+
 export class VorgangBescheidWizardE2EComponent {
   private readonly bewilligtButton: string = 'button-bewilligt';
   private readonly abgelehntButton: string = 'button-abgelehnt';
@@ -44,15 +48,21 @@ export class VorgangBescheidWizardE2EComponent {
     'bescheiderstellung-abbrechen-entwurf-verwerfen';
   private readonly bescheidSpeichernButton: string =
     'bescheiderstellung-abbrechen-entwurf-speichern';
-  private readonly uploadBescheidFile: string = '-single-file-upload-button';
-  private readonly uploadAttachment: string = 'Anhang_hochladen-file-upload-button';
+  private readonly uploadBescheidFileButton: string = '-single-file-upload-button';
+  private readonly uploadAttachmentButton: string = 'Anhang_hochladen-file-upload-button';
+  private readonly uploadAutomaticBescheid: string = 'create-bescheid-document-button';
   private readonly mailTextArea: string = 'Text-textarea-editor';
   private readonly saveBescheid: string = 'save-button';
   private readonly sendBescheid: string = 'send-button';
   private readonly confirmAndSaveButton: string = 'confirm-and-save-button';
+  private readonly antragstellerText: string = 'bescheid-nachricht-an-antragsteller';
+  private readonly betreffText: string = 'Betreff-text-input';
+  private readonly nachrichtText: string = 'Text-textarea';
 
   private readonly fileBescheidValid: string = 'Bescheid_validpdf-file-item';
   private readonly fileAnhangValid: string = 'Anhang_validpdf-file-item';
+  private readonly fileAutomaticBescheid: string =
+    'KFAS_LIVE_KI_10_Haltverbot_befristetpdf-file-item';
 
   private readonly bescheidDocument: string = 'bescheid-document';
   private readonly attachmentDocument: string = 'bescheid-attachments';
@@ -66,145 +76,221 @@ export class VorgangBescheidWizardE2EComponent {
 
   private locatorRoot: string = 'bescheid-wizard';
 
-  public getRoot() {
+  private readonly bescheidVersenden: string = 'Bescheid versenden';
+  private readonly dokumenteHinzufuegen: string = 'Dokumente hinzufügen';
+
+  public getRoot(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.locatorRoot);
   }
 
-  public getBewilligtButton() {
+  public getBewilligtButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.bewilligtButton);
   }
 
-  public getAbgelehntButton() {
+  public getAbgelehntButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.abgelehntButton);
   }
 
-  public getUeberspringenButton() {
+  public getUeberspringenButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.ueberspringenButton);
   }
-  public getStatusText() {
+  public getStatusText(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.statusText);
   }
 
-  public getUeberspringenDialog() {
+  public getUeberspringenDialog(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.ueberspringenDialog);
   }
 
-  public getUeberspringenAbbrechen() {
+  public getUeberspringenAbbrechen(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.ueberspringenAbbrechen);
   }
 
-  public getUeberspringenAbschliessen() {
+  public getUeberspringenAbschliessen(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.ueberspringenAbschliessen);
   }
 
-  public getDateInput() {
+  public getDateInput(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.dateInput);
   }
-  public getDateError() {
+  public getDateError(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.dateError);
   }
 
-  public getWeiterButton() {
+  public getWeiterButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.weiterButton);
   }
 
-  public getStepCaption() {
+  public getStepCaption(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.stepCaption);
   }
 
-  public getStepButton1() {
+  public getStepButton1(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.stepButton1);
   }
 
-  public getStepButton2() {
+  public getStepButton2(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.stepButton2);
   }
 
-  public getStepButton3() {
+  public getStepButton3(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.stepButton3);
   }
 
-  public getCloseButton() {
+  public getCloseButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.closeButton);
   }
 
-  public getCloseDialog() {
+  public getCloseDialog(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.closeDialog);
   }
 
-  public getCloseVerwerfenButton() {
+  public getCloseVerwerfenButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.bescheidVerwerfenButton);
   }
 
-  public getCloseSpeichernButton() {
+  public getCloseSpeichernButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.bescheidSpeichernButton);
   }
 
-  public getUploadBescheidButton() {
-    return cy.getTestElement(this.uploadBescheidFile);
+  public getUploadBescheidButton(): Cypress.Chainable<JQuery<HTMLElement>> {
+    return cy.getTestElement(this.uploadBescheidFileButton);
   }
 
-  public getUploadAttachmentButton() {
-    return cy.getTestElement(this.uploadAttachment);
+  public getUploadAttachmentButton(): Cypress.Chainable<JQuery<HTMLElement>> {
+    return cy.getTestElement(this.uploadAttachmentButton);
   }
 
-  public getFileBescheidValidInWizard() {
+  public getFileBescheidValidInWizard(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.locatorRoot).find(`[data-test-id=${this.fileBescheidValid}]`);
   }
 
-  public getFileAnhangValidInWizard() {
+  public getFileAnhangValidInWizard(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.locatorRoot).find(`[data-test-id=${this.fileAnhangValid}]`);
   }
 
-  public getDeleteButtonOfElement(element: string) {
+  public getAutomaticBescheidFileInWizard() {
+    return cy.getTestElement(this.locatorRoot).find(`[data-test-id=${this.fileAutomaticBescheid}]`);
+  }
+
+  public getDeleteButtonOfElement(element: string): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(element).find('[title="Anhang löschen"]');
   }
 
-  public getElementFromFileName(filename: string) {
+  public getElementFromFileName(filename: string): string {
     return filename.replace(/\./g, '') + '-file-item';
   }
 
-  public getBescheidDocument() {
+  public getBescheidDocument(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.bescheidDocument);
   }
 
-  public getAttachmentDocument() {
+  public getAttachmentDocument(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.attachmentDocument);
   }
 
-  public getBescheidUploadSpinner() {
+  public getBescheidUploadSpinner(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.get(this.bescheidUploadSpinner);
   }
 
-  public getAttachmentUploadSpinner() {
+  public getAttachmentUploadSpinner(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.get(this.attachmentUploadSpinner);
   }
 
-  public getBescheidSaveSpinner() {
+  public getBescheidSaveSpinner(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.get(this.bescheidSaveSpinner);
   }
 
-  public getSendenSpinner() {
+  public getSendenSpinner(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.get(this.sendenSpinner);
   }
 
-  public getMailTextArea() {
-    return cy.get(this.mailTextArea);
+  public getMailText(): Cypress.Chainable<JQuery<HTMLElement>> {
+    return cy.getTestElement(this.nachrichtText);
   }
 
-  public getSaveButton() {
+  public getSaveButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.saveBescheid);
   }
 
-  public getSendButton() {
+  public getSendButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.sendBescheid);
   }
 
-  public getResultBox() {
+  public getResultBox(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.bescheidResultBox);
   }
 
-  public getConfirmAndSaveButton() {
+  public getConfirmAndSaveButton(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.confirmAndSaveButton);
   }
+
+  public getAntragstellerText(): Cypress.Chainable<JQuery<HTMLElement>> {
+    return cy.getTestElement(this.antragstellerText);
+  }
+
+  public getBetreffText(): Cypress.Chainable<JQuery<HTMLElement>> {
+    return cy.getTestElement(this.betreffText);
+  }
+
+  public getNachrichtText(): Cypress.Chainable<JQuery<HTMLElement>> {
+    return cy.getTestElement(this.nachrichtText);
+  }
+
+  public isBescheidDocumentsStep(): void {
+    contains(this.getRoot(), this.dokumenteHinzufuegen);
+  }
+
+  public isBescheidVersendenStep(): void {
+    contains(this.getRoot(), this.bescheidVersenden);
+  }
+
+  public ablehnen(): void {
+    this.getAbgelehntButton().should('exist').click();
+  }
+
+  public weiter(): void {
+    this.getWeiterButton().should('exist').click();
+  }
+
+  public close(): void {
+    this.getCloseButton().should('exist').click();
+  }
+
+  public isOpened(): void {
+    this.getRoot().should('exist');
+  }
+
+  public isClosed(): void {
+    this.getRoot().should('not.exist');
+  }
+
+  public getUploadAutomaticBescheidButton() {
+    return cy.getTestElement(this.uploadAutomaticBescheid);
+  }
+
+  public uploadBescheid(fileName: string): void {
+    uploadFile(this.getUploadBescheidButton(), fileName);
+  }
+
+  public uploadAttachment(fileName: string): void {
+    uploadFile(this.getUploadAttachmentButton(), fileName);
+  }
+
+  public bescheidUploadSpinnerIsClosed(): void {
+    this.getBescheidUploadSpinner().should('not.exist');
+  }
+
+  public attachmentSpinnerIsClosed(): void {
+    this.getAttachmentUploadSpinner().should('not.exist');
+  }
+
+  public enterDate(difference: number): void {
+    this.getDateInput().should('exist');
+    enterWith(this.getDateInput(), getAdjustedDateGerman(difference));
+  }
+
+  public closeDialogIsShown(): void {
+    this.getCloseDialog().should('exist');
+  }
 }
diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component.ts
index 7cbf56b323b60afa837fc79bae7b9b296e28448a..26821f5985776515387d535b6c6060f0773b0c35 100644
--- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component.ts
@@ -30,6 +30,7 @@ import {
 
 export class VorgangFormularDatenE2EComponent {
   private readonly locatorRoot: string = 'formulardaten-panel';
+  private readonly locatorDateien: string = 'dateien';
   private readonly locatorMetadaten: string = 'metadaten';
   private readonly locatorAntragdaten: string = 'antragdaten';
   private readonly locatorTabset: string = 'div[role=tab]';
@@ -39,11 +40,14 @@ export class VorgangFormularDatenE2EComponent {
   private readonly historieContainer: VorgangFormularDatenHistorieE2EComponent =
     new VorgangFormularDatenHistorieE2EComponent();
 
+  private readonly fileListHeader: string = 'file-list';
+  private readonly attachmentListHeader: string = 'attachment-list';
+
   private readonly antragdatenTab: number = 0;
-  private readonly metadatenTab: number = 1;
-  private readonly representationTab: number = 2;
-  private readonly attachmentTab: number = 3;
-  private readonly historieTab: number = 4;
+  private readonly metadatenTab: number = 9;
+  private readonly representationTab: number = 9;
+  private readonly dateienTab: number = 1;
+  private readonly historieTab: number = 2;
 
   public getRoot() {
     return cy.getTestElement(this.locatorRoot);
@@ -65,8 +69,8 @@ export class VorgangFormularDatenE2EComponent {
     return this.getTabsetElement().eq(this.representationTab);
   }
 
-  public getAttachmentTab() {
-    return this.getTabsetElement().eq(this.attachmentTab);
+  public getDateienTab() {
+    return this.getTabsetElement().eq(this.dateienTab);
   }
 
   public getHistorieTab() {
@@ -85,6 +89,14 @@ export class VorgangFormularDatenE2EComponent {
     return getTestElement(this.locatorAntragdaten);
   }
 
+  public getDateien() {
+    return getTestElement(this.locatorDateien);
+  }
+
+  public getTabset() {
+    return getTestElement(this.locatorTabset);
+  }
+
   public getHistorieContainer(): VorgangFormularDatenHistorieE2EComponent {
     return this.historieContainer;
   }
@@ -92,4 +104,17 @@ export class VorgangFormularDatenE2EComponent {
   public getHistorieItemByIndex(index: number): VorgangFormularDatenHistorieItemE2EComponent {
     return this.getHistorieContainer().getListItemByIndex(index);
   }
+
+  public getFileListHeader() {
+    return getTestElement(this.fileListHeader);
+  }
+
+  public getAttachmentListHeader() {
+    return getTestElement(this.attachmentListHeader);
+  }
+
+  public getFileElementByName(fileName: string) {
+    fileName = fileName.replace(/\./g, '') + '-file-item';
+    return getTestElement(fileName);
+  }
 }
diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component.ts
index d879ee9fc1c21ef8e1318dad1ca87283118e2439..fba7e4dfd79867f2b53aeda47cd108742548cce1 100644
--- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component.ts
@@ -21,6 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { enterWith } from '../../support/cypress.util';
 import { convertToDataTestId } from '../../support/tech.util';
 
 export class VorgangSearchE2EComponent {
@@ -36,7 +37,7 @@ export class VorgangSearchE2EComponent {
     return cy.getTestElement(this.locatorRoot);
   }
 
-  public getInput() {
+  public getInput(): Cypress.Chainable<JQuery<HTMLElement>> {
     return cy.getTestElement(this.locatorInput);
   }
 
@@ -61,6 +62,10 @@ export class VorgangSearchE2EComponent {
   public getClearButton() {
     return cy.getTestElement(this.locatorClearButton);
   }
+
+  public doSearch(searchString: string): void {
+    enterWith(this.getInput(), searchString, 300);
+  }
 }
 
 export class VorgangSearchPreviewListItemE2EComponent {
diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component.ts
index f1240912ebb55269bfea578cd2a72a23187a61a6..446c287de76ee0c62fd746f6df9241c95ed0ce92 100644
--- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component.ts
@@ -87,6 +87,6 @@ export class VorgangViewE2EComponent {
   }
 
   public getButton() {
-    return this.getRoot().getTestElementWithClass(this.button);
+    return this.getRoot().findTestElementWithClass(this.button);
   }
 }
diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component.ts
index 2b0fe296fec1a11d59f843624c441ae14788dea9..d4b039afbb15779a709339c390a2a4f6d8c70e73 100644
--- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component.ts
@@ -205,14 +205,14 @@ export class BescheidHistorieItemE2EComponent {
   }
 
   public getStatus() {
-    return cy.getTestElementWithClass(this.status);
+    return this.getRoot().findTestElementWithClass(this.status);
   }
 
   public getBescheidDokumentText() {
-    return cy.getTestElementWithClass(this.bescheidDokument);
+    return this.getRoot().findTestElementWithClass(this.bescheidDokument);
   }
 
   public getBescheidAnhaengeText() {
-    return cy.getTestElementWithClass(this.bescheidAnhaenge);
+    return this.getRoot().findTestElementWithClass(this.bescheidAnhaenge);
   }
 }
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-loeschen-anfordern.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-loeschen-anfordern.cy.ts
index 91617d3639ed07f3107ce74e274de36b9d319262..c22d4da4f7d654fdbf843bc28381da807dd31771 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-loeschen-anfordern.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-loeschen-anfordern.cy.ts
@@ -32,7 +32,7 @@ import {
 } from '../../../model/vorgang';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
-import { dropCollections } from '../../../support/cypress-helper';
+import { dropCollections, wait } from '../../../support/cypress-helper';
 import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
 import { loginAsEmil } from '../../../support/user-util';
 import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
@@ -167,6 +167,8 @@ describe('Vorgang löschen anfordern', () => {
 
       it('should show status Abgeschlossen', () => {
         notExist(vorgangPage.getProgressBar());
+        wait(2000, 'Statusänderung flaky');
+        cy.scrollTo(0, -500);
 
         haveText(
           vorgangPage.getVorgangDetailHeader().getStatus(),
@@ -277,6 +279,10 @@ describe('Vorgang löschen anfordern', () => {
       it('should show status Verworfen', () => {
         notExist(vorgangPage.getProgressBar());
 
+        wait(2000, 'Statusänderung im UI nicht schnell genug');
+        cy.scrollTo(0, -500);
+
+        vorgangPage.getVorgangDetailHeader().getStatus();
         haveText(
           vorgangPage.getVorgangDetailHeader().getStatus(),
           vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN],
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loeschen-anfordern.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loeschen-anfordern.cy.ts
index 6ae63d71c0d8c4d0c7477a53749f5784fcd19a96..6eb2921858a19d25aeb0423fd4c03a2a4378831e 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loeschen-anfordern.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loeschen-anfordern.cy.ts
@@ -21,7 +21,7 @@ import {
 } from '../../../model/vorgang';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
-import { dropCollections, visitUrl } from '../../../support/cypress-helper';
+import { dropCollections, visitUrl, wait } from '../../../support/cypress-helper';
 import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
 import { loginAsLudwig, loginAsSabine } from '../../../support/user-util';
 import { buildVorgang, initVorgaenge, initVorgang, objectIds } from '../../../support/vorgang-util';
@@ -161,6 +161,9 @@ describe('Vorgang Löschen anfordern', () => {
         });
 
         it('should have status zu Löschen', () => {
+          wait(2000, 'Statusänderung im UI nicht schnell genug');
+          cy.scrollTo(0, -500);
+
           haveText(
             vorgangPage.getVorgangDetailHeader().getStatus(),
             vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN],
@@ -299,6 +302,9 @@ describe('Vorgang Löschen anfordern', () => {
         it('should show status Abgeschlossen', () => {
           notExist(vorgangPage.getProgressBar());
 
+          wait(2000, 'Statusänderung im UI nicht schnell genug');
+          cy.scrollTo(0, -500);
+
           haveText(
             vorgangPage.getVorgangDetailHeader().getStatus(),
             vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN],
@@ -408,6 +414,9 @@ describe('Vorgang Löschen anfordern', () => {
         it('should show status Verworfen', () => {
           notExist(vorgangPage.getProgressBar());
 
+          wait(2000, 'Statusänderung im UI nicht schnell genug');
+          cy.scrollTo(0, -500);
+
           haveText(
             vorgangPage.getVorgangDetailHeader().getStatus(),
             vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN],
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/anhang-herunterladen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/vorgang-anhang-herunterladen.cy.ts
similarity index 86%
rename from alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/anhang-herunterladen.cy.ts
rename to alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/vorgang-anhang-herunterladen.cy.ts
index 69dfac76104a5ea135bb876ffc97766877219999..946a0c86da3a2c4dade2896dbaeb09ab0734084a 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/anhang-herunterladen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/vorgang-anhang-herunterladen.cy.ts
@@ -24,6 +24,7 @@
 import { AttachmentContainerE2EComponent } from 'apps/alfa-e2e/src/components/attachment/attachment.e2e.component';
 import { VorgangFormularDatenE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component';
 import { convertToDataTestId } from 'apps/alfa-e2e/src/support/tech.util';
+import { AttachmentListE2EComponent } from '../../../components/attachment/attachment.e2e.component';
 import { VorgangDetailHeaderE2EComponent } from '../../../components/vorgang/vorgang-detail-header.e2e.component';
 import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
 import { VorgangSubnavigationE2EComponent } from '../../../components/vorgang/vorgang-subnavigation';
@@ -40,7 +41,14 @@ import {
   createXmlRepresentation,
   initGridFs,
 } from '../../../support/binary-file-util';
-import { dropCollections, readFileFromDownloads } from '../../../support/cypress-helper';
+import {
+  countDownloadFiles,
+  deleteDownloadFolder,
+  dropCollections,
+  getDownloadFiles,
+  readFileFromDownloads,
+  unzipDownloadFile,
+} from '../../../support/cypress-helper';
 import { exist, notExist } from '../../../support/cypress.util';
 import { loginAsSabine } from '../../../support/user-util';
 import {
@@ -58,8 +66,11 @@ describe('Vorgang Anhänge', () => {
   const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader();
   const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation();
   const attachmentContainer: AttachmentContainerE2EComponent = vorgangPage.getAttachmentContainer();
+  const attachmentList: AttachmentListE2EComponent = new AttachmentListE2EComponent();
   const formularDatenContainer: VorgangFormularDatenE2EComponent =
     vorgangPage.getFormularDatenContainer();
+  const vorgangDatenFormular: VorgangFormularDatenE2EComponent =
+    vorgangPage.getFormularDatenContainer();
 
   const xmlRepresentation: FileDataE2E = createXmlRepresentation();
 
@@ -104,7 +115,7 @@ describe('Vorgang Anhänge', () => {
     });
 
     it('should show attachment on click on tab', () => {
-      formularDatenContainer.getAttachmentTab().click();
+      formularDatenContainer.getDateienTab().click();
 
       notExist(vorgangPage.getSpinner());
       exist(attachmentContainer.getList().getRoot());
@@ -130,6 +141,22 @@ describe('Vorgang Anhänge', () => {
       exist(readFileFromDownloads(buildDownloadFileName(pdfAttachmentName)));
     });
 
+    it('should download attachment zip file', () => {
+      deleteDownloadFolder().then(() => {
+        attachmentList.downloadAttachments();
+      });
+    });
+
+    it('should unzip attachment file', () => {
+      getDownloadFiles().then((files) => {
+        unzipDownloadFile(files[0]).then(() => {
+          countDownloadFiles().then((count) => {
+            expect(count).to.eq(3);
+          });
+        });
+      });
+    });
+
     it('should navigate to vorganglist on back button', () => {
       subnavigation.getBackButton().click();
       waitForSpinnerToDisappear();
@@ -155,7 +182,7 @@ describe('Vorgang Anhänge', () => {
     });
 
     it('should show attachment on click on tab', () => {
-      formularDatenContainer.getRepresentationTab().click();
+      formularDatenContainer.getDateienTab().click();
 
       notExist(vorgangPage.getSpinner());
       exist(attachmentContainer.getList().getRoot());
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-abbrechen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-abbrechen.cy.ts
index c2943c6ef548e9872c2e2e6ad16eefff928ed4c6..81ce0e4386153c2cc241067a25805d9e5ac2d97f 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-abbrechen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-abbrechen.cy.ts
@@ -15,7 +15,7 @@ import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-lis
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
 import { dropCollections } from '../../../support/cypress-helper';
-import { contains, enterWith, exist, haveText, notExist } from '../../../support/cypress.util';
+import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
 import {
   TEST_FILE_BESCHEID_ANHANG_VALID,
   TEST_FILE_BESCHEID_VALID,
@@ -25,12 +25,13 @@ import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang
 
 registerLocaleData(localeDe, 'de', localeDeExtra);
 
-describe('Bescheid abbrechen', () => {
+describe('Vorgang - Bescheid abbrechen', () => {
   const mainPage: MainPage = new MainPage();
   const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
 
   const bewilligtText: string = 'Bewilligt am';
   const abgelehntText: string = 'Abgelehnt am';
+  const stepCaption2: string = 'Dokumente hinzufügen';
 
   const vorgangPage: VorgangPage = new VorgangPage();
   const bescheidWizard: VorgangBescheidWizardE2EComponent = vorgangPage.getBescheidWizard();
@@ -57,59 +58,98 @@ describe('Bescheid abbrechen', () => {
     dropCollections();
   });
 
-  describe('Discard changes', () => {
-    it('should discard all data after clicking X and confirm dicard', () => {
+  describe.skip('Sollte gefixt sein nach OZG-6185 - Discard changes after click on Verwerfen', () => {
+    it('should click abgelehnt, enter date, and continue to step 2', () => {
       vorgangList.getListItem(bescheidVorgang.name).getRoot().click();
       waitForSpinnerToDisappear();
 
       vorgangFormularButtons.getBescheidenButton().click();
-      bescheidWizard.getAbgelehntButton().click();
-      enterWith(bescheidWizard.getDateInput(), getAdjustedDateGerman(-1));
-      bescheidWizard.getWeiterButton().click();
-      uploadFile(bescheidWizard.getUploadBescheidButton(), TEST_FILE_BESCHEID_VALID);
-      notExist(bescheidWizard.getBescheidUploadSpinner());
-      uploadFile(bescheidWizard.getUploadAttachmentButton(), TEST_FILE_BESCHEID_ANHANG_VALID);
-      notExist(bescheidWizard.getAttachmentUploadSpinner());
-      bescheidWizard.getWeiterButton().click();
-      bescheidWizard.getCloseButton().click();
-      exist(bescheidWizard.getCloseDialog());
+      bescheidWizard.ablehnen();
+      bescheidWizard.enterDate(-1);
+      bescheidWizard.weiter();
 
+      bescheidWizard.isBescheidDocumentsStep();
+    });
+
+    it('should upload files and continue to step 3', () => {
+      bescheidWizard.uploadBescheid(TEST_FILE_BESCHEID_VALID);
+      bescheidWizard.bescheidUploadSpinnerIsClosed();
+      bescheidWizard.uploadAttachment(TEST_FILE_BESCHEID_ANHANG_VALID);
+      bescheidWizard.attachmentSpinnerIsClosed();
+      bescheidWizard.weiter();
+
+      bescheidWizard.isBescheidVersendenStep();
+    });
+
+    it('should open dialog after click on X', () => {
+      bescheidWizard.close();
+
+      bescheidWizard.closeDialogIsShown();
+    });
+
+    it('should close Wizard after click on Verwerfen', () => {
       bescheidWizard.getCloseVerwerfenButton().click();
-      notExist(bescheidWizard.getRoot());
+      waitForSpinnerToDisappear();
+
+      bescheidWizard.isClosed();
+    });
+
+    it('should show status In Bearbeitung', () => {
       haveText(
         vorgangPage.getVorgangDetailHeader().getStatus(),
         vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG],
       );
+    });
+  });
 
+  describe('Keep changes after click on Entwurf speichern', () => {
+    it('click Vorgang', () => {
+      vorgangList.getListItem(bescheidVorgang.name).getRoot().click();
+      waitForSpinnerToDisappear();
+    });
+
+    it('should have default Bescheid status and continue to step 2', () => {
       vorgangFormularButtons.getBescheidenButton().click();
       contains(bescheidWizard.getStatusText(), bewilligtText + ' ' + getAdjustedDateGerman(0));
-      bescheidWizard.getWeiterButton().click();
+      bescheidWizard.weiter();
+    });
+
+    it('should not show file from previous Bescheid', () => {
       notExist(bescheidWizard.getFileAnhangValidInWizard());
       notExist(bescheidWizard.getFileBescheidValidInWizard());
     });
 
-    it('should save all data after clicking X and confirm save', () => {
-      bescheidWizard.getAbgelehntButton().click();
-      enterWith(bescheidWizard.getDateInput(), getAdjustedDateGerman(-1));
-      bescheidWizard.getWeiterButton().click();
+    it('should upload Bescheid and attachment', () => {
       uploadFile(bescheidWizard.getUploadBescheidButton(), TEST_FILE_BESCHEID_VALID);
       notExist(bescheidWizard.getBescheidUploadSpinner());
       uploadFile(bescheidWizard.getUploadAttachmentButton(), TEST_FILE_BESCHEID_ANHANG_VALID);
       notExist(bescheidWizard.getAttachmentUploadSpinner());
-      bescheidWizard.getCloseButton().click();
+    });
+    it('should open dialog after click on X', () => {
+      bescheidWizard.close();
+      exist(bescheidWizard.getCloseDialog());
+    });
+
+    it('should close Wizard after click on Speichern', () => {
       bescheidWizard.getCloseSpeichernButton().click();
       waitForSpinnerToDisappear();
       notExist(bescheidWizard.getRoot());
+    });
 
+    it('should show status In Bearbeitung', () => {
       haveText(
         vorgangPage.getVorgangDetailHeader().getStatus(),
         vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG],
       );
+    });
 
+    it('should keep date and status from current Bescheid in progress', () => {
       vorgangFormularButtons.getBescheidenButton().click();
-      contains(bescheidWizard.getStatusText(), abgelehntText + ' ' + getAdjustedDateGerman(-1));
+      contains(bescheidWizard.getStatusText(), bewilligtText + ' ' + getAdjustedDateGerman(0));
+    });
 
-      bescheidWizard.getWeiterButton().click();
+    it('should keep files from current Bescheid in progress', () => {
+      bescheidWizard.weiter();
       exist(bescheidWizard.getFileAnhangValidInWizard());
       exist(bescheidWizard.getFileBescheidValidInWizard());
     });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-automatisch-erstellen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-automatisch-erstellen.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c2a6b888ce2b2bad7055322952440965512d27b5
--- /dev/null
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-automatisch-erstellen.cy.ts
@@ -0,0 +1,121 @@
+import { registerLocaleData } from '@angular/common';
+import localeDe from '@angular/common/locales/de';
+import localeDeExtra from '@angular/common/locales/extra/de';
+import { VorgangBescheidWizardE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-bescheid-wizard.e2e.component';
+import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
+import { VorgangSubnavigationE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-subnavigation';
+import { SmockerMocks } from 'apps/alfa-e2e/src/model/smocker';
+import {
+  EingangE2E,
+  EingangHeaderE2E,
+  VorgangE2E,
+  VorgangStatusE2E,
+} from 'apps/alfa-e2e/src/model/vorgang';
+import 'cypress-real-events/support';
+import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
+import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
+import { VorgangPage } from '../../../page-objects/vorgang.po';
+import { addSmockerMock, dropCollections } from '../../../support/cypress-helper';
+import { exist, haveText, notExist } from '../../../support/cypress.util';
+import { initUsermanagerUsers, loginAsSabine } from '../../../support/user-util';
+import {
+  buildVorgang,
+  createVorgang,
+  initVorgaenge,
+  objectIds,
+} from '../../../support/vorgang-util';
+
+registerLocaleData(localeDe, 'de', localeDeExtra);
+
+//TODO: Jenkins konfigurieren
+describe.skip('Upload automatic Bescheid', () => {
+  const mainPage: MainPage = new MainPage();
+  const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
+
+  const vorgangPage: VorgangPage = new VorgangPage();
+  const bescheidWizard: VorgangBescheidWizardE2EComponent = vorgangPage.getBescheidWizard();
+
+  const formIdP: string = 'KFAS_STAGE_KI_10_Haltverbot_LANDESHACKATHON';
+  const formEngineName: string = 'FormSolutions';
+  const eingangHeader: EingangHeaderE2E = { ...createVorgang().eingangs[0].header };
+
+  const eingangP: EingangE2E = {
+    ...createVorgang().eingangs[0],
+    header: { ...eingangHeader, formId: formIdP, formEngineName },
+  };
+
+  const bescheidAutomatik: VorgangE2E = {
+    ...createVorgang(),
+    status: VorgangStatusE2E.IN_BEARBEITUNG,
+    name: 'automatischerBescheid',
+    eingangs: [eingangP],
+  };
+
+  const standardVorgang: VorgangE2E = {
+    ...buildVorgang(objectIds[1], 'Standard Vorgang'),
+    status: VorgangStatusE2E.IN_BEARBEITUNG,
+  };
+
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent =
+    vorgangPage.getFormularButtons();
+
+  const vorgangSubnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation();
+
+  before(() => {
+    initVorgaenge([bescheidAutomatik, standardVorgang]);
+    initUsermanagerUsers();
+
+    addSmockerMock(SmockerMocks.SMARTDOCUMENT_MOCK);
+
+    loginAsSabine();
+
+    waitForSpinnerToDisappear();
+    exist(vorgangList.getRoot());
+  });
+
+  after(() => {
+    dropCollections();
+  });
+
+  describe.skip('Upload automatic Bescheid document', () => {
+    it('should show automatic Bescheid button', () => {
+      vorgangList.getListItem(bescheidAutomatik.name).getRoot().click();
+      waitForSpinnerToDisappear();
+
+      vorgangFormularButtons.getBescheidenButton().click();
+      bescheidWizard.getWeiterButton().click();
+      exist(bescheidWizard.getUploadAutomaticBescheidButton());
+    });
+
+    it('should upload automatic Bescheid file', () => {
+      waitForSpinnerToDisappear();
+      bescheidWizard.getUploadAutomaticBescheidButton().click();
+
+      exist(bescheidWizard.getBescheidUploadSpinner());
+      notExist(bescheidWizard.getBescheidUploadSpinner());
+      exist(bescheidWizard.getAutomaticBescheidFileInWizard());
+    });
+
+    it('should show automatic header and text in step 3', () => {
+      bescheidWizard.getWeiterButton().click();
+      waitForSpinnerToDisappear();
+
+      haveText(bescheidWizard.getMailText(), '');
+    });
+  });
+
+  describe('Do not show automatic upload button on other Vorgang', () => {
+    it('should not show button on Vorgang with different formID', () => {
+      bescheidWizard.getCloseButton().click();
+      bescheidWizard.getCloseVerwerfenButton().click();
+      vorgangSubnavigation.getBackButton().click();
+      vorgangList.getListItem(standardVorgang.name).getRoot().click();
+      waitForSpinnerToDisappear();
+
+      vorgangFormularButtons.getBescheidenButton().click();
+      bescheidWizard.getWeiterButton().click();
+
+      notExist(bescheidWizard.getUploadAutomaticBescheidButton());
+    });
+  });
+});
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-dokumente-hochladen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-dokumente-hochladen.cy.ts
index fecc0d94c2591421c36835b202e9e9b5e4ab2653..6e114b91917aa3a237f1eff680e867053633b652 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-dokumente-hochladen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-dokumente-hochladen.cy.ts
@@ -10,7 +10,7 @@ import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-lis
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
 import { dropCollections, getTestElement } from '../../../support/cypress-helper';
-import { contains, exist, notExist } from '../../../support/cypress.util';
+import { contains, exist, haveValue, notContains, notExist } from '../../../support/cypress.util';
 import {
   TEST_FILE_BESCHEID_ANHANG_BIG,
   TEST_FILE_BESCHEID_ANHANG_VALID,
@@ -43,6 +43,11 @@ describe('Bescheid Dokumente hochladen', () => {
   const documentError: string = 'Erlaubte Dateiendungen';
   const sizeError: string = 'Anhänge größer';
   const missingBescheidError: string = 'Bitte fügen Sie';
+  const nachrichtHeader: string = 'Neue Nachricht';
+  const antragstellerName: string = 'An: Max Testermann';
+  const betreffText: string = 'Ihr Bescheid zum Antrag';
+  const nachrichtText: string =
+    'Sehr geehrte/r Antragsteller/in,\n\nim Folgenden erhalten Sie Ihren Bescheid.\n\nMit freundlichen Grüßen\n\nIhre Verwaltung';
 
   before(() => {
     initVorgaenge([bescheidVorgang]);
@@ -144,4 +149,22 @@ describe('Bescheid Dokumente hochladen', () => {
       contains(bescheidWizard.getBescheidDocument(), missingBescheidError);
     });
   });
+
+  describe('check contents of step 3', () => {
+    it('should show Max Testermann as Antragsteller, the default message text', () => {
+      uploadFile(bescheidWizard.getUploadBescheidButton(), TEST_FILE_BESCHEID_VALID);
+      notExist(bescheidWizard.getBescheidUploadSpinner());
+
+      bescheidWizard.getWeiterButton().click();
+
+      contains(bescheidWizard.getAntragstellerText(), nachrichtHeader);
+      contains(bescheidWizard.getAntragstellerText(), antragstellerName);
+      haveValue(bescheidWizard.getBetreffText(), betreffText);
+      haveValue(bescheidWizard.getNachrichtText(), nachrichtText);
+    });
+
+    it('should not contain error message from upload', () => {
+      notContains(bescheidWizard.getAttachmentDocument(), sizeError);
+    });
+  });
 });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-info-anzeigen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-info-anzeigen.cy.ts
index dd926439b5d110258be4ea3f702018343668ea53..8a72acae98a5c36a1fe67582333a156466723c4b 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-info-anzeigen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-info-anzeigen.cy.ts
@@ -14,13 +14,17 @@ import {
   TEST_FILE_BESCHEID_ANHANG_VALID,
   TEST_FILE_BESCHEID_VALID,
 } from 'apps/alfa-e2e/src/support/data.util';
-import { uploadFile } from 'apps/alfa-e2e/src/support/file-upload';
 import { getAdjustedDateGerman } from 'apps/alfa-e2e/src/support/tech.util';
 import 'cypress-real-events/support';
 import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
-import { countDownloadFiles, dropCollections } from '../../../support/cypress-helper';
+import {
+  countDownloadFiles,
+  deleteDownloadFolder,
+  dropCollections,
+  readFileFromDownloads,
+} from '../../../support/cypress-helper';
 import {
   contains,
   enterWith,
@@ -75,51 +79,79 @@ describe('Bescheid Info anzeigen', () => {
   });
 
   describe('Show Bescheid Entwurf info on details page', () => {
-    it('should show Entwurf on details page', () => {
+    it('should not show Bescheid info in list', () => {
       notExist(bescheide.getBescheidListItem());
+    });
+
+    it('should open Wizard', () => {
       vorgangList.getListItem(bescheidVorgang.name).getRoot().click();
       waitForSpinnerToDisappear();
 
       vorgangFormularButtons.getBescheidenButton().click();
-      bescheidWizard.getAbgelehntButton().click();
-      enterWith(bescheidWizard.getDateInput(), getAdjustedDateGerman(-1));
-      bescheidWizard.getWeiterButton().click();
-      bescheidWizard.getCloseButton().click();
+
+      bescheidWizard.isOpened();
+    });
+
+    it('should click abgelehnt, set date and continue to step 2', () => {
+      bescheidWizard.ablehnen();
+      bescheidWizard.enterDate(-1);
+      bescheidWizard.weiter();
+      bescheidWizard.isBescheidDocumentsStep();
+    });
+
+    it('should close Wizard', () => {
+      bescheidWizard.close();
       bescheidWizard.getCloseSpeichernButton().click();
+      bescheidWizard.isClosed();
+    });
+
+    it('should show status In Bearbeitung', () => {
       haveText(
         vorgangPage.getVorgangDetailHeader().getStatus(),
         vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG],
       );
+    });
 
+    it('should show Bescheid as Entwurf with abgelehnt status and date yesterday', () => {
       exist(bescheide.getBescheidContainer());
-
       contains(bescheide.getBescheidContainer(), abgelehntText + ' ' + getAdjustedDateGerman(-1));
-
       contains(bescheide.getBescheidContainer(), entwurfText);
     });
 
     it('should show caption Bescheid fortsetzen on button', () => {
       contains(vorgangFormularButtons.getBescheidenButton(), fortsetzenText);
     });
+  });
 
-    it('should show complete info after saving Bescheid', () => {
+  describe('should show complete info after saving Bescheid', () => {
+    it('should set date to two days before and continue to step 2', () => {
       vorgangFormularButtons.getBescheidenButton().click();
       enterWith(bescheidWizard.getDateInput(), getAdjustedDateGerman(-2));
       bescheidWizard.getWeiterButton().click();
-      uploadFile(bescheidWizard.getUploadBescheidButton(), TEST_FILE_BESCHEID_VALID);
-      notExist(bescheidWizard.getBescheidUploadSpinner());
-      uploadFile(bescheidWizard.getUploadAttachmentButton(), TEST_FILE_BESCHEID_ANHANG_VALID);
-      notExist(bescheidWizard.getAttachmentUploadSpinner());
+      bescheidWizard.isBescheidDocumentsStep();
+    });
 
-      bescheidWizard.getWeiterButton().click();
+    it('should upload files and continue to step 3', () => {
+      bescheidWizard.uploadBescheid(TEST_FILE_BESCHEID_VALID);
+      bescheidWizard.bescheidUploadSpinnerIsClosed();
+      bescheidWizard.uploadAttachment(TEST_FILE_BESCHEID_ANHANG_VALID);
+      bescheidWizard.attachmentSpinnerIsClosed();
+      bescheidWizard.weiter();
+
+      bescheidWizard.isBescheidVersendenStep();
+    });
+
+    it('should save Bescheid and close wizard', () => {
       bescheidWizard.getSaveButton().click();
       bescheidWizard.getConfirmAndSaveButton().click();
       waitForSpinnerToDisappear();
+      bescheidWizard.isClosed();
+    });
 
+    it('should show Bescheid as abgelehnt, and contain both files', () => {
       exist(bescheide.getBescheidContainer());
 
       contains(bescheide.getBescheidContainer(), abgelehntText);
-
       exist(bescheide.getFileBescheidValidInVorgang());
       exist(bescheide.getFileAnhangValidInVorgang());
     });
@@ -139,21 +171,35 @@ describe('Bescheid Info anzeigen', () => {
     });
 
     it('should download both attachments', () => {
-      bescheide.getFileBescheidValidInVorgang().click();
-      bescheide.getFileAnhangValidInVorgang().click();
-      countDownloadFiles().then((count) => {
-        expect(count).to.eq(2);
+      deleteDownloadFolder().then(() => {
+        bescheide.getFileBescheidValidInVorgang().click();
+        bescheide.getFileAnhangValidInVorgang().click();
+        readFileFromDownloads(TEST_FILE_BESCHEID_ANHANG_VALID).then(() => {
+          countDownloadFiles().then((count) => {
+            expect(count).to.eq(2);
+          });
+        });
       });
     });
+  });
 
-    it('should show second Bescheid after reopening Vorgang and creating new Bescheid', () => {
+  describe('should show second Bescheid after reopening Vorgang and creating new Bescheid', () => {
+    it('create new Bescheid and set it to abgelehnt', () => {
       vorgangFormularButtons.getWiedereroeffnenButton().click();
       vorgangFormularButtons.getBescheidenButton().click();
-      bescheidWizard.getAbgelehntButton().click();
-      bescheidWizard.getWeiterButton().click();
-      uploadFile(bescheidWizard.getUploadBescheidButton(), TEST_FILE_BESCHEID_VALID);
-      notExist(bescheidWizard.getBescheidUploadSpinner());
-      bescheidWizard.getWeiterButton().click();
+      bescheidWizard.ablehnen();
+      bescheidWizard.weiter();
+      bescheidWizard.isBescheidDocumentsStep();
+    });
+
+    it('should upload Bescheid and continue to step 3', () => {
+      bescheidWizard.uploadBescheid(TEST_FILE_BESCHEID_VALID);
+      bescheidWizard.bescheidUploadSpinnerIsClosed();
+      bescheidWizard.weiter();
+      bescheidWizard.isBescheidVersendenStep();
+    });
+
+    it('should show 2 Bescheid containers after saving', () => {
       bescheidWizard.getSaveButton().click();
       bescheidWizard.getConfirmAndSaveButton().click();
       exist(bescheidWizard.getBescheidSaveSpinner());
@@ -167,8 +213,10 @@ describe('Bescheid Info anzeigen', () => {
       exist(bescheide.getAbgelehntIconInHeader());
       contains(bescheide.getBeschiedenDateInHeader(), getAdjustedDateGerman(0));
     });
+  });
 
-    it('should show info on list page', () => {
+  describe('show Bescheid info on Vorgang list', () => {
+    it('should show Bescheid info on list page', () => {
       vorgangSubnavigationButtons.getBackButton().click();
 
       exist(bescheide.getBescheidListItem());
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-senden.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-senden.cy.ts
index ee5b49ac5ea8a9551b58a159f2007fdfeaef868b..20f733647019d1d1f7bb2f70ecb7aff0206291cd 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-senden.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-bescheid/vorgang-bescheid-senden.cy.ts
@@ -26,11 +26,11 @@ import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang
 
 registerLocaleData(localeDe, 'de', localeDeExtra);
 
-describe.skip('Bescheid senden', () => {
+describe('Bescheid senden', () => {
   const mainPage: MainPage = new MainPage();
   const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
 
-  const abgelehntText: string = 'Ihr Antrag wurde abgelehnt';
+  const anredeText: string = 'Sehr geehrte/r Antragsteller/in,';
   const mailText: string = 'Ihr Bescheid zum Antrag';
 
   const vorgangPage: VorgangPage = new VorgangPage();
@@ -67,7 +67,6 @@ describe.skip('Bescheid senden', () => {
         waitForSpinnerToDisappear();
 
         vorgangFormularButtons.getBescheidenButton().click();
-        bescheidWizard.getAbgelehntButton().click();
         enterWith(bescheidWizard.getDateInput(), getAdjustedDateGerman(1));
         bescheidWizard.getWeiterButton().click();
         uploadFile(bescheidWizard.getUploadBescheidButton(), TEST_FILE_BESCHEID_VALID);
@@ -86,13 +85,11 @@ describe.skip('Bescheid senden', () => {
 
       it('should contain correct text and both attachments', () => {
         const postfachMailItem: PostfachMailListItem = postfachMailContainer.getListItem(mailText);
-
         postfachMailItem.getRoot().click();
         waitForSpinnerToDisappear();
 
         const postfachListItem: PostfachMailListItem = postfachMailPage.getListItem(mailText);
-
-        contains(postfachMailPage.getMailText(), abgelehntText);
+        contains(postfachMailPage.getMailText(), anredeText);
 
         exist(
           postfachListItem
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-dateien-tab.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-dateien-tab.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..85fe66298c9e1653dd2d47ddb8b6e4108c71fc2c
--- /dev/null
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-dateien-tab.cy.ts
@@ -0,0 +1,133 @@
+import { registerLocaleData } from '@angular/common';
+import localeDe from '@angular/common/locales/de';
+import localeDeExtra from '@angular/common/locales/extra/de';
+import { AttachmentListE2EComponent } from 'apps/alfa-e2e/src/components/attachment/attachment.e2e.component';
+import { VorgangFormularDatenE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component';
+import { VorgangSubnavigationE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-subnavigation';
+import { FileDataE2E } from 'apps/alfa-e2e/src/model/binary-file';
+import {
+  createJpgAttachment,
+  createPdfAttachment,
+  createXmlRepresentation,
+  initGridFs,
+} from 'apps/alfa-e2e/src/support/binary-file-util';
+import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
+import { EingangE2E, VorgangE2E } from '../../../model/vorgang';
+import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
+import { VorgangPage } from '../../../page-objects/vorgang.po';
+import {
+  createJpgGridFsData,
+  createPdfGridFsData,
+  createXmlGridFsData,
+} from '../../../support/binary-file-util';
+import { dropCollections } from '../../../support/cypress-helper';
+import { contains, exist, notExist } from '../../../support/cypress.util';
+import { loginAsSabine } from '../../../support/user-util';
+import {
+  buildVorgang,
+  createVorgang,
+  initVorgaenge,
+  objectIds,
+} from '../../../support/vorgang-util';
+
+registerLocaleData(localeDe, 'de', localeDeExtra);
+
+describe('Dateien Tab', () => {
+  const mainPage: MainPage = new MainPage();
+  const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
+
+  const vorgangPage: VorgangPage = new VorgangPage();
+  const vorgangDatenFormular: VorgangFormularDatenE2EComponent =
+    vorgangPage.getFormularDatenContainer();
+  const vorgangSubnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation();
+  const attachmentList: AttachmentListE2EComponent = new AttachmentListE2EComponent();
+
+  const xmlFileName: string = 'XML-Daten.xml';
+  const jpgFileName: string = 'win.jpg';
+  const pdfFileName: string = 'Anlage_Vollmacht.pdf';
+
+  const xmlRepresentation: FileDataE2E = createXmlRepresentation();
+
+  const sonstigeAttachment = {
+    name: 'datei_sonstiges',
+    files: [createJpgAttachment(), createPdfAttachment()],
+  };
+
+  const eingangWithRepresentation: EingangE2E = {
+    ...createVorgang().eingangs[0],
+    numberOfRepresentations: 1,
+    representations: [xmlRepresentation],
+  };
+
+  const vorgangRepresentation: VorgangE2E = {
+    ...buildVorgang(objectIds[0], 'VorgangWithRepresentation'),
+    eingangs: [eingangWithRepresentation],
+  };
+
+  const eingangWithAttachments: EingangE2E = {
+    ...createVorgang().eingangs[0],
+    numberOfRepresentations: 1,
+    representations: [xmlRepresentation],
+    numberOfAttachments: 2,
+    attachments: [sonstigeAttachment],
+  };
+
+  const vorgangWithAttachments: VorgangE2E = {
+    ...buildVorgang(objectIds[1], 'VorgangWithAttachments'),
+    eingangs: [eingangWithAttachments],
+  };
+
+  before(() => {
+    initGridFs([createXmlGridFsData(), createPdfGridFsData(), createJpgGridFsData()]);
+    initVorgaenge([vorgangRepresentation, vorgangWithAttachments]);
+
+    loginAsSabine();
+
+    waitForSpinnerToDisappear();
+    exist(vorgangList.getRoot());
+  });
+
+  after(() => {
+    dropCollections();
+  });
+
+  describe('show Dateien contents', () => {
+    it('should not show Metadaten or Representation tab', () => {
+      vorgangList.getListItem(vorgangRepresentation.name).getRoot().click();
+      waitForSpinnerToDisappear();
+
+      notExist(vorgangDatenFormular.getMetadatenTab());
+      notExist(vorgangDatenFormular.getRepresentationTab());
+    });
+    it('should show 1 file in header of Dateien tab', () => {
+      contains(vorgangDatenFormular.getDateienTab(), '(1)');
+    });
+
+    it('should only show sub-header for Antrag', () => {
+      exist(vorgangDatenFormular.getFileListHeader());
+      notExist(vorgangDatenFormular.getAttachmentListHeader());
+    });
+
+    it('should show 1 XML file for Antragsdetails', () => {
+      exist(vorgangDatenFormular.getFileElementByName(xmlFileName));
+    });
+
+    it('should show 3 files in header of Dateien tab', () => {
+      vorgangSubnavigation.getBackButton().click();
+      vorgangList.getListItem(vorgangWithAttachments.name).getRoot().click();
+
+      contains(vorgangDatenFormular.getDateienTab(), '(3)');
+    });
+
+    it('should show sub-headers for Antrag and Anhänge', () => {
+      exist(vorgangDatenFormular.getFileListHeader());
+      exist(vorgangDatenFormular.getAttachmentListHeader());
+    });
+
+    it('should show attachments and download button', () => {
+      exist(vorgangDatenFormular.getFileElementByName(jpgFileName));
+      exist(vorgangDatenFormular.getFileElementByName(pdfFileName));
+      exist(attachmentList.getDownloadAttachmentsButton(vorgangDatenFormular.getRoot()));
+    });
+  });
+});
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts
index 926d415508c42364a82a165d6f33c6fbdab5b246..768acbc0f79869d9a834fd236fcc25232232808e 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts
@@ -24,6 +24,7 @@
 import { registerLocaleData } from '@angular/common';
 import localeDe from '@angular/common/locales/de';
 import localeDeExtra from '@angular/common/locales/extra/de';
+import { SnackBarE2EComponent } from 'apps/alfa-e2e/src/components/ui/snackbar.e2e.component';
 import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
 import {
   VorgangMoreMenuE2EComponent,
@@ -46,6 +47,8 @@ registerLocaleData(localeDe, 'de', localeDeExtra);
 
 describe('Vorgang exportieren', () => {
   const mainPage: MainPage = new MainPage();
+  const snackBar: SnackBarE2EComponent = mainPage.getSnackBar();
+
   const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
 
   const vorgangPage: VorgangPage = new VorgangPage();
@@ -100,14 +103,24 @@ describe('Vorgang exportieren', () => {
       vorgangMoreMenu.getButton().click({ force: true });
     });
 
-    it('should  show "Herunterladen" button in Abgeschlossen status', () => {
+    it('should handle snackbar after abschliessen', () => {
       vorgangFormularButtons.getAbschliessenButton().click();
+      waitForSpinnerToDisappear();
+
+      exist(snackBar.getCloseButton());
+      snackBar.getCloseButton().click();
+      notExist(snackBar.getMessage());
+    });
 
+    it('should show "Herunterladen" button in Abgeschlossen status', () => {
       vorgangMoreMenu.getButton().click();
+
       exist(menuItem.getButton());
+      vorgangMoreMenu.getButton().click({ force: true });
     });
 
     it('should have 1 file in download folder after download', () => {
+      vorgangMoreMenu.getButton().click();
       deleteDownloadFolder().then(() => {
         menuItem.getButton().click({ force: true });
         waitForSpinnerToDisappear();
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts
index 2a0e6f115c47059a992399afe671ab931407920f..774264c1145b03c36e535c670df13f69554e857f 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts
@@ -67,14 +67,7 @@ import {
   createWiedervorlageItem,
 } from 'apps/alfa-e2e/src/support/wiedervorlage-util';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
-import {
-  backspaceOn,
-  enterWith,
-  exist,
-  haveText,
-  haveValue,
-  notExist,
-} from '../../../support/cypress.util';
+import { backspaceOn, exist, haveText, haveValue, notExist } from '../../../support/cypress.util';
 import {
   UserRoleE2E,
   getUserSabine,
@@ -447,6 +440,7 @@ describe('VorgangList Suche', () => {
     describe('select vorgang in vorgangdetail preview list', () => {
       it('should navigate to vorgang on selection', () => {
         vorgangSearch.getInput().clear().type(vorgangOtherName);
+        waitForSpinnerToDisappear();
         exist(previewListItemVorgangOther.getRoot());
 
         previewListItemVorgangOther.getRoot().click();
@@ -697,13 +691,13 @@ describe('VorgangList Suche', () => {
 
   describe('empty search field', () => {
     it('should not search with empty input', () => {
-      doSearchWith('');
+      vorgangSearch.getInput().clear().type('{enter}');
 
       notExist(vorgangPage.getSpinner());
     });
   });
 
   function doSearchWith(searchBy: string): void {
-    enterWith(vorgangSearch.getInput(), searchBy);
+    vorgangSearch.doSearch(searchBy);
   }
 });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-views-filter.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-views-filter.cy.ts
index 7ed13f59c0f6caf94b0914eff020cf57fa7630c1..c2d95b6e8e7097f83c3cb9ac6e3ec80db42e8641 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-views-filter.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-views-filter.cy.ts
@@ -24,7 +24,6 @@ import { dropCollections, dropSearchIndex } from 'apps/alfa-e2e/src/support/cypr
 import {
   containClass,
   contains,
-  enterWith,
   exist,
   haveLength,
   haveText,
@@ -770,11 +769,11 @@ describe('Vorgang views and filter', () => {
       });
 
       it('should unselect Alle filter', () => {
-        isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter());
+        isButtonToggleNotChecked(navigation.getAlleFilter());
       });
 
       it('should keep Meine Vorgänge unselected', () => {
-        isButtonToggleNotChecked(navigation.getAlleFilter());
+        isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter());
       });
 
       it('should keep view selection', () => {
@@ -808,7 +807,7 @@ describe('Vorgang views and filter', () => {
 
       it('should keep filter selection', () => {
         isButtonToggleChecked(navigation.getAlleFilter());
-        isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter());
+        isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter());
       });
 
       it('should unselect Meine Vorgänge filter', () => {
@@ -899,7 +898,7 @@ describe('Vorgang views and filter', () => {
   });
 
   function doSearch(searchString: string): void {
-    enterWith(vorgangSearch.getInput(), searchString);
+    vorgangSearch.doSearch(searchString);
   }
 
   function isNotSelected(element) {
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.erledigen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.erledigen.cy.ts
index 6d63193ad9a0fae0dacccbd7b9f79cab989cdb88..994c49a6065a7b85d0f294803291af520ed6b252 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.erledigen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.erledigen.cy.ts
@@ -144,6 +144,8 @@ describe('Wiedervorlage erledigen/wiedereroeffnen', () => {
       waitforSpinnerToAppear();
       waitForSpinnerToDisappear();
 
+      wait(1000, 'Wait for async BE to complete');
+
       containClass(wiedervorlageContainer.getStatusDot(), 'erledigt');
       contains(
         snackBar.getMessage(),
@@ -185,6 +187,8 @@ describe('Wiedervorlage erledigen/wiedereroeffnen', () => {
       waitforSpinnerToAppear();
       waitForSpinnerToDisappear();
 
+      wait(1000, 'Wait for async BE to complete');
+
       notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt');
       contains(
         snackBar.getMessage(),
@@ -208,36 +212,66 @@ describe('Wiedervorlage erledigen/wiedereroeffnen', () => {
     });
   });
 
-  describe('tiny pentest for erledigen/wiedereroeffnen', () => {
+  describe('View Wiedervorlage view icon', () => {
     const wiedervorlage: WiedervorlageInVorgangE2EComponent =
       wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff);
+    const locatorIconIsOverdue: string = 'wiedervorlage-icon-is-overdue';
+    const locatorIconDefault: string = 'wiedervorlage-icon-default';
 
-    it('should open wiedervorlage on click', () => {
-      wait(500);
-      wiedervorlage.getLink().click();
-
+    it('back to vorgang list', () => {
+      wait(1000, 'Wait for async BE to complete');
+      vorgangPage.getSubnavigation().getBackButton().click();
       waitForSpinnerToDisappear();
+    });
 
-      exist(subnavigation.getRoot());
+    it('should show red icon', () => {
+      exist(wiedervorlagenView.getRoot().findTestElementWithClass(locatorIconIsOverdue));
+    });
+
+    it('Open Vorgang-Detail-Page', () => {
+      mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click();
+      waitForSpinnerToDisappear();
     });
 
     it('should mark as erledigt', () => {
+      const link = wiedervorlage.getLink();
+      link.click();
+      waitForSpinnerToDisappear();
       subnavigation.erledigen();
+      waitForSpinnerToDisappear();
 
-      waitforSpinnerToAppear();
+      wait(1000, 'Wait for async BE to complete');
+
+      subnavigation.navigateBack();
       waitForSpinnerToDisappear();
+    });
 
-      containClass(wiedervorlageContainer.getStatusDot(), 'erledigt');
-      contains(
-        snackBar.getMessage(),
-        `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde erledigt`,
-      );
+    it('back to vorgang list', () => {
+      vorgangPage.getSubnavigation().getBackButton().click();
+      waitForSpinnerToDisappear();
     });
 
-    it('should close snackBar on close', () => {
-      snackBar.getCloseButton().click();
+    it('should show default icon', () => {
+      exist(wiedervorlagenView.getRoot().findTestElementWithClass(locatorIconDefault));
+    });
+  });
 
-      notExist(snackBar.getMessage());
+  describe('tiny lasttest for erledigen/wiedereroeffnen', () => {
+    const wiedervorlage: WiedervorlageInVorgangE2EComponent =
+      wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff);
+
+    it('Open Vorgang-Detail-Page', () => {
+      mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click();
+      waitForSpinnerToDisappear();
+    });
+
+    it('should open wiedervorlage on click', () => {
+      wait(500);
+      wiedervorlage.getLink().click();
+
+      waitForSpinnerToDisappear();
+
+      exist(subnavigation.getRoot());
     });
 
     it('should mark as open', () => {
@@ -297,56 +331,32 @@ describe('Wiedervorlage erledigen/wiedereroeffnen', () => {
       notExist(snackBar.getMessage());
     });
 
-    it('should open vorgang detail on click on back', () => {
-      subnavigation.navigateBack();
+    it('should mark as erledigt', () => {
+      subnavigation.erledigen();
 
       waitforSpinnerToAppear();
       waitForSpinnerToDisappear();
 
-      exist(vorgangDetailHeader.getRoot());
-    });
-  });
-
-  //Test an die richtige Stelle verschieben und den Test vereinfachen
-  describe('View item icon', () => {
-    const wiedervorlage: WiedervorlageInVorgangE2EComponent =
-      wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff);
-    const locatorIconIsOverdue: string = 'wiedervorlage-icon-is-overdue';
-    const locatorIconDefault: string = 'wiedervorlage-icon-default';
-
-    it('back to vorgang list', () => {
-      wait(500);
-      vorgangPage.getSubnavigation().getBackButton().click();
-      waitForSpinnerToDisappear();
+      containClass(wiedervorlageContainer.getStatusDot(), 'erledigt');
+      contains(
+        snackBar.getMessage(),
+        `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde erledigt`,
+      );
     });
 
-    it('should show red icon', () => {
-      exist(wiedervorlagenView.getRoot().getTestElementWithClass(locatorIconIsOverdue));
-    });
+    it('should close snackBar on close', () => {
+      snackBar.getCloseButton().click();
 
-    it('Open Vorgang-Detail-Page', () => {
-      mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click();
-      waitForSpinnerToDisappear();
+      notExist(snackBar.getMessage());
     });
 
-    it('should mark as erledigt', () => {
-      wait(500);
-      wiedervorlage.getLink().click();
-      waitForSpinnerToDisappear();
-      subnavigation.erledigen();
-      waitForSpinnerToDisappear();
+    it('should open vorgang detail on click on back', () => {
       subnavigation.navigateBack();
-      waitForSpinnerToDisappear();
-    });
 
-    it('back to vorgang list', () => {
-      wait(500);
-      vorgangPage.getSubnavigation().getBackButton().click();
+      waitforSpinnerToAppear();
       waitForSpinnerToDisappear();
-    });
 
-    it('should show default icon', () => {
-      exist(wiedervorlagenView.getRoot().getTestElementWithClass(locatorIconDefault));
+      exist(vorgangDetailHeader.getRoot());
     });
   });
 });
diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml
index 480b4e1dd5db361f8aff3f159d6302851b98a875..c73587a0b07ff1fb36e484323bd8f5ea31a19300 100644
--- a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml
+++ b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml
@@ -4,12 +4,11 @@ ozgcloud:
 e2eTest: true
 project:
   destinations:
-    - namespace: '*'
+    - namespace: "*"
       server: https://kubernetes.default.svc
 alfa:
   env:
-    overrideSpringProfiles: 'oc,e2e,dev'
-    ozgcloud_feature_bescheid-wizard: "true"
+    overrideSpringProfiles: "oc,e2e,dev"
   ingress:
     use_staging_cert: true
   ozgcloud:
@@ -20,7 +19,7 @@ alfa:
 
 vorgang_manager:
   env:
-    overrideSpringProfiles: 'oc,e2e,dev'
+    overrideSpringProfiles: "oc,e2e,dev"
     ozgcloud_bescheid_smart_documents_url: http://smocker:8080/smartdocuments
     ozgcloud_bescheid_smart_documents_basic_auth_username: MGM
     ozgcloud_bescheid_smart_documents_basic_auth_password: MGM
@@ -80,7 +79,7 @@ smocker:
       response:
         status: 500
         headers:
-          body: 'Da ist etwas schiefgelaufen'
+          body: "Da ist etwas schiefgelaufen"
 
     # bayernid
     - request:
diff --git a/alfa-client/apps/alfa-e2e/src/support/commands.ts b/alfa-client/apps/alfa-e2e/src/support/commands.ts
index 1d1403d708893387744dec0e12e7783f116802a6..180457361a59046324cdf21cdb28989945f81b79 100644
--- a/alfa-client/apps/alfa-e2e/src/support/commands.ts
+++ b/alfa-client/apps/alfa-e2e/src/support/commands.ts
@@ -91,6 +91,9 @@ Cypress.Commands.add('getTestElement', (selector, ...args) => {
 });
 
 Cypress.Commands.add('getTestElementWithClass', (selector, ...args) => {
+  console.log(
+    'Achtung: Potentiell nicht eindeutiges Ergebnis, weil eine data-test-class mit cy.get() von der DOM-Root aus gesucht wird.',
+  );
   return cy.get(`[${DATA_TEST_CLASS}="${selector}"]`, ...args);
 });
 
@@ -106,7 +109,7 @@ Cypress.Commands.add(
   },
 );
 
-Cypress.Commands.add('findElement', { prevSubject: true }, (subject: any, selector) => {
+Cypress.Commands.add('findElement', { prevSubject: true }, (subject: any, selector: string) => {
   return subject.find(selector);
 });
 
@@ -250,8 +253,8 @@ Cypress.Commands.add('addMockToSmocker', (mock) => {
       url: `${getSmockerUrl()}/mocks`,
       body: mockFile,
       headers: {
-        "Content-Type": "application/x-yaml"
-      }
+        'Content-Type': 'application/x-yaml',
+      },
     });
   });
 });
@@ -270,4 +273,4 @@ function getSmockerUrl(): string {
 
 function getSmockerEnv(): string {
   return Cypress.env(CypressEnv.SMOCKER);
-}
\ No newline at end of file
+}
diff --git a/alfa-client/apps/alfa-e2e/src/support/cypress-helper.ts b/alfa-client/apps/alfa-e2e/src/support/cypress-helper.ts
index cc70ec8dbe3806519598d89d2482029f70699f7a..90c0c0b4058f983b0cb51861d8b632084cb2a8a3 100644
--- a/alfa-client/apps/alfa-e2e/src/support/cypress-helper.ts
+++ b/alfa-client/apps/alfa-e2e/src/support/cypress-helper.ts
@@ -40,6 +40,8 @@ enum CypressTasks {
   INIT_USERMANAGER_DATA = 'initUsermanagerData',
   COUNT_FILES = 'countFiles',
   DELETE_FOLDER = 'deleteFolder',
+  UNZIP_FILE = 'unzipDownloadFile',
+  GET_DOWNLOAD_FILES = 'getDownloadFiles',
 }
 
 enum MongoCollections {
@@ -136,6 +138,14 @@ export function deleteDownloadFolder() {
   return cy.task(CypressTasks.DELETE_FOLDER, DOWNLOAD_FOLDER);
 }
 
+export function unzipDownloadFile(file: string) {
+  return cy.task(CypressTasks.UNZIP_FILE, { folderName: DOWNLOAD_FOLDER, fileName: file });
+}
+
+export function getDownloadFiles(): Cypress.Chainable<Array<string>> {
+  return cy.task(CypressTasks.GET_DOWNLOAD_FILES, DOWNLOAD_FOLDER);
+}
+
 export function scrollToWindowBottom(): void {
   cy.window().scrollTo('bottom');
 }
@@ -169,8 +179,11 @@ export function urlShouldInclude(text: string) {
 }
 
 //TODO: anders loesen -> bad practice
-export function wait(ms: number): void {
+export function wait(ms: number, reason = ''): void {
   cy.wait(ms);
+  if (reason) {
+    console.log(`Had to wait ${ms}ms because of: ${reason}`);
+  }
 }
 //
 
@@ -178,8 +191,8 @@ export function reload(): void {
   cy.reload();
 }
 
-export function readFileFromDownloads(fileName: string) {
-  return cy.readFile(`${DOWNLOAD_FOLDER}/${fileName}`);
+export function readFileFromDownloads(fileName: string): Cypress.Chainable<any> {
+  return cy.readFile(`${DOWNLOAD_FOLDER}/${fileName}`, { timeout: 5000 });
 }
 
 export function pressTab(): void {
@@ -202,4 +215,4 @@ export function addSmockerMock(mock: SmockerMocks): void {
 
 export function resetSmocker(): void {
   cy.resetSmocker();
-}
\ No newline at end of file
+}
diff --git a/alfa-client/apps/alfa-e2e/src/support/cypress-tasks.ts b/alfa-client/apps/alfa-e2e/src/support/cypress-tasks.ts
index 1e965a342e415f6825afaa78d27a684a8a125bfa..a82b4f736601daf7f1b3164cbb45818a609e29de 100644
--- a/alfa-client/apps/alfa-e2e/src/support/cypress-tasks.ts
+++ b/alfa-client/apps/alfa-e2e/src/support/cypress-tasks.ts
@@ -1,5 +1,7 @@
 import { readdir, remove } from 'fs-extra';
 import { Db, Long, MongoClient, ObjectId } from 'mongodb';
+const fs = require('fs');
+const decompress = require('decompress');
 
 const Binary = require('mongodb').Binary;
 
@@ -54,6 +56,15 @@ module.exports = (on: any, config: any) => {
       deleteFolder(folderName);
       return 0;
     },
+    getDownloadFiles(folderName: string) {
+      console.log('get files in folder %s', folderName);
+      return getDownloadFiles(folderName);
+    },
+    unzipDownloadFile({ folderName, fileName }) {
+      console.log('unzip file %s in folder %s', fileName, folderName);
+      unzipFile(folderName, fileName);
+      return 0;
+    },
   });
 
   // Workaround für Angular 13 und Cypress mit Webpack 4,
@@ -333,3 +344,14 @@ function deleteFolder(folderName: string): void {
       throw new Error(`Failed to delete folder: ${err.message}`);
     });
 }
+
+function getDownloadFiles(folderName: string): Promise<Array<string>> {
+  return fs.readdirSync(folderName);
+}
+
+function unzipFile(folderName: string, fileName: string): void {
+  console.log('File: ' + folderName + fileName);
+
+  decompress(folderName + '/' + fileName, folderName);
+  return null;
+}
diff --git a/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts b/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts
index 2e22bc2a6f6bc43f622ebac4772364105bfb9ccc..4440874cbfcc512a5b23c9394c60f50f15e07d21 100644
--- a/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts
+++ b/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts
@@ -22,6 +22,8 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 
+import { wait } from './cypress-helper';
+
 //TODO Naming der Methoden geradeziehen
 
 export function containClass(element: any, cssClass: string): void {
@@ -101,6 +103,10 @@ export function shouldHaveAttributeBeLowerThan(element: any, attributeName: stri
 }
 //
 
+export function shouldHaveAttribute(element: any, name: string, value: string) {
+  element.should('have.attr', name, value);
+}
+
 export function visible(element: any) {
   element.should('be.visible');
 }
@@ -113,8 +119,14 @@ export function enter(element: any): void {
   element.clear().type(CypressKeyboardActions.ENTER);
 }
 
-export function enterWith(element: any, value: any): void {
-  element.clear().type(value + CypressKeyboardActions.ENTER);
+export function enterWith(
+  element: Cypress.Chainable<JQuery<HTMLElement>>,
+  value: string,
+  delayBeforeEnter: number = 200,
+): void {
+  element.clear().type(value);
+  wait(delayBeforeEnter);
+  element.type(CypressKeyboardActions.ENTER);
 }
 
 export function backspaceOn(element: any): void {
diff --git a/alfa-client/apps/demo/src/app/app.component.html b/alfa-client/apps/demo/src/app/app.component.html
index 4ecd2941d74717e3ef1791e8a0c1e4e039da9b66..81bc4dff284d5e739981af85b8d4e1cc0c4b3844 100644
--- a/alfa-client/apps/demo/src/app/app.component.html
+++ b/alfa-client/apps/demo/src/app/app.component.html
@@ -15,7 +15,7 @@
     </div>
     <main class="flex-auto bg-background-50 p-6">
       <div class="w-96">
-        <ods-attachment-container>
+        <ods-attachment-wrapper>
           <ods-attachment
             caption="Mein_2Bescheid.pdf"
             description="234 kB"
@@ -39,7 +39,7 @@
             fileType="pdf"
           >
           </ods-attachment>
-        </ods-attachment-container>
+        </ods-attachment-wrapper>
       </div>
 
       <form id="antrag_bescheiden_form" [formGroup]="exampleForm">
diff --git a/alfa-client/apps/demo/src/app/app.component.ts b/alfa-client/apps/demo/src/app/app.component.ts
index 58a09ee4d02b29261200d0f6f0db78b2bda20baa..5d64b15a623f2330d29201455ec298907bcd94fa 100644
--- a/alfa-client/apps/demo/src/app/app.component.ts
+++ b/alfa-client/apps/demo/src/app/app.component.ts
@@ -5,8 +5,8 @@ import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
 import { RouterModule } from '@angular/router';
 import {
   AttachmentComponent,
-  AttachmentContainerComponent,
   AttachmentIconComponent,
+  AttachmentWrapperComponent,
   BescheidGenerateIconComponent,
   BescheidUploadIconComponent,
   ButtonCardComponent,
@@ -34,7 +34,7 @@ import { CustomStepperComponent } from './components/cdk-demo/custom-stepper.com
   imports: [
     CommonModule,
     AttachmentComponent,
-    AttachmentContainerComponent,
+    AttachmentWrapperComponent,
     ButtonComponent,
     ButtonCardComponent,
     FileUploadButtonComponent,
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts
index 66db648e5e870b40619f321f04321b35b763e93d..bca9352718c8cbdb0e8f0434095d574215da1577 100644
--- a/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts
+++ b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts
@@ -1,6 +1,6 @@
 import { isNotNil } from '@alfa-client/tech-shared';
 import { Component, Input } from '@angular/core';
-import { FormControlEditorAbstractComponent } from 'libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component';
+import { FormControlEditorAbstractComponent } from '@ods/component';
 
 @Component({
   selector: 'text-field',
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
index 78fe8433b135b716b9882a8c4a7bf4cccd2fef0b..228b24efb9cd33d7d236fbb0a5b4a4499cee4169 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
@@ -1520,4 +1520,14 @@ describe('BescheidService', () => {
       });
     });
   });
+
+  describe('clear attachment upload', () => {
+    it('should clear stateresource', () => {
+      service.uploadAttachmentInProgress$.next(createStateResource(createUploadFileInProgress()));
+
+      service.clearAttachmentUpload();
+
+      expect(service.uploadAttachmentInProgress$.value).toEqual(createEmptyStateResource());
+    });
+  });
 });
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
index a8994d7ff2c9f8d74952af4e523dd240543e8929..76b74767032eac3979371d834d17c59217323600 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
@@ -589,4 +589,8 @@ export class BescheidService {
   public getUploadedAttachment(): Observable<StateResource<BinaryFileResource>> {
     return this.uploadedAttachment$.asObservable();
   }
+
+  public clearAttachmentUpload(): void {
+    this.uploadAttachmentInProgress$.next(createEmptyStateResource());
+  }
 }
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/bescheid-list-in-vorgang.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/bescheid-list-in-vorgang.component.html
index 8c0d2203d740cd0bba3db4dc9d8642178677d0ae..09e3689508466b42cb14f601cef86e5e1e82637c 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/bescheid-list-in-vorgang.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/bescheid-list-in-vorgang.component.html
@@ -1,5 +1,5 @@
 <div class="flex max-w-xl flex-col gap-4">
-  <ods-bescheid-container
+  <ods-bescheid-wrapper
     *ngFor="let bescheid of bescheidList | toEmbeddedResources: bescheidListLinkRel.BESCHEID_LIST"
     data-test-id="bescheid-container-in-vorgang"
   >
@@ -23,5 +23,5 @@
       [resource]="bescheid"
       [linkRel]="bescheidLinkRel.ATTACHMENTS"
     ></alfa-binary-file-list-container>
-  </ods-bescheid-container>
+  </ods-bescheid-wrapper>
 </div>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/bescheid-list-in-vorgang.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/bescheid-list-in-vorgang.component.spec.ts
index e0d873aa1642ddef9bbd08cf7ced139549f24b50..60b406d0b6ac33394f4fbf38e16e8f22bcd0aa31 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/bescheid-list-in-vorgang.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/bescheid-list-in-vorgang.component.spec.ts
@@ -5,7 +5,7 @@ import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-u
 import { DatePipe } from '@angular/common';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIcon } from '@angular/material/icon';
-import { BescheidContainerComponent, BescheidStatusTextComponent } from '@ods/system';
+import { BescheidStatusTextComponent, BescheidWrapperComponent } from '@ods/system';
 import {
   createBescheidListResource,
   createBescheidResource,
@@ -37,7 +37,7 @@ describe('BescheidListInVorgangComponent', () => {
         MockComponent(DocumentInBescheidContainerComponent),
         MockComponent(BinaryFileListContainerComponent),
         MockComponent(BescheidStatusTextComponent),
-        MockComponent(BescheidContainerComponent),
+        MockComponent(BescheidWrapperComponent),
       ],
     }).compileComponents();
 
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/document-in-bescheid-container/document-in-bescheid-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/document-in-bescheid-container/document-in-bescheid-container.component.html
index aefc4c75af7cfc3bf0669e8c9fb99665f464fde4..464b7a0a4ff8783533e4160bc53d3c007eae5eed 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/document-in-bescheid-container/document-in-bescheid-container.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/document-in-bescheid-container/document-in-bescheid-container.component.html
@@ -1,9 +1,9 @@
 <ng-container *ngIf="documentStateResource$ | async as documentStateResource">
-  <ods-attachment-container>
+  <ods-attachment-wrapper>
     <alfa-binary-file-uri-container
       *ngIf="documentStateResource.resource | hasLink: documentLinkRel.FILE"
       data-test-class="binary-file-uri-container"
       [binaryFileUri]="documentStateResource.resource | getUrl: documentLinkRel.FILE"
     ></alfa-binary-file-uri-container>
-  </ods-attachment-container>
+  </ods-attachment-wrapper>
 </ng-container>
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/document-in-bescheid-container/document-in-bescheid-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/document-in-bescheid-container/document-in-bescheid-container.component.spec.ts
index f005143e8fcd38ef21d5fe5a41753b7f98c347a6..6d4e62565ec7e6fa5e80f193cfa8c8c56fc2885d 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/document-in-bescheid-container/document-in-bescheid-container.component.spec.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-list-in-vorgang-container/bescheid-list-in-vorgang/document-in-bescheid-container/document-in-bescheid-container.component.spec.ts
@@ -16,7 +16,7 @@ import {
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import faker from '@faker-js/faker';
 import { ResourceUri, getUrl } from '@ngxp/rest';
-import { AttachmentContainerComponent } from '@ods/system';
+import { AttachmentWrapperComponent } from '@ods/system';
 import { DocumentLinkRel } from 'libs/bescheid-shared/src/lib/document.linkrel';
 import { DocumentResource } from 'libs/bescheid-shared/src/lib/document.model';
 import { getDataTestClassOf } from 'libs/tech-shared/test/data-test';
@@ -45,7 +45,7 @@ describe('DocumentInBescheidContainerComponent', () => {
         HasLinkPipe,
         GetUrlPipe,
         MockComponent(BinaryFileUriContainerComponent),
-        MockComponent(AttachmentContainerComponent),
+        MockComponent(AttachmentWrapperComponent),
       ],
       providers: [
         {
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid.module.ts b/alfa-client/libs/bescheid/src/lib/bescheid.module.ts
index ab43b96faec19afccbfddc606e2b0b942174c012..e6faf4a67f1e937d0aab66ae583415d8a4030bd9 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid.module.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid.module.ts
@@ -16,8 +16,8 @@ import { CreateBescheidButtonContainerComponent } from './create-bescheid-button
 import { CreateBescheidButtonComponent } from './create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component';
 
 import {
-  BescheidContainerComponent,
   BescheidStatusTextComponent,
+  BescheidWrapperComponent,
   CloseIconComponent,
   StampIconComponent,
 } from '@ods/system';
@@ -31,7 +31,7 @@ import {
     UiModule,
     CommandSharedModule,
     BescheidStatusTextComponent,
-    BescheidContainerComponent,
+    BescheidWrapperComponent,
     StampIconComponent,
     CloseIconComponent,
   ],
diff --git a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts
index c6fcec9a06a7d81756a40aaa2afe23b226cc12bd..4a29ed56be2585d9746e49526e4977f66dbb2239 100644
--- a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts
+++ b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts
@@ -74,7 +74,7 @@ export class BinaryFileEffects {
   loadBinaryFileList$ = createEffect(() =>
     this.actions$.pipe(
       ofType(BinaryFileActions.loadBinaryFileList),
-      switchMap((props: LoadBinaryFileListProps) =>
+      mergeMap((props: LoadBinaryFileListProps) =>
         this.repository.getFiles(props.resource, props.linkRel).pipe(
           map((binaryFileList: BinaryFileListResource) => props.successAction(binaryFileList)),
           catchError((error) => of(props.failureAction(error.error))),
diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts
index 9ad810e73de5bb0a2015ad9b012adc2700f705d1..071f1a03138fae246311d53e97be4819b029127b 100644
--- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts
+++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts
@@ -21,26 +21,34 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { HttpClient, HttpHeaders } from '@angular/common/http';
-import { faker } from '@faker-js/faker';
 import {
+  BlobWithFileName,
   ContentType,
   GetRequestOptions,
   HttpErrorHandler,
+  HttpHeader,
   ListResource,
   TechSharedModule,
 } from '@alfa-client/tech-shared';
 import { mock, mockClass, useFromMock } from '@alfa-client/test-utils';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { faker } from '@faker-js/faker';
 import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest';
 import { cold, hot } from 'jest-marbles';
 import { DummyLinkRel } from 'libs/tech-shared/test/dummy';
 import { createDummyListResource, createDummyResource } from 'libs/tech-shared/test/resource';
-import { of } from 'rxjs';
-import { createBinaryFileResource } from '../../test/binary-file';
+import { Observable, of } from 'rxjs';
+import {
+  createBinaryFileResource,
+  createBlob,
+  createGetRequestOptions,
+} from '../../test/binary-file';
 import { BinaryFileLinkRel } from './binary-file.linkrel';
 import { BinaryFileResource } from './binary-file.model';
 import { BinaryFileRepository } from './binary-file.repository';
 
+import * as HttpUtil from '../../../tech-shared/src/lib/http.util';
+
 describe('BinaryFileRepository', () => {
   let repository: BinaryFileRepository;
 
@@ -181,7 +189,7 @@ describe('BinaryFileRepository', () => {
     });
 
     function getExpectedRequestOptions(): HttpHeaders {
-      return new HttpHeaders().set('Accept', [
+      return new HttpHeaders().set(HttpHeader.ACCEPT, [
         ContentType.APPLICATION_PDF,
         ContentType.APPLICATION_JSON,
       ]);
@@ -224,4 +232,55 @@ describe('BinaryFileRepository', () => {
       expect(resourceWrapper.get).toHaveBeenCalledWith(DummyLinkRel.DUMMY);
     });
   });
+
+  describe('downloadArchive', () => {
+    const blob: Blob = createBlob();
+    const uri: ResourceUri = faker.internet.url();
+
+    const blobWithFileName: BlobWithFileName = { blob, fileName: faker.name.firstName() };
+
+    beforeEach(() => {
+      httpClient.get.mockReturnValue(hot('a', { a: blob }));
+      jest.spyOn(HttpUtil, 'buildBlobWithFileName').mockReturnValue(blobWithFileName);
+    });
+
+    it('should call httpClient', () => {
+      const requestOptions: GetRequestOptions = createGetRequestOptions();
+      repository.buildRequestOptionsForArchive = jest.fn().mockReturnValue(requestOptions);
+
+      repository.downloadArchive(uri);
+
+      expect(httpClient.get).toHaveBeenCalledWith(uri, requestOptions);
+    });
+
+    it('should return value', () => {
+      const result: Observable<BlobWithFileName> = repository.downloadArchive(uri);
+
+      expect(result).toBeObservable(cold('b', { b: blobWithFileName }));
+    });
+
+    describe('buildRequestOptionsForArchive', () => {
+      it('should return httpHeaders', () => {
+        const result: GetRequestOptions = repository.buildRequestOptionsForArchive();
+
+        expect(result.responseType).toEqual('blob');
+      });
+
+      it('should return responseType', () => {
+        const result: GetRequestOptions = repository.buildRequestOptionsForArchive();
+
+        expect(result.headers).toEqual(buildExpectedRequestOptions());
+      });
+
+      it('should return observe', () => {
+        const result: GetRequestOptions = repository.buildRequestOptionsForArchive();
+
+        expect((<any>result).observe).toEqual('response');
+      });
+    });
+
+    function buildExpectedRequestOptions(): HttpHeaders {
+      return new HttpHeaders().set(HttpHeader.ACCEPT, ContentType.APPLICATION_OCTET_STREAM);
+    }
+  });
 });
diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.ts
index 9e2d3f4548b00e0fbbe64f7971b4af6c44356479..ef0c1b6762f8ac2177282f36b07d64879f8aac7c 100644
--- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.ts
+++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.ts
@@ -21,16 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { HttpClient, HttpHeaders } from '@angular/common/http';
-import { Injectable } from '@angular/core';
 import {
+  BlobWithFileName,
   ContentType,
   GetRequestOptions,
   HttpHeader,
   SkipInterceptor,
+  buildBlobWithFileName,
 } from '@alfa-client/tech-shared';
+import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
+import { Injectable } from '@angular/core';
 import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest';
-import { Observable } from 'rxjs';
+import { Observable, map } from 'rxjs';
 import { BinaryFileLinkRel } from './binary-file.linkrel';
 import { BinaryFileListResource, BinaryFileResource } from './binary-file.model';
 
@@ -41,7 +43,11 @@ export class BinaryFileRepository {
     private resourceFactory: ResourceFactory,
   ) {}
 
-  public uploadFile(resource: Resource, linkRel: string, file: File): Observable<any> {
+  public uploadFile(
+    resource: Resource,
+    linkRel: string,
+    file: File,
+  ): Observable<HttpResponse<Object>> {
     const formData: FormData = new FormData();
 
     formData.append('file', file, file.name);
@@ -89,4 +95,16 @@ export class BinaryFileRepository {
   public getFiles(resource: Resource, linkRel: string): Observable<BinaryFileListResource> {
     return this.resourceFactory.from(resource).get(linkRel);
   }
+
+  public downloadArchive(uri: ResourceUri): Observable<BlobWithFileName> {
+    return this.httpClient
+      .get<HttpResponse<Blob>>(uri, this.buildRequestOptionsForArchive())
+      .pipe(map(buildBlobWithFileName));
+  }
+
+  buildRequestOptionsForArchive(): GetRequestOptions {
+    let headers = new HttpHeaders();
+    headers = headers.set(HttpHeader.ACCEPT, ContentType.APPLICATION_OCTET_STREAM);
+    return <GetRequestOptions>{ headers, responseType: 'blob' as 'json', observe: 'response' };
+  }
 }
diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.spec.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.spec.ts
index ff3225272c34a37e6ccb820eaed7b82c39e4ef6a..9d69ae78a151079401a9d94caceff99e8c980675 100644
--- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.spec.ts
+++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.spec.ts
@@ -21,30 +21,32 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
-import { faker } from '@faker-js/faker';
 import {
+  BlobWithFileName,
+  StateResource,
   createEmptyStateResource,
   createStateResource,
-  StateResource,
 } from '@alfa-client/tech-shared';
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
 import { SnackBarService } from '@alfa-client/ui';
-import { Resource } from '@ngxp/rest';
+import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
+import { fakeAsync, tick } from '@angular/core/testing';
+import { faker } from '@faker-js/faker';
+import { Resource, ResourceUri } from '@ngxp/rest';
 import { cold, hot } from 'jest-marbles';
-import { createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file';
+import { createBinaryFileResource, createBlob } from 'libs/binary-file-shared/test/binary-file';
 import {
   VALIDATION_MESSAGES,
   ValidationMessageCode,
 } from 'libs/tech-shared/src/lib/validation/tech.validation.messages';
 import { DummyLinkRel } from 'libs/tech-shared/test/dummy';
 import { createDummyResource } from 'libs/tech-shared/test/resource';
-import { of } from 'rxjs';
+import { Observable, of } from 'rxjs';
+import { createHttpErrorResponse } from '../../../tech-shared/test/http';
+import { singleHot } from '../../../tech-shared/test/marbles';
 import { BinaryFileResource } from './binary-file.model';
 import { BinaryFileRepository } from './binary-file.repository';
 import { BinaryFileService } from './binary-file.service';
-import { fakeAsync, tick } from '@angular/core/testing';
-import { createHttpErrorResponse } from '../../../tech-shared/test/http';
 
 describe('BinaryFileService', () => {
   let service: BinaryFileService;
@@ -80,7 +82,23 @@ describe('BinaryFileService', () => {
       expect(repository.download).toHaveBeenCalledWith(binaryFileResource);
     });
 
-    describe('save file', () => {
+    it('should return value', () => {
+      repository.download.mockReturnValue(singleHot(blob, '-a'));
+
+      const returnValue: Observable<StateResource<Blob>> = service.downloadFile(
+        binaryFileResource,
+        downloadNamePrefix,
+      );
+
+      expect(returnValue).toBeObservable(
+        cold('ab', {
+          a: createEmptyStateResource(true),
+          b: createStateResource(blob),
+        }),
+      );
+    });
+
+    describe('save data', () => {
       describe('on existing response', () => {
         it('should save file without prefix', () => {
           service.saveBinaryFile(blob, binaryFileResource, undefined);
@@ -122,12 +140,72 @@ describe('BinaryFileService', () => {
     });
   });
 
+  describe('download archive', () => {
+    const blob: Blob = createBlob();
+    const resourceUri: ResourceUri = faker.internet.url();
+
+    beforeEach(() => {
+      service.save = jest.fn();
+      repository.downloadArchive.mockReturnValue(hot('a', { a: blob }));
+    });
+
+    it('should call repository', () => {
+      service.downloadArchive(resourceUri);
+
+      expect(repository.downloadArchive).toHaveBeenCalledWith(resourceUri);
+    });
+
+    it('should return value', () => {
+      repository.downloadArchive.mockReturnValue(singleHot(blob, '-a'));
+      service.saveData = jest.fn().mockReturnValue(createStateResource(blob));
+
+      const returnValue: Observable<StateResource<Blob>> = service.downloadArchive(resourceUri);
+
+      expect(returnValue).toBeObservable(
+        cold('ab', {
+          a: createEmptyStateResource(true),
+          b: createStateResource(blob),
+        }),
+      );
+    });
+
+    describe('save data', () => {
+      const fileName: string = faker.random.word();
+      const blobWithFileName: BlobWithFileName = { blob, fileName };
+
+      describe('on existing response', () => {
+        it('should save file', () => {
+          service.saveData(blobWithFileName);
+
+          expect(service.save).toHaveBeenCalledWith(blob, fileName);
+        });
+
+        it('should return loaded stateResource', () => {
+          const result: StateResource<Blob> = service.saveData(blobWithFileName);
+
+          expect(result).toEqual(createStateResource(blob));
+        });
+      });
+
+      describe('on non existing response', () => {
+        it('should return loading stateResource', () => {
+          const result: StateResource<Blob> = service.saveData({
+            ...blobWithFileName,
+            blob: undefined,
+          });
+
+          expect(result).toEqual(createEmptyStateResource(true));
+        });
+      });
+    });
+  });
+
   describe('upload file', () => {
     const dummyResource: Resource = createDummyResource();
     const dummyLinkRel: string = DummyLinkRel.DUMMY;
 
     const fileLocation: string = 'fileLocation';
-    const uploadFileResponse: HttpResponse<void> = <any>{
+    const uploadFileResponse: HttpResponse<Object> = <any>{
       response: { headers: { ['Location']: fileLocation } },
     };
 
diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.ts
index 8e051164991b0bb42bcf1b7c268f23d2307e0516..bb6592cb76931ff30edca949cc28a864686ecfce 100644
--- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.ts
+++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.ts
@@ -22,7 +22,9 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import {
+  BlobWithFileName,
   EMPTY_STRING,
+  HttpHeader,
   StateResource,
   createEmptyStateResource,
   createErrorStateResource,
@@ -58,7 +60,9 @@ export class BinaryFileService {
     showValidationErrorSnackBar: boolean = true,
   ): Observable<StateResource<BinaryFileResource>> {
     return this.repository.uploadFile(resource, linkRel, file).pipe(
-      mergeMap((response: HttpResponse<void>) => this.getFile(response.headers.get('Location'))),
+      mergeMap((response: HttpResponse<Object>) =>
+        this.getFile(response.headers.get(HttpHeader.LOCATION)),
+      ),
       catchError((errorResponse) =>
         this.handleError(errorResponse.error, showValidationErrorSnackBar),
       ),
@@ -115,13 +119,29 @@ export class BinaryFileService {
     return file.name;
   }
 
+  public downloadArchive(uri: ResourceUri): Observable<StateResource<Blob>> {
+    return this.repository.downloadArchive(uri).pipe(
+      map((data: BlobWithFileName) => this.saveData(data)),
+      startWith(createEmptyStateResource<Blob>(true)),
+    );
+  }
+
+  saveData(dataWithFileName: BlobWithFileName): StateResource<Blob> {
+    const data: Blob = dataWithFileName.blob;
+    if (isNil(data)) {
+      return createEmptyStateResource(true);
+    }
+    this.save(data, dataWithFileName.fileName);
+    return createStateResource(data);
+  }
+
   save(data: any, fileName: string): void {
     saveAs(data, fileName);
   }
 
   public getFile(uri: ResourceUri): Observable<StateResource<BinaryFileResource>> {
     return this.repository.getFile(uri).pipe(
-      map((fileList) => createStateResource(fileList)),
+      map((fileList: BinaryFileResource) => createStateResource(fileList)),
       startWith(createEmptyStateResource<BinaryFileResource>(true)),
     );
   }
@@ -131,7 +151,7 @@ export class BinaryFileService {
     linkRel: string,
   ): Observable<StateResource<BinaryFileListResource>> {
     return this.repository.getFiles(resource, linkRel).pipe(
-      map((fileList) => createStateResource(fileList)),
+      map((fileList: BinaryFileListResource) => createStateResource(fileList)),
       startWith(createEmptyStateResource<BinaryFileListResource>(true)),
     );
   }
diff --git a/alfa-client/libs/binary-file-shared/test/binary-file.ts b/alfa-client/libs/binary-file-shared/test/binary-file.ts
index 11ec8db5f9e7d0fea09215377ba9cb3911d93ea9..c776a49793353a3674e60ed40431df7392091509 100644
--- a/alfa-client/libs/binary-file-shared/test/binary-file.ts
+++ b/alfa-client/libs/binary-file-shared/test/binary-file.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { StateResource, createStateResource } from '@alfa-client/tech-shared';
+import { GetRequestOptions, StateResource, createStateResource } from '@alfa-client/tech-shared';
 import { faker } from '@faker-js/faker';
 import { BinaryFileListLinkRel } from 'libs/binary-file-shared/src/lib/binary-file.linkrel';
 import {
@@ -64,3 +64,11 @@ export function createLoadingBinaryFileStateResource(): StateResource<BinaryFile
 export function createLoadedBinaryFileResource(): StateResource<BinaryFileResource> {
   return createStateResource(createBinaryFileResource());
 }
+
+export function createBlob(): Blob {
+  return <Blob>{};
+}
+
+export function createGetRequestOptions(): GetRequestOptions {
+  return <GetRequestOptions>{};
+}
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html
index ccb6ff68ca977040b551bbccdae63a27b5122617..bdd7a27733a69d622edeb8e8abff53f5eb8c8d2b 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html
+++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html
@@ -1,5 +1,5 @@
-<ods-attachment-container>
+<ods-attachment-wrapper>
   <alfa-binary-file-list
     [binaryFileListStateResource]="binaryFileListStateResource$ | async"
   ></alfa-binary-file-list>
-</ods-attachment-container>
+</ods-attachment-wrapper>
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts
index 861fc464fac3928e8c5a25ff71fcd93031abfa13..1541adfb3f823192df4745d1534ab7ca2478df01 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts
@@ -11,7 +11,7 @@ import { of } from 'rxjs';
 import { BinaryFileListContainerComponent } from './binary-file-list-container.component';
 import { BinaryFileListComponent } from './binary-file-list/binary-file-list.component';
 
-import { AttachmentContainerComponent } from '@ods/system';
+import { AttachmentWrapperComponent } from '@ods/system';
 
 describe('BinaryFileListContainerComponent', () => {
   let component: BinaryFileListContainerComponent;
@@ -30,7 +30,7 @@ describe('BinaryFileListContainerComponent', () => {
       declarations: [
         BinaryFileListContainerComponent,
         MockComponent(BinaryFileListComponent),
-        MockComponent(AttachmentContainerComponent),
+        MockComponent(AttachmentWrapperComponent),
       ],
       providers: [
         {
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-uri-container/binary-file-uri-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-uri-container/binary-file-uri-container.component.html
index bd452e3e647ee15ed78a06b3e75374873c3f7b8d..156e5a66a1684b330e0a364a7e66a476244bf1cd 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file-uri-container/binary-file-uri-container.component.html
+++ b/alfa-client/libs/binary-file/src/lib/binary-file-uri-container/binary-file-uri-container.component.html
@@ -1,11 +1,10 @@
 <ng-container *ngIf="binaryFileStateResource$ | async as binaryFileStateResource">
-  <ods-attachment-container>
+  <ods-attachment-wrapper>
     <alfa-binary-file2-container
       *ngIf="binaryFileStateResource.resource as binaryFile"
       data-test-class="binary-file-container"
       [file]="binaryFile"
-      [isLoading]="binaryFileStateResource.loading"
       [deletable]="false"
     ></alfa-binary-file2-container>
-  </ods-attachment-container>
+  </ods-attachment-wrapper>
 </ng-container>
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-uri-container/binary-file-uri-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-uri-container/binary-file-uri-container.component.spec.ts
index 34d0358a03a8f651acba5a8335d860df4e8578c8..0080d68eb8b8c6ae8a425340e1422b5055e21fa6 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file-uri-container/binary-file-uri-container.component.spec.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file-uri-container/binary-file-uri-container.component.spec.ts
@@ -21,7 +21,7 @@ import { of } from 'rxjs';
 import { BinaryFile2ContainerComponent } from '../binary-file2-container/binary-file2-container.component';
 import { BinaryFileUriContainerComponent } from './binary-file-uri-container.component';
 
-import { AttachmentContainerComponent } from '@ods/system';
+import { AttachmentWrapperComponent } from '@ods/system';
 
 describe('BinaryFileUriContainerComponent', () => {
   let component: BinaryFileUriContainerComponent;
@@ -37,7 +37,7 @@ describe('BinaryFileUriContainerComponent', () => {
       declarations: [
         BinaryFileUriContainerComponent,
         MockComponent(BinaryFile2ContainerComponent),
-        MockComponent(AttachmentContainerComponent),
+        MockComponent(AttachmentWrapperComponent),
       ],
       providers: [
         {
@@ -97,13 +97,6 @@ describe('BinaryFileUriContainerComponent', () => {
       expect(binaryFileContainerComponent.file).toEqual(binaryFileStateResource.resource);
     });
 
-    it('should be called with isLoading', () => {
-      const binaryFileContainerComponent: BinaryFile2ContainerComponent =
-        getMockComponent<BinaryFile2ContainerComponent>(fixture, BinaryFile2ContainerComponent);
-
-      expect(binaryFileContainerComponent.isLoading).toBe(binaryFileStateResource.loading);
-    });
-
     it('should be called with deleteable', () => {
       const binaryFileContainerComponent: BinaryFile2ContainerComponent =
         getMockComponent<BinaryFile2ContainerComponent>(fixture, BinaryFile2ContainerComponent);
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file.module.ts b/alfa-client/libs/binary-file/src/lib/binary-file.module.ts
index b1f7c8e578217084c9419a892fa0edb503846c31..89f78362805623629dbb65e5e9963789da21a337 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file.module.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file.module.ts
@@ -25,9 +25,11 @@ import { TechSharedModule } from '@alfa-client/tech-shared';
 import { UiModule } from '@alfa-client/ui';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
+import { DownloadButtonComponent } from '@ods/component';
 import {
   AttachmentComponent,
-  AttachmentContainerComponent,
+  AttachmentHeaderComponent,
+  AttachmentWrapperComponent,
   CloseIconComponent,
   SpinnerIconComponent,
 } from '@ods/system';
@@ -39,6 +41,7 @@ import { BinaryFileListComponent } from './binary-file-list-container/binary-fil
 import { BinaryFileUriContainerComponent } from './binary-file-uri-container/binary-file-uri-container.component';
 import { BinaryFile2ContainerComponent } from './binary-file2-container/binary-file2-container.component';
 import { BinaryFile2Component } from './binary-file2-container/binary-file2/binary-file2.component';
+import { DownloadArchiveFileButtonContainerComponent } from './download-archive-file-button-container/download-archive-file-button-container.component';
 import { HorizontalBinaryFileListComponent } from './horizontal-binary-file-list/horizontal-binary-file-list.component';
 import { VerticalBinaryFileListComponent } from './vertical-binary-file-list/vertical-binary-file-list.component';
 
@@ -48,9 +51,11 @@ import { VerticalBinaryFileListComponent } from './vertical-binary-file-list/ver
     UiModule,
     TechSharedModule,
     AttachmentComponent,
-    AttachmentContainerComponent,
+    AttachmentHeaderComponent,
+    AttachmentWrapperComponent,
     SpinnerIconComponent,
     CloseIconComponent,
+    DownloadButtonComponent,
   ],
   declarations: [
     BinaryFileAttachmentContainerComponent,
@@ -63,6 +68,7 @@ import { VerticalBinaryFileListComponent } from './vertical-binary-file-list/ver
     BinaryFileUriContainerComponent,
     BinaryFileListContainerComponent,
     BinaryFileListComponent,
+    DownloadArchiveFileButtonContainerComponent,
   ],
   exports: [
     BinaryFileAttachmentContainerComponent,
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2-container.component.html
index f901ea0826e96e938dab2632af3d9d5c754531bb..41fe9ab51a28ec7cc893e0dfd418cbffb86075c5 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2-container.component.html
+++ b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2-container.component.html
@@ -3,7 +3,6 @@
   [file]="file"
   [stateResource]="fileStateResource$ | async"
   [deletable]="deletable"
-  [isLoading]="isLoading"
   [downloadToken]="downloadToken$ | async"
   (startDownload)="startDownload($event)"
   (startDelete)="startDelete.emit($event)"
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2-container.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2-container.component.ts
index 6461380c6ebe06fa80e8a242440f9acee33051fa..ad052ff94920bcd3eb6f1b974aeeba26b276f675 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2-container.component.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2-container.component.ts
@@ -12,7 +12,6 @@ export class BinaryFile2ContainerComponent {
   @Input() file: BinaryFileResource;
   @Input() downloadFileNamePrefix: string;
   @Input() deletable: boolean = false;
-  @Input() isLoading: boolean = false;
 
   @Output() startDelete: EventEmitter<BinaryFileResource> = new EventEmitter();
 
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.html b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.html
index cd64683430db122e9d8411e606f9f80be75d2028..48f6c28798060e009239a18af52f8c24c4944492 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.html
+++ b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.html
@@ -1,10 +1,12 @@
 <ods-attachment
   [caption]="file.name"
+  [loadingCaption]="file.name + ' wird geladen...'"
   [description]="file.size | fileSizePlain"
   [fileType]="getIconType(file.contentType)"
   (click)="downloadFile()"
   [attr.aria-label]="'Anhang: Dateiname: ' + file.name"
   [isLoading]="isLoading"
+  data-test-class="download-file-button"
 >
   <div close class="flex-shrink self-center">
     <button
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.ts
index 6118b4d86b30fae7b721cf1f34c44ca190bdc421..c22c2d1c4bc05dd546c8e8e95f990fa359b7a01f 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file2-container/binary-file2/binary-file2.component.ts
@@ -19,7 +19,6 @@ export class BinaryFile2Component {
   @Input() stateResource: StateResource<Resource>;
   @Input() deletable: boolean = false;
   @Input() downloadToken: ApiDownloadToken = <ApiDownloadToken>{};
-  @Input() isLoading: boolean = false;
 
   readonly fileLinkRel = BinaryFileLinkRel;
 
@@ -33,6 +32,10 @@ export class BinaryFile2Component {
     return this.getStateResource().loading;
   }
 
+  get isLoading(): boolean {
+    return this.getStateResource().loading;
+  }
+
   getStateResource(): StateResource<Resource> {
     return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource;
   }
diff --git a/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.html b/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..a649ed00b6baf0a460ce19e409ad2fc536ebeb24
--- /dev/null
+++ b/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.html
@@ -0,0 +1,5 @@
+<ods-download-button
+  [stateResource]="downloadArchiveInProgress$ | async"
+  data-test-class="download-archive"
+  (click)="downloadArchive()"
+/>
diff --git a/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6b711f3a245de614563b6d1914ea0dbd09a0a73b
--- /dev/null
+++ b/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.spec.ts
@@ -0,0 +1,49 @@
+import { BinaryFileService } from '@alfa-client/binary-file-shared';
+import { Mock, dispatchEventFromFixture, mock } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import faker from '@faker-js/faker';
+import { DownloadButtonComponent } from '@ods/component';
+import { getDataTestClassOf } from 'libs/tech-shared/test/data-test';
+import { MockComponent } from 'ng-mocks';
+import { DownloadArchiveFileButtonContainerComponent } from './download-archive-file-button-container.component';
+
+describe('DownloadArchiveFileButtonContainerComponent', () => {
+  let component: DownloadArchiveFileButtonContainerComponent;
+  let fixture: ComponentFixture<DownloadArchiveFileButtonContainerComponent>;
+
+  const downloadArchiveButton: string = getDataTestClassOf('download-archive');
+
+  const binaryFileService: Mock<BinaryFileService> = mock(BinaryFileService);
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [DownloadArchiveFileButtonContainerComponent],
+      imports: [MockComponent(DownloadButtonComponent)],
+      providers: [
+        {
+          provide: BinaryFileService,
+          useValue: binaryFileService,
+        },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(DownloadArchiveFileButtonContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('download attachments', () => {
+    const downloadUri: string = faker.internet.url();
+
+    it('should call service to download archive', () => {
+      component.downloadUri = downloadUri;
+      dispatchEventFromFixture(fixture, downloadArchiveButton, 'click');
+
+      expect(binaryFileService.downloadArchive).toHaveBeenCalledWith(downloadUri);
+    });
+  });
+});
diff --git a/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.ts b/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0c584eeb78164e120a18be156e24703c1c9f87ad
--- /dev/null
+++ b/alfa-client/libs/binary-file/src/lib/download-archive-file-button-container/download-archive-file-button-container.component.ts
@@ -0,0 +1,22 @@
+import { BinaryFileService } from '@alfa-client/binary-file-shared';
+import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { Component, Input } from '@angular/core';
+import { Observable, of } from 'rxjs';
+
+@Component({
+  selector: 'alfa-download-archive-file-button-container',
+  templateUrl: './download-archive-file-button-container.component.html',
+})
+export class DownloadArchiveFileButtonContainerComponent {
+  @Input() downloadUri: string;
+
+  public downloadArchiveInProgress$: Observable<StateResource<unknown>> = of(
+    createEmptyStateResource(),
+  );
+
+  constructor(private binaryFileService: BinaryFileService) {}
+
+  public downloadArchive(): void {
+    this.downloadArchiveInProgress$ = this.binaryFileService.downloadArchive(this.downloadUri);
+  }
+}
diff --git a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.html b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.html
index fbea31c02eff3f5d30abd9cf1c1ff7a73447f716..187ab55187039b6ca7ea2f9d6b1ab8e0cc456a4a 100644
--- a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.html
+++ b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.html
@@ -23,17 +23,31 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-spinner [stateResource]="fileListResource">
-  <div class="vertical" data-test-id="file-list">
-    <alfa-binary-file-container
+<ozgcloud-spinner
+  *ngIf="binaryFileListStateResource.resource"
+  [stateResource]="binaryFileListStateResource"
+>
+  <ods-attachment-wrapper [title]="title" data-test-id="file-list">
+    <ods-attachment-header [title]="title">
+      <alfa-download-archive-file-button-container
+        *ngIf="archiveDownloadUri"
+        data-test-class="download-archive-file-button"
+        [downloadUri]="archiveDownloadUri"
+        action-buttons
+      ></alfa-download-archive-file-button-container
+    ></ods-attachment-header>
+    <ng-container
       *ngFor="
-        let binaryFileResource of fileListResource.resource
+        let binaryFileResource of binaryFileListStateResource.resource
           | toEmbeddedResources: fileListRel.FILE_LIST
       "
-      [file]="binaryFileResource"
-      [deletable]="deletable"
-      [downloadFileNamePrefix]="downloadFileNamePrefix"
     >
-    </alfa-binary-file-container>
-  </div>
+      <alfa-binary-file2-container
+        [file]="binaryFileResource"
+        [deletable]="deletable"
+        [downloadFileNamePrefix]="downloadFileNamePrefix"
+      >
+      </alfa-binary-file2-container>
+    </ng-container>
+  </ods-attachment-wrapper>
 </ozgcloud-spinner>
diff --git a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.scss b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.scss
deleted file mode 100644
index 1212c1617eca6dd57a7d70ae7069d282a3611ea7..0000000000000000000000000000000000000000
--- a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-.vertical {
-  display: flex;
-  flex-direction: column;
-  max-width: 100%;
-  align-items: flex-start;
-  margin: 0 -4px;
-  margin-top: 1rem;
-}
diff --git a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.spec.ts b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.spec.ts
index 07c0a783352ebfa2a91827c1216b71ca1736baae..a42980975bd6362343a865a3dae296bbd3191728 100644
--- a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.spec.ts
+++ b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.spec.ts
@@ -21,24 +21,46 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { createEmptyStateResource, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared';
+import { BinaryFileResource } from '@alfa-client/binary-file-shared';
+import { ToEmbeddedResourcesPipe, createStateResource } from '@alfa-client/tech-shared';
+import {
+  existsAsHtmlElement,
+  getMockComponent,
+  notExistsAsHtmlElement,
+} from '@alfa-client/test-utils';
 import { SpinnerComponent } from '@alfa-client/ui';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import faker from '@faker-js/faker';
+import { ResourceUri } from '@ngxp/rest';
+import { AttachmentHeaderComponent, AttachmentWrapperComponent } from '@ods/system';
+import {
+  createBinaryFileListResource,
+  createBinaryFileResource,
+} from 'libs/binary-file-shared/test/binary-file';
+import { getDataTestClassOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
-import { BinaryFileContainerComponent } from './../binary-file-container/binary-file-container.component';
+import { BinaryFile2ContainerComponent } from '../binary-file2-container/binary-file2-container.component';
+import { DownloadArchiveFileButtonContainerComponent } from '../download-archive-file-button-container/download-archive-file-button-container.component';
 import { VerticalBinaryFileListComponent } from './vertical-binary-file-list.component';
 
 describe('VerticalBinaryFileListComponent', () => {
   let component: VerticalBinaryFileListComponent;
   let fixture: ComponentFixture<VerticalBinaryFileListComponent>;
 
+  const downloadArchiveFileButton: string = getDataTestClassOf('download-archive-file-button');
+
+  const binaryFile: BinaryFileResource = createBinaryFileResource();
+
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [
         VerticalBinaryFileListComponent,
         ToEmbeddedResourcesPipe,
-        MockComponent(BinaryFileContainerComponent),
+        MockComponent(AttachmentWrapperComponent),
+        MockComponent(AttachmentHeaderComponent),
+        MockComponent(BinaryFile2ContainerComponent),
         MockComponent(SpinnerComponent),
+        MockComponent(DownloadArchiveFileButtonContainerComponent),
       ],
     }).compileComponents();
   });
@@ -46,11 +68,80 @@ describe('VerticalBinaryFileListComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(VerticalBinaryFileListComponent);
     component = fixture.componentInstance;
-    component.fileListResource = createEmptyStateResource();
+    component.binaryFileListStateResource = createStateResource(
+      createBinaryFileListResource([binaryFile]),
+    );
     fixture.detectChanges();
   });
 
   it('should create', () => {
     expect(component).toBeTruthy();
   });
+
+  describe('binary file component', () => {
+    describe('should be called with', () => {
+      it('file', () => {
+        const comp: BinaryFile2ContainerComponent = getMockComponent(
+          fixture,
+          BinaryFile2ContainerComponent,
+        );
+
+        expect(comp.file).toBe(binaryFile);
+      });
+
+      it('deletable', () => {
+        const comp: BinaryFile2ContainerComponent = getMockComponent(
+          fixture,
+          BinaryFile2ContainerComponent,
+        );
+
+        expect(comp.deletable).toBe(component.deletable);
+      });
+
+      it('downloadFileNamePrefix', () => {
+        const comp: BinaryFile2ContainerComponent = getMockComponent(
+          fixture,
+          BinaryFile2ContainerComponent,
+        );
+
+        expect(comp.downloadFileNamePrefix).toBe(component.downloadFileNamePrefix);
+      });
+    });
+  });
+
+  describe('download archive button', () => {
+    const downloadUri: ResourceUri = faker.internet.url();
+
+    it('should be visible if uri exists', () => {
+      component.archiveDownloadUri = downloadUri;
+
+      fixture.detectChanges();
+
+      existsAsHtmlElement(fixture, downloadArchiveFileButton);
+    });
+
+    it('should be hidden if uri is undefined', () => {
+      component.archiveDownloadUri = undefined;
+
+      fixture.detectChanges();
+
+      notExistsAsHtmlElement(fixture, downloadArchiveFileButton);
+    });
+
+    describe('component should be called with', () => {
+      beforeEach(() => {
+        component.archiveDownloadUri = downloadUri;
+        fixture.detectChanges();
+      });
+
+      it('downloadUri', () => {
+        const comp: DownloadArchiveFileButtonContainerComponent = getMockComponent(
+          fixture,
+          DownloadArchiveFileButtonContainerComponent,
+        );
+
+        expect(comp.downloadUri).toBe(downloadUri);
+      });
+    });
+  });
 });
diff --git a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.ts b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.ts
index 3eb9096547a466caf4ac3b11ee935f728bee1745..363dc54b3bfb8ff2dc7f7bd5e00570afe9fe5565 100644
--- a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.ts
+++ b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.ts
@@ -21,20 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { BinaryFileListLinkRel, BinaryFileListResource } from '@alfa-client/binary-file-shared';
-import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { Component, Input } from '@angular/core';
+import { ResourceUri } from '@ngxp/rest';
 
 @Component({
   selector: 'alfa-vertical-binary-file-list',
   templateUrl: './vertical-binary-file-list.component.html',
-  styleUrls: ['./vertical-binary-file-list.component.scss'],
 })
 export class VerticalBinaryFileListComponent {
-  @Input() fileListResource: StateResource<BinaryFileListResource> =
+  @Input() binaryFileListStateResource: StateResource<BinaryFileListResource> =
     createEmptyStateResource<BinaryFileListResource>();
   @Input() downloadFileNamePrefix: string;
+  @Input() title: string = '';
   @Input() deletable: boolean = false;
+  @Input() archiveDownloadUri: ResourceUri;
 
   readonly fileListRel = BinaryFileListLinkRel;
 }
diff --git a/alfa-client/libs/design-component/src/index.ts b/alfa-client/libs/design-component/src/index.ts
index 8670320bc61acad5f807315ea595229b26da068d..0ed0ab64368e0b3716f3ed6b1ab8d7da0a6fc2d7 100644
--- a/alfa-client/libs/design-component/src/index.ts
+++ b/alfa-client/libs/design-component/src/index.ts
@@ -1,5 +1,7 @@
 export * from './lib/button-with-spinner/button-with-spinner.component';
+export * from './lib/download-button/download-button.component';
 export * from './lib/form/file-upload-editor/file-upload-editor.component';
+export * from './lib/form/formcontrol-editor.abstract.component';
 export * from './lib/form/single-file-upload-editor/single-file-upload-editor.component';
 export * from './lib/form/text-editor/text-editor.component';
 export * from './lib/form/textarea-editor/textarea-editor.component';
diff --git a/alfa-client/libs/design-component/src/lib/download-button/download-button.component.spec.ts b/alfa-client/libs/design-component/src/lib/download-button/download-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3b5b17755eea019979b1ec405107272c3f43b692
--- /dev/null
+++ b/alfa-client/libs/design-component/src/lib/download-button/download-button.component.spec.ts
@@ -0,0 +1,48 @@
+import { createEmptyStateResource } from '@alfa-client/tech-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { DownloadButtonComponent } from './download-button.component';
+
+describe('DownloadButtonComponent', () => {
+  let component: DownloadButtonComponent;
+  let fixture: ComponentFixture<DownloadButtonComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DownloadButtonComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(DownloadButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('isLoading', () => {
+    it('should return false', () => {
+      component.stateResource = createEmptyStateResource();
+
+      const isLoading: boolean = component.isLoading;
+
+      expect(isLoading).toBeFalsy();
+    });
+
+    it('should return true if stateResource is loading', () => {
+      component.stateResource = createEmptyStateResource(true);
+
+      const isLoading: boolean = component.isLoading;
+
+      expect(isLoading).toBeTruthy();
+    });
+
+    it('should return true if stateResource is reloading', () => {
+      component.stateResource = { ...createEmptyStateResource(), reload: true };
+
+      const isLoading: boolean = component.isLoading;
+
+      expect(isLoading).toBeTruthy();
+    });
+  });
+});
diff --git a/alfa-client/libs/design-component/src/lib/download-button/download-button.component.ts b/alfa-client/libs/design-component/src/lib/download-button/download-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dd69b20129739ad87ed4cd40744a858355b3fefc
--- /dev/null
+++ b/alfa-client/libs/design-component/src/lib/download-button/download-button.component.ts
@@ -0,0 +1,35 @@
+import { CommandResource } from '@alfa-client/command-shared';
+import { StateResource } from '@alfa-client/tech-shared';
+import { CommonModule } from '@angular/common';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { ButtonComponent, SaveIconComponent, iconVariants } from '@ods/system';
+import { VariantProps } from 'class-variance-authority';
+
+type IconVariants = VariantProps<typeof iconVariants>;
+
+@Component({
+  selector: 'ods-download-button',
+  standalone: true,
+  imports: [CommonModule, ButtonComponent, SaveIconComponent],
+  template: `<ods-button
+    [dataTestId]="dataTestId"
+    variant="icon"
+    size="fit"
+    spinnerSize="small"
+    [isLoading]="isLoading"
+    (click)="clickEmitter.emit()"
+  >
+    <ods-save-icon icon [size]="size" class="fill-text"></ods-save-icon>
+  </ods-button>`,
+})
+export class DownloadButtonComponent {
+  @Input() dataTestId: string = '';
+  @Input() size: IconVariants['size'] = 'small';
+  @Input() set stateResource(resource: StateResource<CommandResource>) {
+    this.isLoading = resource.loading || resource.reload;
+  }
+
+  @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
+
+  isLoading: boolean = false;
+}
diff --git a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.spec.ts b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.spec.ts
index 64341eff5a4cbcfc8a9b5730559f23e1acfe440b..bcd618c337bd126c861a20360a9ac56633bfa0ec 100644
--- a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.spec.ts
+++ b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.spec.ts
@@ -32,7 +32,6 @@ import {
 } from '@angular/forms';
 import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
-import { ValidationErrorComponent } from 'libs/ui/src/lib/ui/validation-error/validation-error.component';
 import { MockComponent } from 'ng-mocks';
 import { FileUploadEditorComponent } from './file-upload-editor.component';
 
@@ -51,7 +50,6 @@ describe('FileUploadEditorComponent', () => {
     await TestBed.configureTestingModule({
       declarations: [
         FileUploadEditorComponent,
-        MockComponent(ValidationErrorComponent),
         MockComponent(SpinnerIconComponent),
         MockComponent(FileUploadButtonComponent),
       ],
diff --git a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.ts
index d6e927851b53ccb0b3048b0f7562d10af3a75275..3c7992f6f52d3525ad32f74fd4282442d44dd1a8 100644
--- a/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/file-upload-editor/file-upload-editor.component.ts
@@ -1,5 +1,4 @@
 import { StateResource, TechSharedModule } from '@alfa-client/tech-shared';
-import { FormControlEditorAbstractComponent } from '@alfa-client/ui';
 import { NgForOf } from '@angular/common';
 import { Component, EventEmitter, HostListener, Input, OnInit, Output } from '@angular/core';
 import {
@@ -16,6 +15,7 @@ import {
   SpinnerIconComponent,
 } from '@ods/system';
 import { uniqueId } from 'lodash-es';
+import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 
 @Component({
   selector: 'ods-file-upload-editor',
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component.ts b/alfa-client/libs/design-component/src/lib/form/formcontrol-editor.abstract.component.ts
similarity index 91%
rename from alfa-client/libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component.ts
rename to alfa-client/libs/design-component/src/lib/form/formcontrol-editor.abstract.component.ts
index f0270e9c2fea92811bc6b8a1f3c0b2d115c3c240..a023a009d1780be33395159d25234da39285f745 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/formcontrol-editor.abstract.component.ts
@@ -21,16 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Optional, Self } from '@angular/core';
-import { ControlValueAccessor, UntypedFormControl, NgControl } from '@angular/forms';
 import { Issue } from '@alfa-client/tech-shared';
+import { Component, OnDestroy, OnInit, Optional, Self } from '@angular/core';
+import { ControlValueAccessor, NgControl, UntypedFormControl } from '@angular/forms';
 import { isEmpty } from 'lodash-es';
 import { Subscription } from 'rxjs';
 
 @Component({
   template: 'NO UI',
 })
-export abstract class FormControlEditorAbstractComponent implements ControlValueAccessor {
+export abstract class FormControlEditorAbstractComponent
+  implements ControlValueAccessor, OnInit, OnDestroy
+{
   readonly fieldControl: UntypedFormControl = new UntypedFormControl();
   public onChange = (text: string | Date) => undefined;
   public onTouched = () => undefined;
diff --git a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.spec.ts b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.spec.ts
index 2a7ee6d4fc46926081e1aedbb5bf086f9fc63883..4d44ce0dcbb1165a9ddb6bad46a1537fee601d6d 100644
--- a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.spec.ts
+++ b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.spec.ts
@@ -3,7 +3,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ReactiveFormsModule } from '@angular/forms';
 import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
-import { ValidationErrorComponent } from 'libs/ui/src/lib/ui/validation-error/validation-error.component';
 import { MockComponent } from 'ng-mocks';
 import { SingleFileUploadEditorComponent } from './single-file-upload-editor.component';
 
@@ -18,7 +17,6 @@ describe('SingleFileUploadEditorComponent', () => {
       declarations: [
         SingleFileUploadEditorComponent,
         FileUploadButtonComponent,
-        MockComponent(ValidationErrorComponent),
         MockComponent(SpinnerIconComponent),
       ],
       imports: [ReactiveFormsModule],
diff --git a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
index 36db826a36c473a9012eafc2d3470ce05af011e8..8da41fe6bb90f102b7bad62c44fd230f0eb094c7 100644
--- a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
@@ -1,20 +1,15 @@
 import { TechSharedModule, isNotNil } from '@alfa-client/tech-shared';
-import { FormControlEditorAbstractComponent } from '@alfa-client/ui';
 import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
 import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
 import { uniqueId } from 'lodash-es';
+import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 
 @Component({
   selector: 'ods-single-file-upload-editor',
   templateUrl: './single-file-upload-editor.component.html',
   standalone: true,
-  imports: [
-    FileUploadButtonComponent,
-    SpinnerIconComponent,
-    ReactiveFormsModule,
-    TechSharedModule,
-  ],
+  imports: [FileUploadButtonComponent, SpinnerIconComponent, ReactiveFormsModule, TechSharedModule],
 })
 export class SingleFileUploadEditorComponent extends FormControlEditorAbstractComponent {
   @Input() label: string = '';
diff --git a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html
index bd8034d8366f83cf4ddbee1e54c271fb932f2c9a..544b9312b03adba3e0e097e8eba8a20751e5b013 100644
--- a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html
+++ b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html
@@ -5,7 +5,7 @@
   [autocomplete]="autocomplete"
   [variant]="variant"
   [attr.data-test-id]="(label | convertForDataTest) + '-text-editor'"
-  [required]="required"
+  [required]="isRequired"
   [focus]="focus"
 >
   <ods-validation-error
diff --git a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
index a1881546fe7309af8c1992f7c17645fe3e692ad4..c78a7554800ed6f61eb9d189617811e7f9d0490a 100644
--- a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts
@@ -1,9 +1,9 @@
 import { TechSharedModule } from '@alfa-client/tech-shared';
-import { FormControlEditorAbstractComponent } from '@alfa-client/ui';
 import { CommonModule } from '@angular/common';
-import { Component, Input, OnInit } from '@angular/core';
+import { Component, Input } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
 import { TextInputComponent } from '@ods/system';
+import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 import { ValidationErrorComponent } from '../validation-error/validation-error.component';
 
 @Component({
@@ -18,11 +18,11 @@ import { ValidationErrorComponent } from '../validation-error/validation-error.c
   ],
   templateUrl: './text-editor.component.html',
 })
-export class TextEditorComponent extends FormControlEditorAbstractComponent implements OnInit {
+export class TextEditorComponent extends FormControlEditorAbstractComponent {
   @Input({ required: true }) label: string;
   @Input() autocomplete: 'off' | 'email' = 'off';
   @Input() placeholder: string = '';
-  @Input() required: boolean = false;
+  @Input() isRequired: boolean = false;
   @Input() focus: boolean = false;
 
   get variant(): string {
diff --git a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html
index 73ea744d07206658aafb6af0e95533b8d106960b..5f3959bd34260ac44c11db6a108f24583986b9b0 100644
--- a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html
+++ b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html
@@ -5,7 +5,7 @@
   [rows]="rows"
   [variant]="variant"
   [attr.data-test-id]="(label | convertForDataTest) + '-textarea-editor'"
-  [required]="required"
+  [required]="isRequired"
   [focus]="focus"
 >
   <ods-validation-error
diff --git a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
index 1514871a5a9e0d6032e96fd0b85cd3064726ff13..f78ee2c938fdb89b91a17060ba862ecadcff04aa 100644
--- a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts
@@ -1,9 +1,9 @@
 import { TechSharedModule } from '@alfa-client/tech-shared';
-import { FormControlEditorAbstractComponent } from '@alfa-client/ui';
 import { CommonModule } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
 import { TextareaComponent } from '@ods/system';
+import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 import { ValidationErrorComponent } from '../validation-error/validation-error.component';
 
 @Component({
@@ -20,9 +20,9 @@ import { ValidationErrorComponent } from '../validation-error/validation-error.c
 })
 export class TextareaEditorComponent extends FormControlEditorAbstractComponent {
   @Input({ required: true }) label: string;
-  @Input() placeholder: string;
+  @Input() placeholder: string = '';
   @Input() rows: number = 10;
-  @Input() required: boolean = false;
+  @Input() isRequired: boolean = false;
   @Input() focus: boolean = false;
 
   get variant(): string {
diff --git a/alfa-client/libs/design-system/Dockerfile b/alfa-client/libs/design-system/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..db2112bd5fa7878771e6c2a1fac73bd58feb4e09
--- /dev/null
+++ b/alfa-client/libs/design-system/Dockerfile
@@ -0,0 +1,5 @@
+FROM nginxinc/nginx-unprivileged:stable-alpine
+
+
+COPY dist/storybook /usr/share/nginx/html/
+COPY libs/design-system/nginx.conf /etc/nginx/nginx.conf
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/main/helm/Chart.yaml b/alfa-client/libs/design-system/main/helm/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fcdc7922e7386ee8ab01671dd283b5df3778f037
--- /dev/null
+++ b/alfa-client/libs/design-system/main/helm/Chart.yaml
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+appVersion: '1.0'
+description: A Helm chart for storybook
+name: storybook
+version: 0.0.0-MANAGED-BY-JENKINS
+icon: https://simpleicons.org/icons/helm.svg
diff --git a/alfa-client/libs/design-system/main/helm/templates/_helpers.tpl b/alfa-client/libs/design-system/main/helm/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..08da97368b065f836fbcc316b69c38c77e7a47a9
--- /dev/null
+++ b/alfa-client/libs/design-system/main/helm/templates/_helpers.tpl
@@ -0,0 +1,81 @@
+
+{{/* error check 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec) */}}
+{{/* Namespace */}}
+{{- define "app.namespace" -}}
+{{- if gt (len (.Release.Namespace)) 63 -}}
+{{- fail (printf ".Release.Namespace %s ist zu lang (max. 63 Zeichen)" .Release.Namespace) -}}
+{{- end -}}
+{{ printf "%s" .Release.Namespace }}
+{{- end -}}
+
+{{/* Chart: Name + Version */}}
+{{- define "app.chart" -}}
+{{- if gt (len (printf "%s-%s" .Chart.Name .Chart.Version)) 63 -}}
+{{- fail (printf ".Chart.Name-.Chart.Version %s-%s ist zu lang (max. 63 Zeichen)" .Chart.Name .Chart.Version) -}}
+{{- end -}}
+{{ printf "%s-%s" .Chart.Name .Chart.Version }}
+{{- end -}}
+
+{{/* Managed-by -> On Helm, this value is always Helm */}}
+{{- define "app.managedBy" -}}
+{{- if gt (len (.Release.Service)) 63 -}}
+{{- fail (printf ".Release.Service %s ist zu lang (max. 63 Zeichen)" .Release.Service) -}}
+{{- end -}}
+{{ printf "%s" .Release.Service }}
+{{- end -}}
+
+
+{{/* Default Labels: Helm recommended best-practice labels https://helm.sh/docs/chart_best_practices/labels/ */}}
+{{- define "app.defaultLabels" }}
+app.kubernetes.io/instance: storybook
+app.kubernetes.io/managed-by: {{ include "app.managedBy" . }}
+app.kubernetes.io/name: {{ .Release.Name }}
+app.kubernetes.io/namespace: {{ include "app.namespace" . }}
+app.kubernetes.io/part-of: ozgcloud
+app.kubernetes.io/version: {{ .Chart.Version }}
+helm.sh/chart: {{ include "app.chart" . }}
+{{- end -}}
+
+{{- define "app.matchLabels" }}
+app.kubernetes.io/name: {{ .Release.Name }}
+app.kubernetes.io/namespace: {{ include "app.namespace" . }}
+{{- end -}}
+
+
+{{- define "app.serviceAccountName" -}}
+{{ printf "%s" ( (.Values.serviceAccount).name | default "storybook-service-account" ) }}
+{{- end -}}
+
+
+{{- define "app.baseDomain" -}}
+{{- printf "%s.%s" (include "app.ozgcloudBezeichner" . ) (include "app.baseUrl" . ) }}
+{{- end -}}
+
+{{- define "app.ozgcloudBezeichner" -}}
+{{- required "ozgcloud.bezeichner muss angegeben sein" (.Values.ozgcloud).bezeichner -}}
+{{- if lt 46 (len (.Values.ozgcloud).bezeichner) -}}
+{{ fail (printf "ozgcloud.bezeichner %s ist zu lang (max. 46 Zeichen)" (.Values.ozgcloud).bezeichner) }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.baseUrl" -}}
+{{- required "baseUrl muss angegeben sein" .Values.baseUrl }}
+{{- end -}}
+
+{{- define "app.getCustomList" -}}
+{{- with (.Values.env).customList -}}
+{{- if kindIs "map" . -}}
+{{ include "app.dictToList" . }}
+{{- else if kindIs "slice" . -}}
+{{ . | toYaml }}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.dictToList" -}}
+{{- $customList := list -}}
+{{- range $key, $value := . -}}
+{{- $customList = append $customList (dict "name" $key "value" $value) }}
+{{- end -}}
+{{- $customList | toYaml -}}
+{{- end -}}
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/main/helm/templates/deployment.yaml b/alfa-client/libs/design-system/main/helm/templates/deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7daf47c5c1e9f110de1a378b984698d9130c3c69
--- /dev/null
+++ b/alfa-client/libs/design-system/main/helm/templates/deployment.yaml
@@ -0,0 +1,122 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ .Release.Name }}
+  namespace: {{ include "app.namespace" . }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+spec:
+  progressDeadlineSeconds: 600
+  replicas: {{ .Values.replicaCount }}
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      {{- include "app.matchLabels" . | indent 6 }}
+  strategy:
+    rollingUpdate:
+      maxSurge: 1
+      maxUnavailable: 0
+    type: RollingUpdate
+  template:
+    metadata:
+      labels:
+        {{- include "app.defaultLabels" . | indent 8 }}
+        component: storybook
+    spec:
+      {{- if (.Values.serviceAccount).create }}
+      serviceAccountName: {{ include "app.serviceAccountName" . }}
+      {{- end }}
+      topologySpreadConstraints:
+      - maxSkew: 1
+        topologyKey: kubernetes.io/hostname
+        whenUnsatisfiable: ScheduleAnyway
+        labelSelector:
+          matchLabels:
+            app.kubernetes.io/name: {{ .Release.Name }}
+      
+      containers:
+      - env:        
+        {{- with include "app.getCustomList" . }}
+{{ . | indent 8 }}
+        {{- end }}
+
+        image: "{{ .Values.image.repo }}/{{ .Values.image.name }}:{{ coalesce (.Values.image).tag "latest" }}"
+        imagePullPolicy: Always
+        name: storybook
+
+        startupProbe:
+          httpGet:
+            path: /
+            port: 8080
+            scheme: HTTP
+          timeoutSeconds: 3
+          periodSeconds: 10
+          successThreshold: 1
+          failureThreshold: 3
+        readinessProbe:
+          httpGet:
+            path: /
+            port: 8080
+            scheme: HTTP
+          timeoutSeconds: 3
+          periodSeconds: 10
+          successThreshold: 1
+          failureThreshold: 3
+
+        resources:
+        {{- with .Values.resources }}
+{{ toYaml . | indent 10 }}
+        {{- end }}
+        securityContext:
+          allowPrivilegeEscalation: false
+          privileged: false
+          readOnlyRootFilesystem: false
+          runAsNonRoot: true
+          {{- with (.Values.securityContext).runAsUser }}
+          runAsUser: {{ . }}
+          {{- end }}
+          {{- with (.Values.securityContext).runAsGroup }}
+          runAsGroup: {{ . }}
+          {{- end }}
+        stdin: true
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+        tty: true
+        
+        
+      dnsConfig: {}
+      dnsPolicy: ClusterFirst
+      imagePullSecrets:
+      - name: {{ required "imagePullSecret must be set" .Values.imagePullSecret }}
+      restartPolicy: Always
+      {{- with .Values.hostAliases }}
+      hostAliases:
+{{ toYaml . | indent 8 }}
+      {{- end }}
+      schedulerName: default-scheduler
+      securityContext: {}
+      terminationGracePeriodSeconds: 30
diff --git a/alfa-client/libs/design-system/main/helm/templates/ingress.yaml b/alfa-client/libs/design-system/main/helm/templates/ingress.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..05882a4bd3278a2170632c8e70319e2011b1823f
--- /dev/null
+++ b/alfa-client/libs/design-system/main/helm/templates/ingress.yaml
@@ -0,0 +1,39 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: {{ .Release.Name }}
+  namespace: {{ include "app.namespace" . }}
+  annotations:
+    {{- if (.Values.ingress).certManagerAnnotations -}}
+    {{- range (.Values.ingress).certManagerAnnotations }}
+{{ . | indent 4 }}
+    {{- end }}
+    {{- else if (.Values.ingress).use_staging_cert }}
+    cert-manager.io/cluster-issuer: letsencrypt-staging
+    {{- else }}
+    cert-manager.io/cluster-issuer: letsencrypt-prod
+    {{- end }}
+spec:
+  {{- if and (.Values.ingress).className (ne (.Values).cluster_env "dataport") }}
+  ingressClassName: {{ .Values.ingress.className }}
+  {{- end }}
+  rules:
+    - http:
+        paths:
+          - path: /
+            pathType: Prefix
+            backend:
+              service:
+                name: storybook
+                port: 
+                  number: 8080
+
+      host: {{ include "app.baseDomain" . }}
+  tls:
+    - hosts:
+      - {{ include "app.baseDomain" . }}
+      {{- if (.Values.ingress).tlsSecretName }}
+      secretName: {{ (.Values.ingress).tlsSecretName }}
+      {{- else if ne (.Values).cluster_env "dataport" }}
+      secretName: {{ .Values.ozgcloud.bezeichner }}-{{ .Release.Name }}-tls
+      {{- end }}
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/main/helm/templates/network_policy.yaml b/alfa-client/libs/design-system/main/helm/templates/network_policy.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9e281036f63a8e3bdaeb45223007d484a80af2c3
--- /dev/null
+++ b/alfa-client/libs/design-system/main/helm/templates/network_policy.yaml
@@ -0,0 +1,44 @@
+{{- if not (.Values.networkPolicy).disabled }}
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+  name: network-policy-storybook
+  namespace: {{ .Release.Namespace }}
+spec:
+  podSelector:
+    matchLabels:
+      {{- include "app.matchLabels" . | indent 6 }}
+  policyTypes:
+    - Ingress
+    - Egress
+  ingress:
+  - ports:
+    - port: 8080
+{{- with (.Values.networkPolicy).additionalIngressConfigLocal }}
+{{ toYaml . | indent 2 }}
+{{- end }}
+{{- with (.Values.networkPolicy).additionalIngressConfigGlobal }}
+{{ toYaml . | indent 2 }}
+{{- end }}
+  egress:
+  - to:
+    - namespaceSelector:
+        matchLabels:
+          kubernetes.io/metadata.name: {{ required "networkPolicy.dnsServerNamespace must be set" (.Values.networkPolicy).dnsServerNamespace }}
+    ports:
+      - port: 53
+        protocol: UDP
+      - port: 53
+        protocol: TCP
+      - port: 5353
+        protocol: UDP
+      - port: 5353
+        protocol: TCP
+{{- with (.Values.networkPolicy).additionalEgressConfigLocal }}
+{{ toYaml . | indent 2 }}
+{{- end }}
+{{- with (.Values.networkPolicy).additionalEgressConfigGlobal }}
+{{ toYaml . | indent 2 }}
+{{- end }}
+
+{{- end }}
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/main/helm/templates/service.yaml b/alfa-client/libs/design-system/main/helm/templates/service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a4a152fab1b685e2df235e8b067db58d5c5a995d
--- /dev/null
+++ b/alfa-client/libs/design-system/main/helm/templates/service.yaml
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ .Release.Name }}
+  namespace: {{ include "app.namespace" . }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+    component: storybook-service
+spec:
+  type: ClusterIP
+  ports:
+    - name: http
+      port: 8080
+      protocol: TCP
+      targetPort: 8080
+
+  selector:
+    {{- include "app.matchLabels" . | indent 4 }}
+    component: storybook
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/main/helm/values.yaml b/alfa-client/libs/design-system/main/helm/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..68df0d24e6ecee39af5ae05d521a2f89dec67f22
--- /dev/null
+++ b/alfa-client/libs/design-system/main/helm/values.yaml
@@ -0,0 +1,6 @@
+image:
+  repo: docker.ozg-sh.de
+  name: storybook
+  tag: 0.1.0 # [default: latest]
+replicaCount: 1
+
diff --git a/alfa-client/libs/design-system/nginx.conf b/alfa-client/libs/design-system/nginx.conf
new file mode 100644
index 0000000000000000000000000000000000000000..add779e6030ab68ebb8f5dde211d26f25e69a2e4
--- /dev/null
+++ b/alfa-client/libs/design-system/nginx.conf
@@ -0,0 +1,58 @@
+# Verarbeitungsreihenfolge von location rules:
+# --------------------------------------------------------------------------------------------------------------------------------------------
+# Search-Order       Modifier       Description                                                        Match-Type        Stops-search-on-match
+# --------------------------------------------------------------------------------------------------------------------------------------------
+#     1st               =           The URI must match the specified pattern exactly                  Simple-string              Yes
+#     2nd               ^~          The URI must begin with the specified pattern                     Simple-string              Yes
+#     3rd             (None)        The URI must begin with the specified pattern                     Simple-string               No
+#     4th               ~           The URI must be a case-sensitive match to the specified Rx      Perl-Compatible-Rx      Yes (first match)
+#     4th               ~*          The URI must be a case-insensitive match to the specified Rx    Perl-Compatible-Rx      Yes (first match)
+#     N/A               @           Defines a named location block.                                   Simple-string              Yes
+# --------------------------------------------------------------------------------------------------------------------------------------------
+#
+# Regex Matches werden bevorzugt verwendet.
+# Mehr: https://stackoverflow.com/a/59846239/1546181
+pid /tmp/nginx.pid;
+worker_processes  1;
+
+events {
+    worker_connections  1024;
+}
+
+http {
+    include       mime.types;
+    server_tokens off;
+    access_log off;
+    error_log stderr crit;
+
+    server {
+        listen 8080;
+        server_name localhost;
+
+       
+
+        location / {
+            root   /usr/share/nginx/html/design-system;
+            index  index.html index.htm;
+        }
+        
+
+
+        client_body_temp_path /tmp/client_temp;
+        proxy_temp_path       /tmp/proxy_temp_path;
+        fastcgi_temp_path     /tmp/fastcgi_temp;
+        uwsgi_temp_path       /tmp/uwsgi_temp;
+        scgi_temp_path        /tmp/scgi_temp;
+
+        gzip on;
+        gzip_min_length 1000;
+        gzip_proxied expired no-cache no-store private auth;
+        gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
+    
+
+        error_page   500 502 503 504  /50x.html;
+        location = /50x.html {
+            root html;
+        }
+    }
+}
diff --git a/alfa-client/libs/design-system/project.json b/alfa-client/libs/design-system/project.json
index bcec7a688f84eefe1731c08cc4fa56e21e415975..bc681e80f5d762322adf47a62dba25464c0a7a0d 100644
--- a/alfa-client/libs/design-system/project.json
+++ b/alfa-client/libs/design-system/project.json
@@ -48,6 +48,21 @@
           "quiet": true
         }
       }
+    },
+    "container": {
+      "executor": "@nx-tools/nx-container:build",
+      "dependsOn": ["build"],
+      "options": {
+        "engine": "docker",
+        "push": false,
+        "metadata": {
+          "images": ["docker.ozg-sh.de/storybook"],
+          "load": true,
+          "tags": [
+            "build-latest"
+          ]
+        }
+      }
     }
   }
 }
diff --git a/alfa-client/libs/design-system/run_helm_test.sh b/alfa-client/libs/design-system/run_helm_test.sh
new file mode 100755
index 0000000000000000000000000000000000000000..03f7485f84e6da1fd27bb3e24303172c4a09111c
--- /dev/null
+++ b/alfa-client/libs/design-system/run_helm_test.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -e
+set -x
+
+helm template  ./main/helm/ -f ./test/helm-linter-values.yaml 
+helm lint -f test/helm-linter-values.yaml ./main/helm/ 
+cd main/helm && helm unittest -f '../../test/helm/*.yaml'  .
+
diff --git a/alfa-client/libs/design-system/src/index.ts b/alfa-client/libs/design-system/src/index.ts
index 9f7b60a883c3ad40fc3bb29b3bd56d8a058d9197..57c220dc85cf06f66d1e23edd66bc7d9bff947ea 100644
--- a/alfa-client/libs/design-system/src/index.ts
+++ b/alfa-client/libs/design-system/src/index.ts
@@ -1,7 +1,8 @@
-export * from './lib/attachment-container/attachment-container.component';
+export * from './lib/attachment-header/attachment-header.component';
+export * from './lib/attachment-wrapper/attachment-wrapper.component';
 export * from './lib/attachment/attachment.component';
-export * from './lib/bescheid-container/bescheid-container.component';
 export * from './lib/bescheid-status-text/bescheid-status-text.component';
+export * from './lib/bescheid-wrapper/bescheid-wrapper.component';
 export * from './lib/button-card/button-card.component';
 export * from './lib/button/button.component';
 export * from './lib/form/error-message/error-message.component';
@@ -15,6 +16,7 @@ export * from './lib/icons/bescheid-upload-icon/bescheid-upload-icon.component';
 export * from './lib/icons/close-icon/close-icon.component';
 export * from './lib/icons/exclamation-icon/exclamation-icon.component';
 export * from './lib/icons/file-icon/file-icon.component';
+export * from './lib/icons/iconVariants';
 export * from './lib/icons/save-icon/save-icon.component';
 export * from './lib/icons/send-icon/send-icon.component';
 export * from './lib/icons/spinner-icon/spinner-icon.component';
diff --git a/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.component.spec.ts b/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.component.spec.ts
deleted file mode 100644
index 5c799383d81b51dd6df2350ed794ed09c999df1f..0000000000000000000000000000000000000000
--- a/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.component.spec.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { AttachmentContainerComponent } from './attachment-container.component';
-
-describe('AttachmentContainerComponent', () => {
-  let component: AttachmentContainerComponent;
-  let fixture: ComponentFixture<AttachmentContainerComponent>;
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      imports: [AttachmentContainerComponent],
-    }).compileComponents();
-
-    fixture = TestBed.createComponent(AttachmentContainerComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.component.ts b/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.component.ts
deleted file mode 100644
index 35de705fee041ebb34196879393dffcaecb76f26..0000000000000000000000000000000000000000
--- a/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.component.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { CommonModule } from '@angular/common';
-import { Component } from '@angular/core';
-
-@Component({
-  selector: 'ods-attachment-container',
-  standalone: true,
-  imports: [CommonModule],
-  template: `<div
-    class="border-grayborder block overflow-hidden rounded-md border shadow empty:hidden"
-  >
-    <ng-content></ng-content>
-  </div>`,
-})
-export class AttachmentContainerComponent {}
diff --git a/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.stories.ts b/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.stories.ts
deleted file mode 100644
index dbb89342b65d8059a7eb55cce494d2ec53dac8f6..0000000000000000000000000000000000000000
--- a/alfa-client/libs/design-system/src/lib/attachment-container/attachment-container.stories.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { moduleMetadata, type Meta, type StoryObj } from '@storybook/angular';
-
-import { AttachmentComponent } from '../attachment/attachment.component';
-import { AttachmentContainerComponent } from './attachment-container.component';
-
-const meta: Meta<AttachmentContainerComponent> = {
-  title: 'Containers/Attachment container',
-  component: AttachmentContainerComponent,
-  parameters: {
-    docs: {
-      description: {
-        component: 'Container for multiple attachments',
-      },
-    },
-  },
-  decorators: [
-    moduleMetadata({
-      imports: [AttachmentContainerComponent, AttachmentComponent],
-    }),
-  ],
-  excludeStories: /.*Data$/,
-  tags: ['autodocs'],
-};
-
-export default meta;
-type Story = StoryObj<AttachmentContainerComponent>;
-
-export const Default: Story = {
-  render: () => ({
-    template: `<ods-attachment-container>
-        <ods-attachment caption="Attachment" description="200 kB" fileType="pdf"></ods-attachment>
-        <ods-attachment caption="Second attachment" description="432 kB" fileType="doc"></ods-attachment>
-    </ods-attachment-container>`,
-  }),
-};
diff --git a/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.component.spec.ts b/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b1484d6418804db087a5418a8eb26a8e41114398
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { AttachmentHeaderComponent } from './attachment-header.component';
+
+describe('AttachmentHeaderComponent', () => {
+  let component: AttachmentHeaderComponent;
+  let fixture: ComponentFixture<AttachmentHeaderComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [AttachmentHeaderComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AttachmentHeaderComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.component.ts b/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dadeccb218137f87612c2d67a12c7087a6286927
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.component.ts
@@ -0,0 +1,15 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'ods-attachment-header',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<div class="flex h-11 items-center justify-between px-3">
+    <h4 class="text-sm font-medium text-text">{{ title }}</h4>
+    <ng-content select="[action-buttons]"></ng-content>
+  </div>`,
+})
+export class AttachmentHeaderComponent {
+  @Input() title: string = '';
+}
diff --git a/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.stories.ts b/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..33a3d93237c69b82a28b08efaf36cc92f5970c5e
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/attachment-header/attachment-header.stories.ts
@@ -0,0 +1,45 @@
+import { argsToTemplate, moduleMetadata, type Meta, type StoryObj } from '@storybook/angular';
+
+import { DownloadButtonComponent } from '../../../../design-component/src/lib/download-button/download-button.component';
+
+import { AttachmentComponent } from '../attachment/attachment.component';
+import { AttachmentHeaderComponent } from './attachment-header.component';
+
+const meta: Meta<AttachmentHeaderComponent> = {
+  title: 'Attachment header',
+  component: AttachmentHeaderComponent,
+  parameters: {
+    docs: {
+      description: {
+        component: 'Header may contain title and/or buttons',
+      },
+    },
+  },
+  decorators: [
+    moduleMetadata({
+      imports: [AttachmentHeaderComponent, AttachmentComponent, DownloadButtonComponent],
+    }),
+  ],
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<AttachmentHeaderComponent>;
+
+export const Default: Story = {
+  args: {
+    title: 'Anhänge',
+  },
+  argTypes: {
+    title: {
+      description: 'Title for group of files',
+    },
+  },
+  render: (args) => ({
+    props: args,
+    template: `<ods-attachment-header ${argsToTemplate(args)}>
+        <ods-download-button action-buttons />
+    </ods-attachment-header>`,
+  }),
+};
diff --git a/alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-container.component.spec.ts b/alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.component.spec.ts
similarity index 50%
rename from alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-container.component.spec.ts
rename to alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.component.spec.ts
index 32b8fc6eadf7d114d8730894bd5d666e33b7bc81..bc771a072c51f229dd9c2d68262a32a2f3db915b 100644
--- a/alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-container.component.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.component.spec.ts
@@ -1,16 +1,16 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { BescheidContainerComponent } from './bescheid-container.component';
+import { AttachmentWrapperComponent } from './attachment-wrapper.component';
 
-describe('BescheidContainerComponent', () => {
-  let component: BescheidContainerComponent;
-  let fixture: ComponentFixture<BescheidContainerComponent>;
+describe('AttachmentWrapperComponent', () => {
+  let component: AttachmentWrapperComponent;
+  let fixture: ComponentFixture<AttachmentWrapperComponent>;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      imports: [BescheidContainerComponent],
+      imports: [AttachmentWrapperComponent],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(BescheidContainerComponent);
+    fixture = TestBed.createComponent(AttachmentWrapperComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
diff --git a/alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.component.ts b/alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..863cc92dffee0d1f7a1e2fd58636f40a6a39f1b5
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.component.ts
@@ -0,0 +1,13 @@
+import { CommonModule } from '@angular/common';
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'ods-attachment-wrapper',
+  standalone: true,
+  imports: [CommonModule],
+  styles: [
+    ':host {@apply flex flex-col overflow-hidden rounded-md shadow shadow-grayborder border border-grayborder empty:hidden}',
+  ],
+  template: `<ng-content></ng-content>`,
+})
+export class AttachmentWrapperComponent {}
diff --git a/alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.stories.ts b/alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..485acda2600b59166e331fe38bffba7392c1e783
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/attachment-wrapper/attachment-wrapper.stories.ts
@@ -0,0 +1,47 @@
+import { argsToTemplate, moduleMetadata, type Meta, type StoryObj } from '@storybook/angular';
+
+import { DownloadButtonComponent } from '../../../../design-component/src/lib/download-button/download-button.component';
+
+import { AttachmentComponent } from '../attachment/attachment.component';
+import { AttachmentWrapperComponent } from './attachment-wrapper.component';
+
+const meta: Meta<AttachmentWrapperComponent> = {
+  title: 'Wrappers/Attachment wrapper',
+  component: AttachmentWrapperComponent,
+  parameters: {
+    docs: {
+      description: {
+        component: 'Wrapper for multiple attachments',
+      },
+    },
+  },
+  decorators: [
+    moduleMetadata({
+      imports: [AttachmentWrapperComponent, AttachmentComponent, DownloadButtonComponent],
+    }),
+  ],
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<AttachmentWrapperComponent>;
+
+export const Default: Story = {
+  args: {
+    title: 'Anhänge',
+  },
+  argTypes: {
+    title: {
+      description: 'Title for group of files',
+    },
+  },
+  render: (args) => ({
+    props: args,
+    template: `<ods-attachment-wrapper ${argsToTemplate(args)}>
+        <ods-download-button action-buttons />
+        <ods-attachment caption="Attachment" description="200 kB" fileType="pdf"></ods-attachment>
+        <ods-attachment caption="Second attachment" description="432 kB" fileType="doc"></ods-attachment>
+    </ods-attachment-wrapper>`,
+  }),
+};
diff --git a/alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.component.spec.ts b/alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..741c0bb800a3c711eb0771d36c00fa55feb38dee
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { BescheidWrapperComponent } from './bescheid-wrapper.component';
+
+describe('BescheidWrapperComponent', () => {
+  let component: BescheidWrapperComponent;
+  let fixture: ComponentFixture<BescheidWrapperComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [BescheidWrapperComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(BescheidWrapperComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-container.component.ts b/alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.component.ts
similarity index 54%
rename from alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-container.component.ts
rename to alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.component.ts
index 16f18a8cc4c562567f48be52c279bba2aa139ac3..62f2564416b0855318c87c4fa3b0c2b2b9b47912 100644
--- a/alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-container.component.ts
+++ b/alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.component.ts
@@ -2,11 +2,11 @@ import { CommonModule } from '@angular/common';
 import { Component } from '@angular/core';
 
 @Component({
-  selector: 'ods-bescheid-container',
+  selector: 'ods-bescheid-wrapper',
   standalone: true,
   imports: [CommonModule],
-  template: ` <article class="bg-background-150 flex flex-col gap-4 rounded-lg p-4">
+  template: ` <article class="flex flex-col gap-4 rounded-lg bg-background-150 p-4">
     <ng-content></ng-content>
   </article>`,
 })
-export class BescheidContainerComponent {}
+export class BescheidWrapperComponent {}
diff --git a/alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-comtainer.stories.ts b/alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.stories.ts
similarity index 60%
rename from alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-comtainer.stories.ts
rename to alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.stories.ts
index b0fc0da094793d9e46009e818b7f365a0f4f72ff..2d3a4ee07f081623052bb6b16e76cbb42dcd8c40 100644
--- a/alfa-client/libs/design-system/src/lib/bescheid-container/bescheid-comtainer.stories.ts
+++ b/alfa-client/libs/design-system/src/lib/bescheid-wrapper/bescheid-wrapper.stories.ts
@@ -1,17 +1,17 @@
 import { moduleMetadata, type Meta, type StoryObj } from '@storybook/angular';
 
-import { AttachmentContainerComponent } from '../attachment-container/attachment-container.component';
+import { AttachmentWrapperComponent } from '../attachment-wrapper/attachment-wrapper.component';
 import { AttachmentComponent } from '../attachment/attachment.component';
 import { BescheidStatusTextComponent } from '../bescheid-status-text/bescheid-status-text.component';
-import { BescheidContainerComponent } from './bescheid-container.component';
+import { BescheidWrapperComponent } from './bescheid-wrapper.component';
 
-const meta: Meta<BescheidContainerComponent> = {
-  title: 'Containers/Bescheid container',
-  component: BescheidContainerComponent,
+const meta: Meta<BescheidWrapperComponent> = {
+  title: 'Wrappers/Bescheid wrapper',
+  component: BescheidWrapperComponent,
   parameters: {
     docs: {
       description: {
-        component: 'Container for bescheid information',
+        component: 'Wrapper for bescheid information',
       },
     },
   },
@@ -19,8 +19,8 @@ const meta: Meta<BescheidContainerComponent> = {
     moduleMetadata({
       imports: [
         AttachmentComponent,
-        AttachmentContainerComponent,
-        BescheidContainerComponent,
+        AttachmentWrapperComponent,
+        BescheidWrapperComponent,
         BescheidStatusTextComponent,
       ],
     }),
@@ -30,20 +30,20 @@ const meta: Meta<BescheidContainerComponent> = {
 };
 
 export default meta;
-type Story = StoryObj<BescheidContainerComponent>;
+type Story = StoryObj<BescheidWrapperComponent>;
 
 export const Default: Story = {
   render: () => ({
-    template: `<ods-bescheid-container>
+    template: `<ods-bescheid-wrapper>
         <ods-bescheid-status-text
             bewilligt="true"
             dateText="13.11.2024"
             [hasBescheidDraft]="false"
         ></ods-bescheid-status-text>
-        <ods-attachment-container>
+        <ods-attachment-wrapper>
             <ods-attachment caption="Attachment" description="200 kB" fileType="pdf"></ods-attachment>
             <ods-attachment caption="Second attachment" description="432 kB" fileType="doc"></ods-attachment>
-        </ods-attachment-container>
-    </ods-bescheid-container>`,
+        </ods-attachment-wrapper>
+    </ods-bescheid-wrapper>`,
   }),
 };
diff --git a/alfa-client/libs/design-system/src/lib/button/button.component.ts b/alfa-client/libs/design-system/src/lib/button/button.component.ts
index 19d22368fd3dd405970df6c7a77790783ee19d77..58ba7ec0d96c8c0eb0516c9fbc367b885d686837 100644
--- a/alfa-client/libs/design-system/src/lib/button/button.component.ts
+++ b/alfa-client/libs/design-system/src/lib/button/button.component.ts
@@ -2,19 +2,22 @@ import { CommonModule } from '@angular/common';
 import { Component, EventEmitter, Input, Output } from '@angular/core';
 import { VariantProps, cva } from 'class-variance-authority';
 
+import { IconVariants } from '../icons/iconVariants';
 import { SpinnerIconComponent } from '../icons/spinner-icon/spinner-icon.component';
 
 export const buttonVariants = cva(
-  'flex cursor-pointer items-center gap-4 rounded-md font-medium disabled:cursor-wait text-sm min-w-32 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ozgblue-800',
+  'flex cursor-pointer items-center gap-4 rounded-md font-medium disabled:cursor-wait text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary',
   {
     variants: {
       variant: {
         primary: 'hover:enabled:bg-primary-hover bg-primary text-white shadow-sm',
         outline:
           'border border-primary bg-background-50 text-primary hover:enabled:bg-background-100',
+        icon: 'border border-transparent hover:border-primary',
       },
       size: {
-        medium: 'h-9 py-2 px-4',
+        medium: 'h-9 py-2 px-4 min-w-32',
+        fit: 'h-fit p-2',
       },
     },
     defaultVariants: {
@@ -39,8 +42,8 @@ type ButtonVariants = VariantProps<typeof buttonVariants>;
     (click)="clickEmitter.emit()"
   >
     <ng-content *ngIf="!isLoading" select="[icon]"></ng-content>
-    <ods-spinner-icon *ngIf="isLoading" size="medium"></ods-spinner-icon>
-    <div class="flex-grow">{{ text }}</div>
+    <ods-spinner-icon *ngIf="isLoading" [size]="spinnerSize"></ods-spinner-icon>
+    <div *ngIf="text" class="flex-grow">{{ text }}</div>
   </button>`,
 })
 export class ButtonComponent {
@@ -49,6 +52,7 @@ export class ButtonComponent {
   @Input() isLoading: boolean = false;
   @Input() variant: ButtonVariants['variant'];
   @Input() size: ButtonVariants['size'];
+  @Input() spinnerSize: IconVariants['size'] = 'medium';
 
   @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
 
diff --git a/alfa-client/libs/design-system/src/lib/button/button.stories.ts b/alfa-client/libs/design-system/src/lib/button/button.stories.ts
index 5db5e2e20ad61881bf767c822890d900898544ea..c5ac6ce8b3312deac5a00ce17af2a73f073565e6 100644
--- a/alfa-client/libs/design-system/src/lib/button/button.stories.ts
+++ b/alfa-client/libs/design-system/src/lib/button/button.stories.ts
@@ -1,6 +1,6 @@
 import { argsToTemplate, moduleMetadata, type Meta, type StoryObj } from '@storybook/angular';
 
-import { FileIconComponent } from '../icons/file-icon/file-icon.component';
+import { SaveIconComponent } from '../icons/save-icon/save-icon.component';
 import { ButtonComponent } from './button.component';
 
 const meta: Meta<ButtonComponent> = {
@@ -8,7 +8,7 @@ const meta: Meta<ButtonComponent> = {
   component: ButtonComponent,
   decorators: [
     moduleMetadata({
-      imports: [ButtonComponent, FileIconComponent],
+      imports: [ButtonComponent, SaveIconComponent],
     }),
   ],
   excludeStories: /.*Data$/,
@@ -23,6 +23,8 @@ export const Default: Story = {
     text: 'Hello world!',
     isLoading: false,
     variant: 'primary',
+    size: 'medium',
+    spinnerSize: 'medium',
   },
   argTypes: {
     variant: {
@@ -37,11 +39,12 @@ export const WithIcon: Story = {
   args: {
     text: 'I have an icon',
     variant: 'outline',
+    size: 'medium',
   },
   render: (args) => ({
     props: args,
     template: `<ods-button ${argsToTemplate(args)}>
-      <ods-file-icon icon fileType='pdf' size='small'></ods-file-icon>
+      <ods-save-icon icon size='small'></ods-save-icon>
     </ods-button>`,
   }),
 };
@@ -50,5 +53,19 @@ export const IsLoading: Story = {
   args: {
     text: 'Loading...',
     isLoading: true,
+    size: 'medium',
   },
 };
+
+export const OnlyIcon: Story = {
+  args: {
+    variant: 'icon',
+    size: 'fit',
+  },
+  render: (args) => ({
+    props: args,
+    template: `<ods-button ${argsToTemplate(args)}>
+      <ods-save-icon icon size='medium'></ods-save-icon>
+    </ods-button>`,
+  }),
+};
diff --git a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
index 87770f419954a3c32d59424b0aab2a6a6c05a96b..e136a50bb991af6df9384d7ceca287879b3cdcc8 100644
--- a/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/text-input/text-input.component.ts
@@ -6,12 +6,14 @@ import { cva, VariantProps } from 'class-variance-authority';
 import { ErrorMessageComponent } from '../error-message/error-message.component';
 
 const textInputVariants = cva(
-  'block w-full rounded-lg border bg-background-50 px-3 py-2 text-base leading-5 text-text focus:border-primary focus:ring-primary outline-none',
+  'block w-full rounded-lg border bg-background-50 px-3 py-2 text-base leading-5 text-text focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
   {
     variants: {
       variant: {
-        default: 'border-primary-600/50',
-        error: 'border-error',
+        default:
+          'border-primary-600/50 focus-visible:outline-focus focus-visible:border-background-200 hover:border-primary-hover',
+        error:
+          'border-error/50 hover:border-error focus-visible:outline-error focus-visible:border-background-200',
       },
     },
     defaultVariants: {
@@ -27,9 +29,8 @@ type TextInputVariants = VariantProps<typeof textInputVariants>;
   imports: [CommonModule, ErrorMessageComponent, ReactiveFormsModule, TechSharedModule],
   template: `
     <div>
-      <label [for]="id" class="text-md mb-2 block font-medium text-text"
-        >{{ label }}
-        <ng-container *ngIf="required"><i aria-hidden="true">*</i></ng-container>
+      <label [for]="id" class="text-md mb-2 block font-medium text-text">
+        {{ inputLabel }}<ng-container *ngIf="required"><i aria-hidden="true">*</i></ng-container>
       </label>
       <div class="mt-2">
         <input
@@ -39,9 +40,9 @@ type TextInputVariants = VariantProps<typeof textInputVariants>;
           [ngClass]="textInputVariants({ variant })"
           [placeholder]="placeholder"
           [autocomplete]="autocomplete"
-          [required]="required"
+          [attr.aria-required]="required"
           [attr.aria-invalid]="variant === 'error'"
-          [attr.data-test-id]="(label | convertForDataTest) + '-text-input'"
+          [attr.data-test-id]="(inputLabel | convertForDataTest) + '-text-input'"
           #inputElement
         />
       </div>
@@ -52,7 +53,10 @@ type TextInputVariants = VariantProps<typeof textInputVariants>;
 export class TextInputComponent {
   @ViewChild('inputElement') inputElement: ElementRef;
 
-  @Input({ required: true }) label: string;
+  @Input({ required: true }) set label(label: string) {
+    this.inputLabel = label;
+    this.id = convertForDataTest(label);
+  }
   @Input() placeholder: string = '';
   @Input() autocomplete: string = 'off';
   @Input() variant: TextInputVariants['variant'];
@@ -65,9 +69,7 @@ export class TextInputComponent {
     }
   }
 
+  inputLabel: string;
+  id: string;
   textInputVariants = textInputVariants;
-
-  get id(): string {
-    return convertForDataTest(this.label);
-  }
 }
diff --git a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
index 21e6c863afcc41c876cdfd0fa45704770ce39d56..90a4fa85f7dcb0b5a55f6a926a0d08ab63e332a9 100644
--- a/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/textarea/textarea.component.ts
@@ -1,16 +1,18 @@
-import { convertForDataTest, TechSharedModule } from '@alfa-client/tech-shared';
+import { TechSharedModule, convertForDataTest } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, ElementRef, Input, ViewChild } from '@angular/core';
 import { FormControl, ReactiveFormsModule } from '@angular/forms';
-import { cva, VariantProps } from 'class-variance-authority';
+import { VariantProps, cva } from 'class-variance-authority';
 
 const textareaVariants = cva(
-  'block w-full rounded-lg border bg-background-50 px-3 py-2 text-base text-text leading-5 focus:border-primary focus:ring-primary outline-none',
+  'block w-full rounded-lg border bg-background-50 px-3 py-2 text-base text-text leading-5 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
   {
     variants: {
       variant: {
-        default: 'border-primary-600/50',
-        error: 'border-error',
+        default:
+          'border-primary-600/50 focus-visible:outline-focus focus-visible:border-background-200 hover:border-primary-hover',
+        error:
+          'border-error/50 hover:border-error focus-visible:outline-error focus-visible:border-background-200',
       },
     },
     defaultVariants: {
@@ -26,9 +28,8 @@ type TextareaVariants = VariantProps<typeof textareaVariants>;
   imports: [CommonModule, ReactiveFormsModule, TechSharedModule],
   template: `
     <div class="mt-2">
-      <label [for]="id" class="text-md mb-2 block font-medium text-text"
-        >{{ label }}
-        <ng-container *ngIf="required"><i aria-hidden="true">*</i></ng-container>
+      <label [for]="id" class="text-md mb-2 block font-medium text-text">
+        {{ inputLabel }}<ng-container *ngIf="required"><i aria-hidden="true">*</i></ng-container>
       </label>
       <textarea
         [id]="id"
@@ -37,9 +38,9 @@ type TextareaVariants = VariantProps<typeof textareaVariants>;
         [ngClass]="textareaVariants({ variant })"
         [placeholder]="placeholder"
         [autocomplete]="autocomplete"
-        [required]="required"
+        [attr.aria-required]="required"
         [attr.aria-invalid]="variant === 'error'"
-        [attr.data-test-id]="(label | convertForDataTest) + '-textarea'"
+        [attr.data-test-id]="(inputLabel | convertForDataTest) + '-textarea'"
         #textAreaElement
       ></textarea>
       <ng-content select="[error]"></ng-content>
@@ -49,7 +50,10 @@ type TextareaVariants = VariantProps<typeof textareaVariants>;
 export class TextareaComponent {
   @ViewChild('textAreaElement') textAreaElement: ElementRef;
 
-  @Input({ required: true }) label!: string;
+  @Input({ required: true }) set label(label: string) {
+    this.inputLabel = label;
+    this.id = convertForDataTest(label);
+  }
   @Input({ required: true }) placeholder!: string;
   @Input() error: string;
   @Input() rows: number = 3;
@@ -64,9 +68,7 @@ export class TextareaComponent {
     }
   }
 
+  inputLabel: string;
+  id: string;
   textareaVariants = textareaVariants;
-
-  get id(): string {
-    return convertForDataTest(this.label);
-  }
 }
diff --git a/alfa-client/libs/design-system/src/lib/icons/attachment-icon/attachment-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/attachment-icon/attachment-icon.component.ts
index dea522781c4adc45ddfa582fd86fa7f52f5774f5..30a34056cee8da2a6e01385790c7c8e48cee4431 100644
--- a/alfa-client/libs/design-system/src/lib/icons/attachment-icon/attachment-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/attachment-icon/attachment-icon.component.ts
@@ -2,7 +2,7 @@ import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { twMerge } from 'tailwind-merge';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-attachment-icon',
diff --git a/alfa-client/libs/design-system/src/lib/icons/bescheid-generate-icon/bescheid-generate-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/bescheid-generate-icon/bescheid-generate-icon.component.ts
index 3a7f86c81501c7dc5722b5f868bf1c12fa05c615..d9b829b2269a676de6cf15fed9e50e7cdd9081fa 100644
--- a/alfa-client/libs/design-system/src/lib/icons/bescheid-generate-icon/bescheid-generate-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/bescheid-generate-icon/bescheid-generate-icon.component.ts
@@ -2,7 +2,7 @@ import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { twMerge } from 'tailwind-merge';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-bescheid-generate-icon',
diff --git a/alfa-client/libs/design-system/src/lib/icons/bescheid-upload-icon/bescheid-upload-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/bescheid-upload-icon/bescheid-upload-icon.component.ts
index 3947b891b5f3d07cd29fd9a6c0f3a2bb9c2f6089..cc265fdbb039365e1eeae63fc69b339578493eba 100644
--- a/alfa-client/libs/design-system/src/lib/icons/bescheid-upload-icon/bescheid-upload-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/bescheid-upload-icon/bescheid-upload-icon.component.ts
@@ -2,7 +2,7 @@ import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { twMerge } from 'tailwind-merge';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-bescheid-upload-icon',
diff --git a/alfa-client/libs/design-system/src/lib/icons/close-icon/close-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/close-icon/close-icon.component.ts
index 81c6ce8e91c4ab7fab1ef6e4e9f0bcf6dfc8f7c2..5de688d73e98d67b1296d1519332fd7e3b7c9660 100644
--- a/alfa-client/libs/design-system/src/lib/icons/close-icon/close-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/close-icon/close-icon.component.ts
@@ -2,7 +2,7 @@ import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { twMerge } from 'tailwind-merge';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-close-icon',
diff --git a/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.ts
index 9dda95ea08ca28bee431be67e9400e6ccaa6f0ec..c425c77aaa40b0efa0d0e2dd5b14decbad216f5e 100644
--- a/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/exclamation-icon/exclamation-icon.component.ts
@@ -2,7 +2,7 @@ import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { twMerge } from 'tailwind-merge';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-exclamation-icon',
diff --git a/alfa-client/libs/design-system/src/lib/icons/file-icon/file-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/file-icon/file-icon.component.ts
index 544495d4fab1c914f1126ffa182911cdb23d7a10..e387e2d121ea54836748f7ee9d04ba3923ad1f56 100644
--- a/alfa-client/libs/design-system/src/lib/icons/file-icon/file-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/file-icon/file-icon.component.ts
@@ -4,7 +4,7 @@ import { VariantProps, cva } from 'class-variance-authority';
 
 import { SpinnerIconComponent } from '../spinner-icon/spinner-icon.component';
 
-const fileiconVariants = cva('', {
+const fileiconVariants = cva('fill-ozggray-300', {
   variants: {
     fileType: {
       doc: 'fill-doc',
diff --git a/alfa-client/libs/design-system/src/lib/icons/IconClasses.ts b/alfa-client/libs/design-system/src/lib/icons/iconVariants.ts
similarity index 100%
rename from alfa-client/libs/design-system/src/lib/icons/IconClasses.ts
rename to alfa-client/libs/design-system/src/lib/icons/iconVariants.ts
diff --git a/alfa-client/libs/design-system/src/lib/icons/save-icon/save-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/save-icon/save-icon.component.ts
index 405d1199cd3837498a19164e319107b1b5a706d7..b2d22480f7100aefc09ed77c3d2d499eebef01bf 100644
--- a/alfa-client/libs/design-system/src/lib/icons/save-icon/save-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/save-icon/save-icon.component.ts
@@ -2,7 +2,7 @@ import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { twMerge } from 'tailwind-merge';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-save-icon',
diff --git a/alfa-client/libs/design-system/src/lib/icons/send-icon/send-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/send-icon/send-icon.component.ts
index 60205dd2942b8c0a47fd75f9ffe699a731c33061..6a34bb7ebb5b3b019a8254bf2f723eb93ac2b58e 100644
--- a/alfa-client/libs/design-system/src/lib/icons/send-icon/send-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/send-icon/send-icon.component.ts
@@ -2,7 +2,7 @@ import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { twMerge } from 'tailwind-merge';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-send-icon',
diff --git a/alfa-client/libs/design-system/src/lib/icons/spinner-icon/spinner-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/spinner-icon/spinner-icon.component.ts
index 05aaf8d9aab8a37f8caa3f078f47b9dab1e96117..321829613a72fd018fbadd3b9117c3f16e119cc8 100644
--- a/alfa-client/libs/design-system/src/lib/icons/spinner-icon/spinner-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/spinner-icon/spinner-icon.component.ts
@@ -1,7 +1,7 @@
 import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-spinner-icon',
diff --git a/alfa-client/libs/design-system/src/lib/icons/stamp-icon/stamp-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/stamp-icon/stamp-icon.component.ts
index 7b71c7b5d4dc15511d67441582c2539c7abea06b..26bb89c266ab88212c87bf6b0beba4874843fb2c 100644
--- a/alfa-client/libs/design-system/src/lib/icons/stamp-icon/stamp-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/stamp-icon/stamp-icon.component.ts
@@ -2,7 +2,7 @@ import { NgClass } from '@angular/common';
 import { Component, Input } from '@angular/core';
 import { twMerge } from 'tailwind-merge';
 
-import { IconVariants, iconVariants } from '../IconClasses';
+import { IconVariants, iconVariants } from '../iconVariants';
 
 @Component({
   selector: 'ods-stamp-icon',
diff --git a/alfa-client/libs/design-system/src/lib/tailwind-preset/root.css b/alfa-client/libs/design-system/src/lib/tailwind-preset/root.css
index ef516cdcbe6c4023552a81647ff66826ae0c9ab9..7e997ffe4f9bfb19811dc99c99a708dd8d92e741 100644
--- a/alfa-client/libs/design-system/src/lib/tailwind-preset/root.css
+++ b/alfa-client/libs/design-system/src/lib/tailwind-preset/root.css
@@ -7,6 +7,7 @@
 :root {
   --warning: 38 92% 50%;
   --color-error: 0 71% 49%;
+  --color-focus: 212 64% 47%;
 
   --color-background-secondary: 0 0% 98%;
   --color-mainbg: 0 0% 100%;
@@ -20,7 +21,7 @@
   --color-background-150: 0 0% 95%;
   --color-background-200: 0 0% 90%;
 
-  --color-grayborder: 0 0% 75%;
+  --color-grayborder: 0 0% 92%;
 
   --color-bewilligt-100: 122 100% 92%;
   --color-bewilligt-700: 122 100% 29%;
@@ -36,6 +37,7 @@
 
 .dark {
   --color-error: 0 99% 72%;
+  --color-focus: 43 100% 48%;
 
   --color-background-secondary: 0 0% 16%;
   --color-mainbg: 0 0% 14%;
diff --git a/alfa-client/libs/design-system/src/lib/tailwind-preset/tailwind.config.js b/alfa-client/libs/design-system/src/lib/tailwind-preset/tailwind.config.js
index a207c9b06a2b19caa92f6abda9a783ae20ea61cd..1c7b298d5afa17aae60ab57b36b9152cec514121 100644
--- a/alfa-client/libs/design-system/src/lib/tailwind-preset/tailwind.config.js
+++ b/alfa-client/libs/design-system/src/lib/tailwind-preset/tailwind.config.js
@@ -98,6 +98,7 @@ module.exports = {
         whitetext: 'hsl(var(--color-text-white) / <alpha-value>)',
         warning: 'hsl(var(--warning))',
         error: 'hsl(var(--color-error))',
+        focus: 'hsl(var(--color-focus))',
       },
     },
   },
diff --git a/alfa-client/libs/design-system/test/helm-linter-values.yaml b/alfa-client/libs/design-system/test/helm-linter-values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..88a8eb17a808af1c3314ac178a0db55672280ae6
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm-linter-values.yaml
@@ -0,0 +1,36 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+baseUrl:  test.sh.ozg-cloud.de
+
+ozgcloud:
+  bundesland: sh
+  bezeichner: helm
+  environment: test
+
+imagePullSecret: test-image-secret
+
+networkPolicy:
+  dnsServerNamespace: dummy-dns
+
diff --git a/alfa-client/libs/design-system/test/helm/deployment_63_char_test.yaml b/alfa-client/libs/design-system/test/helm/deployment_63_char_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..09d03963a7eeb081a86cc2e28590feaf82c7385f
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/deployment_63_char_test.yaml
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment less than 63 chars
+release:
+  name: storybook
+  namespace: sh-helm-test
+
+templates:
+  - templates/deployment.yaml
+set:
+  imagePullSecret: test-image-secret
+
+tests:
+  - it: should fail on .Release.Namespace length longer than 63 characters
+    release:
+      namespace: test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890
+    asserts:
+      - failedTemplate:
+          errorMessage: .Release.Namespace test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 ist zu lang (max. 63 Zeichen)
+  - it: should not fail on .Release.Namespace length less than 63 characters
+    asserts:
+      - notFailedTemplate: {}
+  - it: should fail on .Chart.Name-.Chart.Version length longer than 63 characters
+    chart:
+      version: 1.0-test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890
+    asserts:
+      - failedTemplate:
+          errorMessage: .Chart.Name-.Chart.Version storybook-1.0-test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 ist zu lang (max. 63 Zeichen)
+  - it: should not fail on .Chart.Name-.Chart.Version length less than 63 characters
+    asserts:
+      - notFailedTemplate: {}
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/test/helm/deployment_env_test.yaml b/alfa-client/libs/design-system/test/helm/deployment_env_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..006e6c299885077afddf976b14b59bb0718dbd9a
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/deployment_env_test.yaml
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment container environments 
+templates:
+  - templates/deployment.yaml
+set:
+  imagePullSecret: test-image-secret
+
+tests:
+  - it: check customList as list
+    set:
+      env.customList:
+        - name: my_test_environment_name
+          value: "A test value"
+        - name: test_environment
+          value: "B test value"
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: test_environment
+            value: "B test value"
+  - it: check customList as dict
+    set:
+      env.customList:
+        my_test_environment_name: "A test value"
+        test_environment: "B test value"
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: test_environment
+            value: "B test value"
+
+  - it:  no env exist by default
+    asserts:
+      - isEmpty:
+          path: spec.template.spec.containers[0].env
diff --git a/alfa-client/libs/design-system/test/helm/deployment_host_aliases_test.yaml b/alfa-client/libs/design-system/test/helm/deployment_host_aliases_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2df27950bdc08c277a14b952b82ebb96cb08e9b3
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/deployment_host_aliases_test.yaml
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment host aliases
+release:
+  name: storybook
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+set:  
+  imagePullSecret: test-image-secret
+tests:
+  - it: should not set spec.template.spec.hostAliases
+    asserts:
+      - isNull:
+          path: spec.template.spec.hostAliases
+  - it: should set spec.template.spec.hostAliases
+    set:
+      hostAliases:
+        - ip: "127.0.0.1"
+          hostname:
+          - "eins"
+          - "zwei"
+    asserts:
+      - contains:
+          path: spec.template.spec.hostAliases
+          content:
+            ip: "127.0.0.1"
+            hostname:
+            - "eins"
+            - "zwei"
diff --git a/alfa-client/libs/design-system/test/helm/deployment_ozgcloud_base_values_test.yaml b/alfa-client/libs/design-system/test/helm/deployment_ozgcloud_base_values_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8c4e08d29e5cd804dc358818f84be4b36caae501
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/deployment_ozgcloud_base_values_test.yaml
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test ozgcloud base values
+release:
+  name: storybook
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+
+
+tests:
+  - it: should fail on missing imagePullSecret
+    set:
+      ozgcloud:
+        environment: dev
+    asserts:
+      - failedTemplate:
+          errorMessage: imagePullSecret must be set
+  - it: should not fail on given environment
+    set:
+      ozgcloud:
+        environment: dev
+      imagePullSecret: test-image-secret
+    asserts:
+      - notFailedTemplate: {}
diff --git a/alfa-client/libs/design-system/test/helm/deployment_resources_test.yaml b/alfa-client/libs/design-system/test/helm/deployment_resources_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c1823ac3b5de1ccb782f5cf89d76853def332c98
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/deployment_resources_test.yaml
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test deployment container resources
+release:
+  name: storybook
+templates:
+  - templates/deployment.yaml
+set:
+  imagePullSecret: test-image-secret
+
+tests:
+  - it: should generate resources when values set
+    set:
+      resources:
+        limits:
+          cpu: 11m
+          memory: 22Mi
+        requests:
+          cpu: 33m
+          memory: 44Mi
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.cpu
+          value: 11m
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.memory
+          value: 22Mi
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.cpu
+          value: 33m
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.memory
+          value: 44Mi
+  - it: should not generate resources when values not set
+    asserts:
+      - isEmpty:
+          path: spec.template.spec.containers[0].resources
+
diff --git a/alfa-client/libs/design-system/test/helm/deployment_test.yaml b/alfa-client/libs/design-system/test/helm/deployment_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1c76b61107630a97e9d5f69cb4f52b5aed907bcb
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/deployment_test.yaml
@@ -0,0 +1,250 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: deployment_test
+release:
+  name: storybook
+  namespace: storybook
+templates:
+  - templates/deployment.yaml
+set:
+  imagePullSecret: image-pull-secret
+tests:
+  - it: validate deployment root configuration
+    asserts:
+      - isAPIVersion:
+          of: apps/v1
+      - isKind:
+          of: Deployment
+  - it: validate metadata
+    asserts:
+      - equal:
+          path: metadata.name
+          value: storybook
+      - equal:
+          path: metadata.namespace
+          value: storybook
+      - equal:
+          path: metadata.labels["app.kubernetes.io/instance"]
+          value: storybook
+      - equal:
+          path: metadata.labels["app.kubernetes.io/name"]
+          value: storybook
+      - equal:
+          path: metadata.labels["app.kubernetes.io/namespace"]
+          value: storybook
+      - equal:
+          path: metadata.labels["app.kubernetes.io/part-of"]
+          value: ozgcloud
+      - equal:
+          path: metadata.labels["app.kubernetes.io/version"]
+          value: 0.0.0-MANAGED-BY-JENKINS
+      - equal:
+          path: metadata.labels["helm.sh/chart"]
+          value: storybook-0.0.0-MANAGED-BY-JENKINS
+  - it: validate spec root configuration
+    asserts:
+      - equal:
+          path: spec.progressDeadlineSeconds
+          value: 600
+      - equal:
+          path: spec.replicas
+          value: 1
+      - equal:
+          path: spec.revisionHistoryLimit
+          value: 10
+  - it: validate spec selector
+    asserts:
+      - equal:
+          path: spec.selector.matchLabels["app.kubernetes.io/name"]
+          value: storybook
+      - equal:
+          path: spec.selector.matchLabels["app.kubernetes.io/namespace"]
+          value: storybook
+  - it: validate rolling updates
+    asserts:
+      - equal:
+          path: spec.strategy.rollingUpdate.maxSurge
+          value: 1
+      - equal:
+          path: spec.strategy.rollingUpdate.maxUnavailable
+          value: 0
+      - equal:
+          path: spec.strategy.type
+          value: RollingUpdate
+  - it: validate spec template metadata
+    asserts:
+      - equal:
+          path: spec.template.metadata.labels.component
+          value: storybook
+      - equal:
+          path: spec.template.metadata.labels["app.kubernetes.io/instance"]
+          value: storybook
+      - equal:
+          path: spec.template.metadata.labels["app.kubernetes.io/name"]
+          value: storybook
+      - equal:
+          path: spec.template.metadata.labels["app.kubernetes.io/namespace"]
+          value: storybook
+      - equal:
+          path: spec.template.metadata.labels["app.kubernetes.io/part-of"]
+          value: ozgcloud
+      - equal:
+          path: spec.template.metadata.labels["app.kubernetes.io/version"]
+          value: 0.0.0-MANAGED-BY-JENKINS
+      - equal:
+          path: spec.template.metadata.labels["helm.sh/chart"]
+          value: storybook-0.0.0-MANAGED-BY-JENKINS
+  - it: validate spec template spec topology spread constraints
+    asserts:
+      - equal:
+          path: spec.template.spec.topologySpreadConstraints[0].maxSkew
+          value: 1
+      - equal:
+          path: spec.template.spec.topologySpreadConstraints[0].topologyKey
+          value: kubernetes.io/hostname
+      - equal:
+          path: spec.template.spec.topologySpreadConstraints[0].whenUnsatisfiable
+          value: ScheduleAnyway
+      - equal:
+          path: spec.template.spec.topologySpreadConstraints[0].labelSelector.matchLabels["app.kubernetes.io/name"]
+          value: storybook
+  - it: validate image name
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].image
+          value: "docker.ozg-sh.de/storybook:0.1.0"
+      - isAPIVersion:
+          of: apps/v1
+  - it: validate image pull policy
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].imagePullPolicy
+          value: Always
+  - it: validate container name
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].name
+          value: storybook
+  - it: validate readiness probe
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.failureThreshold
+          value: 3
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.httpGet.path
+          value: /
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.httpGet.port
+          value: 8080
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.httpGet.scheme
+          value: HTTP
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.periodSeconds
+          value: 10
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.successThreshold
+          value: 1
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.timeoutSeconds
+          value: 3
+  - it: validate startup probe
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.failureThreshold
+          value: 3
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.httpGet.path
+          value: /
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.httpGet.port
+          value: 8080
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.httpGet.scheme
+          value: HTTP
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.failureThreshold
+          value: 3
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.periodSeconds
+          value: 10
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.successThreshold
+          value: 1
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.timeoutSeconds
+          value: 3
+  - it: validate container security context
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.privileged
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.runAsNonRoot
+          value: true
+
+  - it: validate container root config
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].stdin
+          value: true
+      - equal:
+          path: spec.template.spec.containers[0].terminationMessagePath
+          value: /dev/termination-log
+      - equal:
+          path: spec.template.spec.containers[0].terminationMessagePolicy
+          value: File
+      - equal:
+          path: spec.template.spec.containers[0].tty
+          value: true
+  - it: validate spec template spec root config
+    asserts:
+        - equal:
+            path: spec.template.spec.dnsConfig
+            value: {}
+        - equal:
+            path: spec.template.spec.dnsPolicy
+            value: ClusterFirst
+        - equal:
+            path: spec.template.spec.imagePullSecrets[0].name
+            value: image-pull-secret
+        - equal:
+            path: spec.template.spec.restartPolicy
+            value: Always
+        - equal:
+            path: spec.template.spec.schedulerName
+            value: default-scheduler
+        - equal:
+            path: spec.template.spec.securityContext
+            value: {}
+        - equal:
+            path: spec.template.spec.terminationGracePeriodSeconds
+            value: 30
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/test/helm/ingress_tests.yaml b/alfa-client/libs/design-system/test/helm/ingress_tests.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a6d662510d9e6d214d958042372987813bffb840
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/ingress_tests.yaml
@@ -0,0 +1,101 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test ingress.yaml
+release:
+  name: storybook
+  namespace: sh-helm-test
+templates:
+  - templates/ingress.yaml
+set:  
+  ozgcloud:
+    bezeichner: helm
+  baseUrl: test.by.ozg-cloud.de
+
+tests:
+  - it: check ingress kind
+    asserts:
+      - isKind:
+          of: Ingress
+  - it: should create ingress tls
+    asserts:
+      - equal:
+          path: spec.tls[0].secretName
+          value: helm-storybook-tls
+
+  - it: should not create ingress tls/ingressClass
+    set:
+      cluster_env: dataport
+    asserts:
+      - isNull:
+          path: spec.ingressClassName
+      - isNull:
+          path: spec.tls[0].secretName
+  
+  - it: should use default letsencrypt-prod cluster-issuer
+    asserts:
+      - equal:
+          path: metadata.annotations["cert-manager.io/cluster-issuer"]
+          value: letsencrypt-prod
+
+  - it: should use letsencrypt-staging cluster-issuer
+    set:
+      ingress.use_staging_cert: true
+    asserts:
+      - equal:
+          path: metadata.annotations["cert-manager.io/cluster-issuer"]
+          value: letsencrypt-staging
+
+  - it: should use letsencrypt-prod cluster-issuer
+    set:
+      ingress.use_staging_cert: false
+    asserts:
+      - equal:
+          path: metadata.annotations["cert-manager.io/cluster-issuer"]
+          value: letsencrypt-prod
+
+  - it: should create tls hosts name correctly
+    asserts:
+      - equal:
+          path: spec.tls[0].hosts[0]
+          value: helm.test.by.ozg-cloud.de
+
+
+      - equal:
+          path: spec.rules[0].http.paths[0]
+          value: 
+              path: /
+              pathType: Prefix
+              backend:
+                service:
+                  name: storybook
+                  port: 
+                    number: 8080
+      
+
+  - it: should set hostname
+    asserts:
+      - equal:
+          path: spec.rules[0].host
+          value: helm.test.by.ozg-cloud.de
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/test/helm/network_policy_test.yaml b/alfa-client/libs/design-system/test/helm/network_policy_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7820c1acdcdfafa48427c049c6292757ba2ae6f5
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/network_policy_test.yaml
@@ -0,0 +1,179 @@
+#
+# Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: network policy storybook test
+release:
+  name: storybook
+  namespace: by-helm-test
+templates:
+  - templates/network_policy.yaml
+
+tests:
+  - it: should match apiVersion
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
+    asserts:
+      - isAPIVersion:
+          of: networking.k8s.io/v1
+  - it: should match kind
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
+    asserts:
+      - isKind:
+          of: NetworkPolicy
+  - it: validate metadata
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
+    asserts:
+      - equal:
+          path: metadata
+          value:
+            name: network-policy-storybook
+            namespace: by-helm-test
+
+
+  - it: should add egress rule to dns service
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+    asserts:
+      - contains:
+          path: spec.egress
+          content:
+              to:
+              - namespaceSelector:
+                  matchLabels:
+                    kubernetes.io/metadata.name: test-dns-namespace
+              ports:
+                - port: 53
+                  protocol: UDP
+                - port: 53
+                  protocol: TCP
+                - port: 5353
+                  protocol: UDP
+                - port: 5353
+                  protocol: TCP
+
+  - it: should add additionalIngressConfig local
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-namespace-dns
+        additionalIngressConfigLocal:
+        - from:
+          - podSelector: 
+              matchLabels:
+                component: client2
+    asserts:
+      - contains:
+          path: spec.ingress
+          content:
+            from:
+            - podSelector: 
+                matchLabels:
+                  component: client2
+  - it: should add additionalIngressConfig global
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-namespace-dns
+        additionalIngressConfigGlobal:
+        - from:
+          - podSelector: 
+              matchLabels:
+                component: client2
+    asserts:
+      - contains:
+          path: spec.ingress
+          content:
+            from:
+            - podSelector: 
+                matchLabels:
+                  component: client2
+
+  - it: should add additionalEgressConfig local
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+        additionalEgressConfigLocal:
+        - to:
+          - ipBlock:
+              cidr: 1.2.3.4/32
+    asserts:
+    - contains:
+        path: spec.egress
+        content:
+          to:
+          - ipBlock:
+              cidr: 1.2.3.4/32
+
+  - it: should add additionalEgressConfig global
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-namespace
+        additionalEgressConfigGlobal:
+        - to:
+          - ipBlock:
+              cidr: 1.2.3.4/32
+    asserts:
+    - contains:
+        path: spec.egress
+        content:
+          to:
+          - ipBlock:
+              cidr: 1.2.3.4/32
+
+
+  - it: test network policy disabled
+    set:
+      networkPolicy:
+        disabled: true
+    asserts:
+      - hasDocuments:
+          count: 0
+
+  - it: test network policy unset should be disabled
+    set:
+      networkPolicy:
+        disabled: false
+        dnsServerNamespace: test-dns-server-namespace
+    asserts:
+      - hasDocuments:
+          count: 1
+  - it: test network policy dnsServerNamespace must be set message
+    set:
+      networkPolicy:
+        disabled: false
+    asserts:
+      - failedTemplate:
+          errorMessage: networkPolicy.dnsServerNamespace must be set
+
+  - it: test network policy should be enabled by default
+    set:
+      networkPolicy:
+        dnsServerNamespace: test-dns-server-namespace
+    asserts:
+      - hasDocuments:
+          count: 1
\ No newline at end of file
diff --git a/alfa-client/libs/design-system/test/helm/service_test.yaml b/alfa-client/libs/design-system/test/helm/service_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fd3ae830b640f34e4540828d884dd4fb0aa2df46
--- /dev/null
+++ b/alfa-client/libs/design-system/test/helm/service_test.yaml
@@ -0,0 +1,66 @@
+#
+# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
+# Ministerpräsidenten des Landes Schleswig-Holstein
+# Staatskanzlei
+# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+#
+# Lizenziert unter der EUPL, Version 1.2 oder - sobald
+# diese von der Europäischen Kommission genehmigt wurden -
+# Folgeversionen der EUPL ("Lizenz");
+# Sie dürfen dieses Werk ausschließlich gemäß
+# dieser Lizenz nutzen.
+# Eine Kopie der Lizenz finden Sie hier:
+#
+# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+#
+# Sofern nicht durch anwendbare Rechtsvorschriften
+# gefordert oder in schriftlicher Form vereinbart, wird
+# die unter der Lizenz verbreitete Software "so wie sie
+# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+# ausdrücklich oder stillschweigend - verbreitet.
+# Die sprachspezifischen Genehmigungen und Beschränkungen
+# unter der Lizenz sind dem Lizenztext zu entnehmen.
+#
+
+suite: test service
+release:
+  name: storybook
+  namespace: sh-helm-test
+templates:
+  - templates/service.yaml
+tests:
+  - it: should have the label component with correct value 
+    asserts:
+      - isKind:
+          of: Service
+      - isAPIVersion:
+           of: v1
+      - equal:
+          path: metadata.labels.component
+          value: storybook-service
+  - it: should be of type ClusterIP
+    asserts:
+      - equal:
+          path: spec.type
+          value: ClusterIP
+
+  - it: selector should contain the component label with correct value
+    asserts:
+      - equal:
+          path: spec.selector.component
+          value: storybook
+
+  - it: selector should contain helm recommended labels name and namespace
+    asserts:
+      - equal:
+          path: spec.selector
+          value:
+            app.kubernetes.io/name: storybook
+            app.kubernetes.io/namespace: sh-helm-test
+            component: storybook
+
+  - it: check component label for service
+    asserts:
+      - equal:
+          path: metadata.labels["component"]
+          value: storybook-service
\ No newline at end of file
diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.model.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.model.ts
index 3155c2596134d40deb75c95edad1f86b3a3b9816..f0c5a719ce32a08dafa05c712c5ad694d4a9dc71 100644
--- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.model.ts
+++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.model.ts
@@ -21,7 +21,6 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { CreateCommand } from '@alfa-client/command-shared';
 import { ListResource } from '@alfa-client/tech-shared';
 import { Resource, ResourceUri } from '@ngxp/rest';
 
@@ -34,7 +33,3 @@ export interface Kommentar {
 
 export interface KommentarResource extends Kommentar, Resource {}
 export interface KommentarListResource extends ListResource {}
-
-export interface CreateKommentarCommand extends CreateCommand {
-  kommentar: Kommentar;
-}
diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts
index 0478aadb64501cee92b4900b6275eb8cd122a96d..a7bff9a03fa653434c6ae6b0627e3decce20c587 100644
--- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts
+++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts
@@ -22,14 +22,19 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BinaryFileService } from '@alfa-client/binary-file-shared';
-import { CommandOrder, CommandResource, CommandService } from '@alfa-client/command-shared';
+import {
+  CommandOrder,
+  CommandResource,
+  CommandService,
+  CreateCommand,
+} from '@alfa-client/command-shared';
 import { NavigationService } from '@alfa-client/navigation-shared';
 import {
+  StateResource,
   createEmptyStateResource,
   createStateResource,
-  StateResource,
 } from '@alfa-client/tech-shared';
-import { mock, Mock, useFromMock } from '@alfa-client/test-utils';
+import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
 import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { cold, hot } from 'jest-marbles';
 import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel';
@@ -42,12 +47,7 @@ import {
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { of } from 'rxjs';
 import { KommentarLinkRel, KommentarListLinkRel } from './kommentar.linkrel';
-import {
-  CreateKommentarCommand,
-  Kommentar,
-  KommentarListResource,
-  KommentarResource,
-} from './kommentar.model';
+import { Kommentar, KommentarListResource, KommentarResource } from './kommentar.model';
 import { KommentarRepository } from './kommentar.repository';
 import { KommentarService } from './kommentar.service';
 
@@ -158,9 +158,9 @@ describe('KommentarService', () => {
       });
 
       it('should create CreateKommentarCommand', () => {
-        var command: CreateKommentarCommand = service.createCreateKommentarCommand(kommentar);
+        var command: CreateCommand = service.createCreateKommentarCommand(kommentar);
 
-        expect(command).toEqual({ order: CommandOrder.CREATE_KOMMENTAR, kommentar, body: null });
+        expect(command).toEqual({ order: CommandOrder.CREATE_KOMMENTAR, body: kommentar });
       });
     });
   });
@@ -212,9 +212,9 @@ describe('KommentarService', () => {
       });
 
       it('should create CreateKommentarCommand', () => {
-        var command: CreateKommentarCommand = service.createEditKommentarCommand(kommentar);
+        var command: CreateCommand = service.createEditKommentarCommand(kommentar);
 
-        expect(command).toEqual({ order: CommandOrder.EDIT_KOMMENTAR, kommentar, body: null });
+        expect(command).toEqual({ order: CommandOrder.EDIT_KOMMENTAR, body: kommentar });
       });
     });
   });
diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts
index b1be2ecc5b41cd6504ea878f9297ea4ecc1a7099..1e183c3c45934214bd145fd8c28a6606eb563dd9 100644
--- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts
+++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts
@@ -21,8 +21,6 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable } from '@angular/core';
-import { Params } from '@angular/router';
 import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared';
 import {
   CommandOrder,
@@ -33,23 +31,20 @@ import {
 } from '@alfa-client/command-shared';
 import { NavigationService } from '@alfa-client/navigation-shared';
 import {
+  StateResource,
   createEmptyStateResource,
   createStateResource,
   doIfLoadingRequired,
-  StateResource,
 } from '@alfa-client/tech-shared';
 import { VorgangResource, VorgangService } from '@alfa-client/vorgang-shared';
-import { hasLink, Resource } from '@ngxp/rest';
+import { Injectable } from '@angular/core';
+import { Params } from '@angular/router';
+import { Resource, hasLink } from '@ngxp/rest';
 import { isNil } from 'lodash-es';
-import { BehaviorSubject, Observable, of, Subscription } from 'rxjs';
+import { BehaviorSubject, Observable, Subscription, of } from 'rxjs';
 import { map, startWith, tap } from 'rxjs/operators';
 import { KommentarLinkRel, KommentarListLinkRel } from './kommentar.linkrel';
-import {
-  CreateKommentarCommand,
-  Kommentar,
-  KommentarListResource,
-  KommentarResource,
-} from './kommentar.model';
+import { Kommentar, KommentarListResource, KommentarResource } from './kommentar.model';
 import { KommentarRepository } from './kommentar.repository';
 
 @Injectable({ providedIn: 'root' })
@@ -154,8 +149,8 @@ export class KommentarService {
     );
   }
 
-  createCreateKommentarCommand(kommentar: Kommentar): CreateKommentarCommand {
-    return { order: CommandOrder.CREATE_KOMMENTAR, kommentar, body: null };
+  createCreateKommentarCommand(kommentar: Kommentar): CreateCommand {
+    return { order: CommandOrder.CREATE_KOMMENTAR, body: kommentar };
   }
 
   public editKommentar(
@@ -169,8 +164,8 @@ export class KommentarService {
     );
   }
 
-  createEditKommentarCommand(kommentar: Kommentar): CreateKommentarCommand {
-    return { order: CommandOrder.EDIT_KOMMENTAR, kommentar, body: null };
+  createEditKommentarCommand(kommentar: Kommentar): CreateCommand {
+    return { order: CommandOrder.EDIT_KOMMENTAR, body: kommentar };
   }
 
   createKommentarCommand(
diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.html
index 05831b3b1608abfbd8d66d39c61a4e4e929e8775..a06ec149adf4dcaf0ed23c913dba68d720bbdfbb 100644
--- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.html
+++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.html
@@ -23,5 +23,5 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<alfa-vertical-binary-file-list [fileListResource]="attachments$ | async">
+<alfa-vertical-binary-file-list [binaryFileListStateResource]="attachments$ | async">
 </alfa-vertical-binary-file-list>
diff --git a/alfa-client/libs/tech-shared/src/lib/error/error.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/error/error.util.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..118b8869a0f9a95cba5d73c84b0eb6be5f94bfb8
--- /dev/null
+++ b/alfa-client/libs/tech-shared/src/lib/error/error.util.spec.ts
@@ -0,0 +1,132 @@
+import { HttpErrorResponse } from '@angular/common/http';
+import { createApiError, createHttpErrorResponse, createIssue } from 'libs/tech-shared/test/error';
+import { MessageCode } from '../message-code';
+import { ApiError, Issue } from '../tech.model';
+import {
+  getApiErrorFromHttpErrorResponse,
+  isApiError,
+  isNotApiError,
+  isResourceNotFoundError,
+  isServiceUnavailableMessageCode,
+} from './error.util';
+
+describe('error.util', () => {
+  describe('isApiError', () => {
+    it('should return true if parameter is ApiError', () => {
+      const apiError: ApiError = createApiError();
+
+      const result: boolean = isApiError(apiError);
+
+      expect(result).toBeTruthy();
+    });
+
+    it('should return false if empty ApiError.Issues property', () => {
+      const apiError: ApiError = createApiError([]);
+
+      const result: boolean = isApiError(apiError);
+
+      expect(result).toBeFalsy();
+    });
+
+    it('should return false if parameter is no ApiError', () => {
+      const httpErrorResponse: HttpErrorResponse = createHttpErrorResponse();
+
+      const result: boolean = isApiError(httpErrorResponse);
+
+      expect(result).toBeFalsy();
+    });
+  });
+
+  describe('isNotApiError', () => {
+    it('should return true if parameter is no ApiError', () => {
+      const result: boolean = isNotApiError(createHttpErrorResponse());
+
+      expect(result).toBeTruthy();
+    });
+
+    it('should return false if parameter is ApiError', () => {
+      const issue: Issue = createIssue();
+      const apiError: ApiError = createApiError([issue]);
+
+      const result: boolean = isNotApiError(apiError);
+
+      expect(result).toBeFalsy();
+    });
+  });
+
+  describe('isServiceUnavailableMessageCode', () => {
+    it('should return true if SERVICE_UNAVAILABLE error code', () => {
+      const issue: Issue = { ...createIssue(), messageCode: MessageCode.SERVICE_UNAVAILABLE };
+      const apiError: ApiError = createApiError([issue]);
+
+      const result: boolean = isServiceUnavailableMessageCode(apiError);
+
+      expect(result).toBeTruthy();
+    });
+
+    it('should return false if not SERVICE_UNAVAILABLE error code', () => {
+      const issue: Issue = createIssue();
+      const apiError: ApiError = createApiError([issue]);
+
+      const result: boolean = isServiceUnavailableMessageCode(apiError);
+
+      expect(result).toBeFalsy();
+    });
+
+    it('should return false if input parameter is no ApiError', () => {
+      const httpErrorResponse: HttpErrorResponse = new HttpErrorResponse({});
+
+      const result: boolean = isServiceUnavailableMessageCode(httpErrorResponse);
+
+      expect(result).toBeFalsy();
+    });
+  });
+
+  describe('isResourceNotFoundError', () => {
+    it('should return true if RESOURCE_NOT_FOUND error code', () => {
+      const issue: Issue = { ...createIssue(), messageCode: MessageCode.RESOURCE_NOT_FOUND };
+      const apiError: ApiError = createApiError([issue]);
+
+      const result: boolean = isResourceNotFoundError(apiError);
+
+      expect(result).toBeTruthy();
+    });
+
+    it('should return false if not RESOURCE_NOT_FOUND error code', () => {
+      const issue: Issue = createIssue();
+      const apiError: ApiError = createApiError([issue]);
+
+      const result: boolean = isResourceNotFoundError(apiError);
+
+      expect(result).toBeFalsy();
+    });
+
+    it('should return false if input parameter is no ApiError', () => {
+      const httpErrorResponse: HttpErrorResponse = new HttpErrorResponse({});
+
+      const result: boolean = isResourceNotFoundError(httpErrorResponse);
+
+      expect(result).toBeFalsy();
+    });
+  });
+
+  describe('getApiErrorFromHttpErrorResponse', () => {
+    it('should return ApiError', () => {
+      const issue: Issue = createIssue();
+      const apiError: ApiError = createApiError([issue]);
+      const httpErrorResponse: HttpErrorResponse = createHttpErrorResponse(apiError);
+
+      const result: ApiError = getApiErrorFromHttpErrorResponse(httpErrorResponse);
+
+      expect(result).toBe(apiError);
+    });
+
+    it('should return undefined if no ApiError', () => {
+      const httpErrorResponse: HttpErrorResponse = new HttpErrorResponse({});
+
+      const result: ApiError = getApiErrorFromHttpErrorResponse(httpErrorResponse);
+
+      expect(result).toBeUndefined();
+    });
+  });
+});
diff --git a/alfa-client/libs/tech-shared/src/lib/error/error.util.ts b/alfa-client/libs/tech-shared/src/lib/error/error.util.ts
index 81c2a8d62e817d5e4907c194bf9dd62bfa2fd3a1..00271229b4f5fe102b8ebb7ebe92d43a55465d3d 100644
--- a/alfa-client/libs/tech-shared/src/lib/error/error.util.ts
+++ b/alfa-client/libs/tech-shared/src/lib/error/error.util.ts
@@ -22,16 +22,32 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { HttpErrorResponse } from '@angular/common/http';
-import { isNil } from 'lodash-es';
+import { has } from 'lodash-es';
 import { MessageCode } from '../message-code';
-import { ApiError, HttpError } from '../tech.model';
+import { ApiError } from '../tech.model';
 
-export function isApiError(value: any): boolean {
-  return !isNil(value?.issues) && !isNil(value.issues[0]);
+export function isApiError(error: unknown): boolean {
+  return has(error, 'issues[0]');
 }
 
-export function isServiceUnavailableMessageCode(error: ApiError): boolean {
-  return error.issues[0].messageCode == MessageCode.SERVICE_UNAVAILABLE;
+export function isNotApiError(error: unknown): boolean {
+  return !isApiError(error);
+}
+
+export function isServiceUnavailableMessageCode(error: unknown): boolean {
+  if (isNotApiError(error)) {
+    return false;
+  }
+
+  return (error as ApiError).issues[0].messageCode === MessageCode.SERVICE_UNAVAILABLE;
+}
+
+export function isResourceNotFoundError(error: unknown): boolean {
+  if (isNotApiError(error)) {
+    return false;
+  }
+
+  return (error as ApiError).issues[0].messageCode === MessageCode.RESOURCE_NOT_FOUND;
 }
 
 export function getApiErrorFromHttpErrorResponse(httpErrorResponse: HttpErrorResponse): ApiError {
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.spec.ts
index e7ff1676a507c878018db9eb3cc4e1de38b2d972..10709bf89427a487644c718947970ac429a1a6ba 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.spec.ts
@@ -2,32 +2,31 @@ import { Resource } from '@ngxp/rest';
 import { createDummyResource } from 'libs/tech-shared/test/resource';
 import { HasAnyLinkPipe } from './has-any-link.pipe';
 
+import * as TechUtil from '../tech.util';
+
 describe('HasAnyLinkPipe', () => {
   const oneLink: string = 'one';
   const anotherLink: string = 'another';
   const resource: Resource = createDummyResource([oneLink, anotherLink]);
   const pipe: HasAnyLinkPipe = new HasAnyLinkPipe();
 
-  it('should return true if resource has at least on link', () => {
-    const result: boolean = pipe.transform(resource, oneLink, 'notExists');
+  describe('transform', () => {
+    let hasAnyLinkSpy: jest.SpyInstance<boolean>;
 
-    expect(result).toBe(true);
-  });
-  it('resource return true if resoure has multiple links', () => {
-    const result: boolean = pipe.transform(resource, oneLink, anotherLink);
+    beforeEach(() => {
+      hasAnyLinkSpy = jest.spyOn(TechUtil, 'hasAnyLink').mockReturnValue(true);
+    });
 
-    expect(result).toBe(true);
-  });
+    it('should call has any link', () => {
+      pipe.transform(resource, oneLink);
 
-  it('should return false if resource has no of given links', () => {
-    const result: boolean = pipe.transform(resource, 'notExists', 'notExistsToo');
-
-    expect(result).toBe(false);
-  });
+      expect(hasAnyLinkSpy).toHaveBeenCalledWith(resource, oneLink);
+    });
 
-  it('should return false if resource is null', () => {
-    const result: boolean = pipe.transform(null, 'notExists', 'notExistsToo');
+    it('should return value', () => {
+      const result: boolean = pipe.transform(resource, oneLink, anotherLink);
 
-    expect(result).toBe(false);
+      expect(result).toBe(true);
+    });
   });
 });
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts
index a6627c5fd1072763525025f304082f42749be211..b2827a5cbad9d558ed5666ed506cb9cfa38411ea 100644
--- a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts
@@ -1,12 +1,11 @@
 import { Pipe, PipeTransform } from '@angular/core';
-import { hasLink, Resource } from '@ngxp/rest';
-import { isEmpty } from 'lodash-es';
+import { Resource } from '@ngxp/rest';
+import { LinkRelationName } from '../resource/resource.model';
+import { hasAnyLink } from '../tech.util';
 
 @Pipe({ name: 'hasAnyLink' })
 export class HasAnyLinkPipe implements PipeTransform {
-  transform(resource: Resource, ...links: string[]) {
-    return !isEmpty(
-      links.map((link) => hasLink(resource, link)).filter((hasLink) => hasLink === true),
-    );
+  transform(resource: Resource, ...links: LinkRelationName[]): boolean {
+    return hasAnyLink(resource, ...links);
   }
 }
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c3353c6cdb3b8957c4c6ae71f849c4a504b700cd
--- /dev/null
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.spec.ts
@@ -0,0 +1,32 @@
+import { Resource } from '@ngxp/rest';
+import { createDummyResource } from 'libs/tech-shared/test/resource';
+import { NotHasAnyLinkPipe } from './not-has-any-link.pipe';
+
+import * as TechUtil from '../tech.util';
+
+describe('NotHasAnyLinkPipe', () => {
+  const oneLink: string = 'one';
+  const anotherLink: string = 'another';
+  const resource: Resource = createDummyResource([oneLink, anotherLink]);
+  const pipe: NotHasAnyLinkPipe = new NotHasAnyLinkPipe();
+
+  describe('transform', () => {
+    let notHasAnyLinkSpy: jest.SpyInstance<boolean>;
+
+    beforeEach(() => {
+      notHasAnyLinkSpy = jest.spyOn(TechUtil, 'notHasAnyLink').mockReturnValue(true);
+    });
+
+    it('should call not has any link', () => {
+      pipe.transform(resource, oneLink);
+
+      expect(notHasAnyLinkSpy).toHaveBeenCalledWith(resource, oneLink);
+    });
+
+    it('should return value', () => {
+      const result: boolean = pipe.transform(resource, oneLink, anotherLink);
+
+      expect(result).toBe(true);
+    });
+  });
+});
diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f207bca8edccd5f6229207b9cfb0c8d9204e3b92
--- /dev/null
+++ b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-any-link.pipe.ts
@@ -0,0 +1,11 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { Resource } from '@ngxp/rest';
+import { LinkRelationName } from '../resource/resource.model';
+import { notHasAnyLink } from '../tech.util';
+
+@Pipe({ name: 'notHasAnyLink' })
+export class NotHasAnyLinkPipe implements PipeTransform {
+  transform(resource: Resource, ...links: LinkRelationName[]): boolean {
+    return notHasAnyLink(resource, ...links);
+  }
+}
diff --git a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts b/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts
index ecb138d23695a7111038967cf2d80147cbac5206..331031b298487fcfa77df7c10041a33cfedec7bb 100644
--- a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts
+++ b/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts
@@ -40,6 +40,7 @@ import { FormatToPrettyDatePipe } from './pipe/format-to-pretty-date.pipe';
 import { GetUrlPipe } from './pipe/get-url.pipe';
 import { HasAnyLinkPipe } from './pipe/has-any-link.pipe';
 import { HasLinkPipe } from './pipe/has-link.pipe';
+import { NotHasAnyLinkPipe } from './pipe/not-has-any-link.pipe';
 import { NotHasLinkPipe } from './pipe/not-has-link.pipe';
 import { ToEmbeddedResourcesPipe } from './pipe/to-embedded-resource.pipe';
 import { ToResourceUriPipe } from './pipe/to-resource-uri.pipe';
@@ -57,6 +58,7 @@ import { ToTrafficLightPipe } from './pipe/to-traffic-light.pipe';
     HasLinkPipe,
     HasAnyLinkPipe,
     NotHasLinkPipe,
+    NotHasAnyLinkPipe,
     ToResourceUriPipe,
     ToTrafficLightPipe,
     ToTrafficLightTooltipPipe,
@@ -77,6 +79,7 @@ import { ToTrafficLightPipe } from './pipe/to-traffic-light.pipe';
     HasLinkPipe,
     HasAnyLinkPipe,
     NotHasLinkPipe,
+    NotHasAnyLinkPipe,
     ToResourceUriPipe,
     ToTrafficLightPipe,
     ToTrafficLightTooltipPipe,
diff --git a/alfa-client/libs/tech-shared/src/lib/tech.model.ts b/alfa-client/libs/tech-shared/src/lib/tech.model.ts
index 3d9ca01c2225d3550fd9b8832a8feac5a3b4e50e..c85852676e5184152aa17856cca07bd33b3a3223 100644
--- a/alfa-client/libs/tech-shared/src/lib/tech.model.ts
+++ b/alfa-client/libs/tech-shared/src/lib/tech.model.ts
@@ -68,6 +68,7 @@ export enum HttpMethod {
 export enum HttpHeader {
   ACCEPT = 'Accept',
   CONTENT_DISPOSITION = 'content-disposition',
+  LOCATION = 'Location',
 }
 
 export interface BlobWithFileName {
diff --git a/alfa-client/libs/tech-shared/src/lib/tech.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/tech.util.spec.ts
index 446e4961c800953f06a005d7a36c2eb2e643ef91..6184389586142f4acbdc09bb20ffe793ac3424ff 100644
--- a/alfa-client/libs/tech-shared/src/lib/tech.util.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/tech.util.spec.ts
@@ -23,6 +23,9 @@
  */
 
 import { faker } from '@faker-js/faker';
+import { Resource } from '@ngxp/rest';
+import { createDummyResource } from 'libs/tech-shared/test/resource';
+import { LinkRelationName } from './resource/resource.model';
 import {
   EMPTY_STRING,
   allEmpty,
@@ -32,11 +35,13 @@ import {
   encodeUrlForEmbedding,
   getFirstLetter,
   getStringValue,
+  hasAnyLink,
   hasContent,
   hasMinLength,
   isNotEmpty,
   isNotNil,
   isNotNull,
+  notHasAnyLink,
   replaceAllWhitespaces,
   replacePlaceholder,
   replacePlaceholders,
@@ -363,4 +368,50 @@ describe('TechUtil', () => {
       expect(value).toBeUndefined();
     });
   });
+
+  describe('has any link', () => {
+    const oneLink: string = 'one';
+    const anotherLink: string = 'another';
+    const resource: Resource = createDummyResource([oneLink, anotherLink]);
+
+    it('should return true if resource has at least on link', () => {
+      const result: boolean = hasAnyLink(resource, oneLink, 'notExists');
+
+      expect(result).toBe(true);
+    });
+
+    it('resource return true if resoure has multiple links', () => {
+      const result: boolean = hasAnyLink(resource, oneLink, anotherLink);
+
+      expect(result).toBe(true);
+    });
+
+    it('should return false if resource has no of given links', () => {
+      const result: boolean = hasAnyLink(resource, 'notExists', 'notExistsToo');
+
+      expect(result).toBe(false);
+    });
+
+    it('should return false if resource is null', () => {
+      const result: boolean = hasAnyLink(null, 'notExists', 'notExistsToo');
+
+      expect(result).toBe(false);
+    });
+  });
+
+  describe('not has any link', () => {
+    const link: LinkRelationName = 'one';
+    const otherLink: LinkRelationName = 'two';
+
+    it('should return false if at least one link exists', () => {
+      const result: boolean = notHasAnyLink(createDummyResource([link]), link, otherLink);
+
+      expect(result).toBe(false);
+    });
+    it('should return true if no link exists', () => {
+      const result: boolean = notHasAnyLink(createDummyResource(), link, otherLink);
+
+      expect(result).toBe(true);
+    });
+  });
 });
diff --git a/alfa-client/libs/tech-shared/src/lib/tech.util.ts b/alfa-client/libs/tech-shared/src/lib/tech.util.ts
index 0d227ab5dd449507c3b3b9da22b753c8d82f3799..55e881a99ac582741b7bea58ddde81b00c5c11b0 100644
--- a/alfa-client/libs/tech-shared/src/lib/tech.util.ts
+++ b/alfa-client/libs/tech-shared/src/lib/tech.util.ts
@@ -21,9 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { Resource, hasLink } from '@ngxp/rest';
 import { Base64 } from 'js-base64';
 import { isEmpty, isNil, isNull, isUndefined } from 'lodash-es';
 import { sanitize } from 'sanitize-filename-ts';
+import { LinkRelationName } from './resource/resource.model';
 import { ApiError } from './tech.model';
 
 export const EMPTY_STRING: string = '';
@@ -143,3 +145,15 @@ export function convertToBoolean(booleanStr: string): boolean {
 export function joinAndTrim(inputStrings: string[], delimiter: string = ' ') {
   return inputStrings.join(delimiter).trim();
 }
+
+export function notHasAnyLink(resource: Resource, ...links: LinkRelationName[]): boolean {
+  return !hasAnyLink(resource, ...links);
+}
+
+export function hasAnyLink(resource: Resource, ...links: LinkRelationName[]): boolean {
+  return !isEmpty(
+    links
+      .map((link: LinkRelationName) => hasLink(resource, link))
+      .filter((hasLink: boolean) => hasLink === true),
+  );
+}
diff --git a/alfa-client/libs/ui/src/index.ts b/alfa-client/libs/ui/src/index.ts
index 4a57b047ecb1d1e9bd7fc7a6a85bbca76fb12447..18cbad77e78dfb553c9cc351c0f6a084446b41a0 100644
--- a/alfa-client/libs/ui/src/index.ts
+++ b/alfa-client/libs/ui/src/index.ts
@@ -37,7 +37,6 @@ export * from './lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.model';
 export * from './lib/ui/editor/date-editor/date-editor.component';
 export * from './lib/ui/editor/enum-editor/enum-editor.component';
 export * from './lib/ui/editor/enum-editor/enum-editor.model';
-export * from './lib/ui/editor/formcontrol-editor.abstract.component';
 export * from './lib/ui/editor/text-editor/text-editor.component';
 export * from './lib/ui/editor/textarea-editor/textarea-editor.component';
 export * from './lib/ui/expansion-panel/expansion-panel.component';
diff --git a/alfa-client/libs/ui/src/lib/assets/update.svg b/alfa-client/libs/ui/src/lib/assets/update.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1eb6a0751c7673b2de4a52c06aba58f191f32570
--- /dev/null
+++ b/alfa-client/libs/ui/src/lib/assets/update.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="M480-120q-75 0-140.5-28.5t-114-77q-48.5-48.5-77-114T120-480q0-75 28.5-140.5t77-114q48.5-48.5 114-77T480-840q82 0 155.5 35T760-706v-94h80v240H600v-80h110q-41-56-101-88t-129-32q-117 0-198.5 81.5T200-480q0 117 81.5 198.5T480-200q105 0 183.5-68T756-440h82q-15 137-117.5 228.5T480-120Zm112-192L440-464v-216h80v184l128 128-56 56Z"/></svg>
\ No newline at end of file
diff --git a/alfa-client/libs/ui/src/lib/icon/icon.model.ts b/alfa-client/libs/ui/src/lib/icon/icon.model.ts
index a7b7d26ba85860a97d0977b9a1d2cdfa2bca0a43..a7fa9937a697357073f444068efd1e352271a745 100644
--- a/alfa-client/libs/ui/src/lib/icon/icon.model.ts
+++ b/alfa-client/libs/ui/src/lib/icon/icon.model.ts
@@ -43,4 +43,5 @@ export enum Icons {
   VORGANG_VORPRUEFEN = 'vorgang_vorpruefen',
   XDOMEA = 'xdomea_file',
   PASTE_FROM_CLIPBOARD = 'paste_from_clipboard',
+  UPDATE = 'update',
 }
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts
index 814dc618b5a9b4cd8d9d0e9fd1f7690110e7d495..99a9eb92b61246dbcc5ded540b949153ffea8a2f 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts
@@ -31,8 +31,8 @@ import {
   ViewChild,
 } from '@angular/core';
 import { ResourceUri } from '@ngxp/rest';
+import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 import { isEmpty, isEqual, isNil } from 'lodash-es';
-import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 
 @Component({
   selector: 'ozgcloud-autocomplete-editor',
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts
index d896c82a1626ffd500382b34f58481fd1a794124..0d76de506f2b3e1a7114b0984a780bed9f505fd8 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts
@@ -1,7 +1,7 @@
 import { Component, Input, OnInit } from '@angular/core';
-import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
-import { CheckboxEnumEditorItem } from './checkbox-enum-editor.model';
 import { MatCheckboxChange } from '@angular/material/checkbox';
+import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
+import { CheckboxEnumEditorItem } from './checkbox-enum-editor.model';
 
 /**
  * Ein Checkbox, dessen Wert beim FormControl statt boolean als string aus dem enum editor item
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts
index 27619ab5f03eb534053f871ae817dcacd07f5fe3..ea6c64bf12eff1271c4c2ac016bd73333e9e6308 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts
@@ -25,7 +25,7 @@ import { add2000Years } from '@alfa-client/tech-shared';
 import { Component, Input } from '@angular/core';
 import { MatDatepickerInputEvent } from '@angular/material/datepicker';
 import { isDate } from 'date-fns';
-import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
+import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 
 @Component({
   selector: 'ozgcloud-date-editor',
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.ts
index 58a4a6f3413d95da58da14ec6b0cf0126eecfa76..4e4451f0621feb2c6c1472eedd2d18f27a2da348 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Component, Input, OnInit } from '@angular/core';
-import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
+import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 import { EnumEditorItem } from './enum-editor.model';
 
 @Component({
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts
index 172a8deb368e10e86648c95cd7ddb40d18d51d86..5e9fde7e1eb22fb4ec2929181c3bd122693f7558 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts
@@ -21,6 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { StateResource } from '@alfa-client/tech-shared';
 import {
   Component,
   ElementRef,
@@ -33,13 +34,12 @@ import {
 } from '@angular/core';
 import {
   ControlContainer,
+  FormGroupDirective,
   UntypedFormArray,
   UntypedFormControl,
-  FormGroupDirective,
 } from '@angular/forms';
-import { StateResource } from '@alfa-client/tech-shared';
+import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 import { uniqueId } from 'lodash-es';
-import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 
 @Component({
   selector: 'ozgcloud-file-upload-editor',
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts
index 017dab82a8ba476c585b0af20b9f7c3080e0ff7b..5bb6b3a96e9f06d8770c527bd80dd202b9c3e06c 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts
@@ -24,8 +24,8 @@
 import { hasContent } from '@alfa-client/tech-shared';
 import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
 import { SubscriptSizing } from '@angular/material/form-field';
+import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 import { Observable, map, startWith } from 'rxjs';
-import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 
 @Component({
   selector: 'ozgcloud-text-editor',
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts
index ff008c8ba924f7ff54291ecf8f0130bda01aeea5..12d1e2d4906205137a55508042d63b95c9a7e857 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts
@@ -23,7 +23,7 @@
  */
 import { CdkTextareaAutosize } from '@angular/cdk/text-field';
 import { AfterViewInit, Component, Input, ViewChild } from '@angular/core';
-import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
+import { FormControlEditorAbstractComponent } from 'libs/design-component/src/lib/form/formcontrol-editor.abstract.component';
 
 @Component({
   selector: 'ozgcloud-textarea-editor',
diff --git a/alfa-client/libs/ui/src/lib/ui/messages.ts b/alfa-client/libs/ui/src/lib/ui/messages.ts
index 35f77d1e3c0b4cb1134b96853eaead712319de2b..49891db3e6afb98e20be5f33e612a2054bb2f41b 100644
--- a/alfa-client/libs/ui/src/lib/ui/messages.ts
+++ b/alfa-client/libs/ui/src/lib/ui/messages.ts
@@ -22,6 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 export enum Messages {
-  HTTP_STATUS_FORBIDDEN = 'Die Aktion konnte wegen fehlender Berechtigungen nicht durchgeführt werden',
+  HTTP_STATUS_FORBIDDEN = 'Die Aktion konnte wegen fehlender Berechtigungen nicht durchgeführt werden.',
   HTTP_USER_MANAGER_SERVICE_UNAVAILABLE = 'Der UserManager ist zurzeit leider nicht verfügbar.',
+  HTTP_STATUS_VORGANG_NOT_FOUND = 'Der aufgerufene Vorgang wurde nicht gefunden.',
 }
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
index 6e6bc3d6944283627afe1d9044ec8111e9575742..27769a03b7ebd03c1db3a8ad50ee02d5b5ce9a69 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
@@ -10,6 +10,7 @@ export class OzgcloudDialogService {
   readonly WIZARD_DIALOG_CONFIG: DialogConfig = {
     width: '1000px',
     restoreFocus: false,
+    disableClose: true,
   };
 
   constructor(private dialog: Dialog) {}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.html
deleted file mode 100644
index 0c6b5172652511b4c53e0ace77438a6a55b0728a..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
-
--->
-<alfa-vertical-binary-file-list
-  [fileListResource]="fileListResource$ | async"
-  [downloadFileNamePrefix]="vorgangWithEingang.nummer"
->
-</alfa-vertical-binary-file-list>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.scss
deleted file mode 100644
index 9a08a5aabce6cc4cdbb268c4190a8d67f82f19e5..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.spec.ts
deleted file mode 100644
index a9ec25ceade2c4416584d658de61791a3db9c645..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.spec.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { VerticalBinaryFileListComponent } from '@alfa-client/binary-file';
-import { mock } from '@alfa-client/test-utils';
-import {
-  VorgangService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
-import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
-import { MockComponent } from 'ng-mocks';
-import { VorgangDetailAttachmentListComponent } from './vorgang-detail-attachment-list.component';
-
-describe('VorgangDetailAttachmentListComponent', () => {
-  let component: VorgangDetailAttachmentListComponent;
-  let fixture: ComponentFixture<VorgangDetailAttachmentListComponent>;
-
-  const vorgangService = mock(VorgangService);
-  const vorgangWithAttachments: VorgangWithEingangResource = createVorgangWithEingangResource([
-    VorgangWithEingangLinkRel.ATTACHMENTS,
-  ]);
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [
-        VorgangDetailAttachmentListComponent,
-        MockComponent(VerticalBinaryFileListComponent),
-      ],
-      providers: [
-        {
-          provide: VorgangService,
-          useValue: vorgangService,
-        },
-      ],
-    }).compileComponents();
-  });
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(VorgangDetailAttachmentListComponent);
-    component = fixture.componentInstance;
-    component.vorgangWithEingang = createVorgangWithEingangResource();
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-
-  describe('on vorgang with "attachment" link', () => {
-    it('should call vorgangService methods', () => {
-      component.vorgangWithEingang = vorgangWithAttachments;
-
-      component.ngOnInit();
-
-      expect(vorgangService.getAttachments).toHaveBeenCalled();
-    });
-  });
-});
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.ts
deleted file mode 100644
index f1d39c242772553f9b49f790df9b3220d3afea05..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { Component, Input, OnInit } from '@angular/core';
-import { BinaryFileListResource } from '@alfa-client/binary-file-shared';
-import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
-import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
-import { Observable, of } from 'rxjs';
-
-@Component({
-  selector: 'alfa-vorgang-detail-attachment-list',
-  templateUrl: './vorgang-detail-attachment-list.component.html',
-  styleUrls: ['./vorgang-detail-attachment-list.component.scss'],
-})
-export class VorgangDetailAttachmentListComponent implements OnInit {
-  @Input() vorgangWithEingang: VorgangWithEingangResource;
-
-  fileListResource$: Observable<StateResource<BinaryFileListResource>> = of(
-    createEmptyStateResource<BinaryFileListResource>(),
-  );
-
-  constructor(private vorgangService: VorgangService) {}
-
-  ngOnInit(): void {
-    this.fileListResource$ = this.vorgangService.getAttachments();
-  }
-}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..085d1d818ee3dbe414ea74dde833aa1ce01366c7
--- /dev/null
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.html
@@ -0,0 +1,29 @@
+<div class="flex w-full flex-col gap-6 py-4 xl:flex-row">
+  <div class="flex-1">
+    <ng-container
+      *ngIf="representationListStateResource$ | async as representationListStateResource"
+    >
+      <alfa-vertical-binary-file-list
+        *ngIf="representationListStateResource.resource"
+        title="Antrag"
+        data-test-id="representation-list"
+        [binaryFileListStateResource]="representationListStateResource"
+        [downloadFileNamePrefix]="downloadPrefix"
+      >
+      </alfa-vertical-binary-file-list>
+    </ng-container>
+  </div>
+  <div class="flex-1">
+    <ng-container *ngIf="attachmentListStateResource$ | async as attachmentListStateResource">
+      <alfa-vertical-binary-file-list
+        *ngIf="attachmentListStateResource.resource"
+        title="Anhänge"
+        data-test-id="attachment-list"
+        [binaryFileListStateResource]="attachmentListStateResource"
+        [downloadFileNamePrefix]="downloadPrefix"
+        [archiveDownloadUri]="attachmentsDownloadUri"
+      >
+      </alfa-vertical-binary-file-list>
+    </ng-container>
+  </div>
+</div>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..141729a2b4ec449a4746a6b97968e44bbf4f8499
--- /dev/null
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.spec.ts
@@ -0,0 +1,223 @@
+import { VerticalBinaryFileListComponent } from '@alfa-client/binary-file';
+import { BinaryFileListResource } from '@alfa-client/binary-file-shared';
+import { StateResource, createStateResource } from '@alfa-client/tech-shared';
+import { Mock, getDebugElementFromFixtureByCss, mock } from '@alfa-client/test-utils';
+import {
+  VorgangService,
+  VorgangWithEingangLinkRel,
+  VorgangWithEingangResource,
+} from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import faker from '@faker-js/faker';
+import { getUrl } from '@ngxp/rest';
+import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binary-file';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { VorgangDetailDateienContainerComponent } from './vorgang-detail-dateien-container.component';
+
+describe('VorgangDetailDateienContainerComponent', () => {
+  let component: VorgangDetailDateienContainerComponent;
+  let fixture: ComponentFixture<VorgangDetailDateienContainerComponent>;
+
+  const attachmentList: string = getDataTestIdOf('attachment-list');
+  const representationList: string = getDataTestIdOf('representation-list');
+
+  const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource();
+
+  const vorgangService: Mock<VorgangService> = mock(VorgangService);
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [VorgangDetailDateienContainerComponent],
+      declarations: [
+        VorgangDetailDateienContainerComponent,
+        MockComponent(VerticalBinaryFileListComponent),
+      ],
+      providers: [
+        {
+          provide: VorgangService,
+          useValue: vorgangService,
+        },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(VorgangDetailDateienContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should call handleVorgangChange on set new vorgang', () => {
+    component.handleVorgangChange = jest.fn();
+
+    component.vorgangWithEingang = createVorgangWithEingangResource();
+
+    expect(component.handleVorgangChange).toHaveBeenCalled();
+  });
+
+  describe('handle vorgang change', () => {
+    it('should set downloadPrefix', () => {
+      component.handleVorgangChange(vorgang);
+
+      expect(component.downloadPrefix).toEqual(vorgang.nummer);
+    });
+
+    it('should call handle attachements', () => {
+      component.handleAttachments = jest.fn();
+
+      component.handleVorgangChange(vorgang);
+
+      expect(component.handleAttachments).toHaveBeenCalledWith(vorgang);
+    });
+
+    it('should call get representations if exists', () => {
+      component.getRepresentationsIfExists = jest.fn();
+
+      component.handleVorgangChange(vorgang);
+
+      expect(component.getRepresentationsIfExists).toHaveBeenCalledWith(vorgang);
+    });
+  });
+
+  describe('get representations if exists', () => {
+    it('should call vorgangService if link exists', () => {
+      component.getRepresentationsIfExists(
+        createVorgangWithEingangResource([VorgangWithEingangLinkRel.REPRESENTATIONS]),
+      );
+
+      expect(vorgangService.getRepresentations).toHaveBeenCalled();
+    });
+  });
+
+  describe('handle attachments', () => {
+    it('should call set download uri', () => {
+      component.setAttachmentsDownloadUri = jest.fn();
+
+      component.handleAttachments(vorgang);
+
+      expect(component.setAttachmentsDownloadUri).toHaveBeenCalledWith(vorgang);
+    });
+
+    it('should call vorgangService methods', () => {
+      component.handleVorgangChange(
+        createVorgangWithEingangResource([VorgangWithEingangLinkRel.ATTACHMENTS]),
+      );
+
+      expect(vorgangService.getAttachments).toHaveBeenCalled();
+    });
+
+    it('should call get attachments if exists', () => {
+      component.getAttachmentsIfExists = jest.fn();
+
+      component.handleVorgangChange(vorgang);
+
+      expect(component.getAttachmentsIfExists).toHaveBeenCalledWith(vorgang);
+    });
+  });
+
+  describe('get attachments if exists', () => {
+    it('should call vorgangService if link exists', () => {
+      component.getAttachmentsIfExists(
+        createVorgangWithEingangResource([VorgangWithEingangLinkRel.ATTACHMENTS]),
+      );
+
+      expect(vorgangService.getAttachments).toHaveBeenCalled();
+    });
+  });
+
+  describe('download attachments link', () => {
+    it('should be set if exists', () => {
+      const vorganWithLink: VorgangWithEingangResource = createVorgangWithEingangResource([
+        VorgangWithEingangLinkRel.DOWNLOAD_ATTACHMENTS,
+      ]);
+
+      component.handleVorgangChange(vorganWithLink);
+
+      expect(component.attachmentsDownloadUri).toBe(
+        getUrl(vorganWithLink, VorgangWithEingangLinkRel.DOWNLOAD_ATTACHMENTS),
+      );
+    });
+
+    it('should NOT be set if missing', () => {
+      const vorganWithLink: VorgangWithEingangResource = createVorgangWithEingangResource();
+
+      component.handleVorgangChange(vorganWithLink);
+
+      expect(component.attachmentsDownloadUri).toBeUndefined();
+    });
+  });
+
+  describe('on existing attachments', () => {
+    describe('binary file list component should be called with', () => {
+      const binaryFileListResource: BinaryFileListResource = createBinaryFileListResource();
+      const binaryFileListStateResource: StateResource<BinaryFileListResource> =
+        createStateResource(binaryFileListResource);
+
+      beforeEach(() => {
+        component.attachmentListStateResource$ = of(binaryFileListStateResource);
+        fixture.detectChanges();
+      });
+
+      it('binaryFileListStateResource', () => {
+        const binaryFileListComp: VerticalBinaryFileListComponent =
+          getVerticalBinaryFileListComponent(attachmentList);
+        expect(binaryFileListComp.binaryFileListStateResource).toEqual(binaryFileListStateResource);
+      });
+
+      it('downloadFileNamePrefix', () => {
+        const binaryFileListComp: VerticalBinaryFileListComponent =
+          getVerticalBinaryFileListComponent(attachmentList);
+        expect(binaryFileListComp.downloadFileNamePrefix).toEqual(component.downloadPrefix);
+      });
+
+      it('archiveDownloadUri', () => {
+        component.attachmentsDownloadUri = faker.internet.url();
+
+        fixture.detectChanges();
+
+        const binaryFileListComp: VerticalBinaryFileListComponent =
+          getVerticalBinaryFileListComponent(attachmentList);
+        expect(binaryFileListComp.archiveDownloadUri).toEqual(component.attachmentsDownloadUri);
+      });
+    });
+  });
+
+  describe('On existing representations', () => {
+    describe('binary file list component should be called with', () => {
+      const binaryFileListResource: BinaryFileListResource = createBinaryFileListResource();
+      const binaryFileListStateResource: StateResource<BinaryFileListResource> =
+        createStateResource(binaryFileListResource);
+
+      beforeEach(() => {
+        component.representationListStateResource$ = of(binaryFileListStateResource);
+        fixture.detectChanges();
+      });
+
+      it('binaryFileListStateResource', () => {
+        const binaryFileListComp: VerticalBinaryFileListComponent =
+          getVerticalBinaryFileListComponent(representationList);
+        expect(binaryFileListComp.binaryFileListStateResource).toEqual(binaryFileListStateResource);
+      });
+
+      it('downloadFileNamePrefix', () => {
+        const binaryFileListComp: VerticalBinaryFileListComponent =
+          getVerticalBinaryFileListComponent(representationList);
+        expect(binaryFileListComp.downloadFileNamePrefix).toEqual(component.downloadPrefix);
+      });
+    });
+  });
+
+  function getVerticalBinaryFileListComponent(
+    dataTestIdElement: string,
+  ): VerticalBinaryFileListComponent {
+    return getDebugElementFromFixtureByCss(
+      fixture,
+      'alfa-vertical-binary-file-list' + dataTestIdElement,
+    ).componentInstance;
+  }
+});
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..55c4a9368bb1a8a89b0b1f8cecf7185682c2ccaf
--- /dev/null
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component.ts
@@ -0,0 +1,67 @@
+import { BinaryFileListResource } from '@alfa-client/binary-file-shared';
+import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import {
+  VorgangService,
+  VorgangWithEingangLinkRel,
+  VorgangWithEingangResource,
+} from '@alfa-client/vorgang-shared';
+import { Component, Input } from '@angular/core';
+import { getUrl, hasLink } from '@ngxp/rest';
+import { Observable, of } from 'rxjs';
+
+@Component({
+  selector: 'alfa-vorgang-detail-dateien-container',
+  templateUrl: './vorgang-detail-dateien-container.component.html',
+})
+export class VorgangDetailDateienContainerComponent {
+  @Input() set vorgangWithEingang(vorgangWithEingang: VorgangWithEingangResource) {
+    this.handleVorgangChange(vorgangWithEingang);
+  }
+
+  public attachmentListStateResource$: Observable<StateResource<BinaryFileListResource>> = of(
+    createEmptyStateResource<BinaryFileListResource>(),
+  );
+  public representationListStateResource$: Observable<StateResource<BinaryFileListResource>> = of(
+    createEmptyStateResource<BinaryFileListResource>(),
+  );
+
+  public downloadPrefix: string;
+  public attachmentsDownloadUri: string;
+
+  public readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel;
+
+  constructor(private vorgangService: VorgangService) {}
+
+  handleVorgangChange(vorgangWithEingang: VorgangWithEingangResource): void {
+    this.downloadPrefix = vorgangWithEingang.nummer;
+
+    this.handleAttachments(vorgangWithEingang);
+    this.getRepresentationsIfExists(vorgangWithEingang);
+  }
+
+  handleAttachments(vorgangWithEingang: VorgangWithEingangResource): void {
+    this.setAttachmentsDownloadUri(vorgangWithEingang);
+    this.getAttachmentsIfExists(vorgangWithEingang);
+  }
+
+  setAttachmentsDownloadUri(vorgangWithEingang: VorgangWithEingangResource): void {
+    if (hasLink(vorgangWithEingang, VorgangWithEingangLinkRel.DOWNLOAD_ATTACHMENTS)) {
+      this.attachmentsDownloadUri = getUrl(
+        vorgangWithEingang,
+        VorgangWithEingangLinkRel.DOWNLOAD_ATTACHMENTS,
+      );
+    }
+  }
+
+  getRepresentationsIfExists(vorgangWithEingang: VorgangWithEingangResource): void {
+    if (hasLink(vorgangWithEingang, VorgangWithEingangLinkRel.REPRESENTATIONS)) {
+      this.representationListStateResource$ = this.vorgangService.getRepresentations();
+    }
+  }
+
+  getAttachmentsIfExists(vorgangWithEingang: VorgangWithEingangResource): void {
+    if (hasLink(vorgangWithEingang, VorgangWithEingangLinkRel.ATTACHMENTS)) {
+      this.attachmentListStateResource$ = this.vorgangService.getAttachments();
+    }
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html
index fdb75c0c568b35de0627f2b6295459812f1d2b8f..1d4d2f566f9ea57e41318a3f59f7b40f0c19b308 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html
@@ -40,32 +40,20 @@
         [antragsData]="antragsData"
       ></alfa-vorgang-detail-antrag-data>
     </mat-tab>
-    <mat-tab label="Metadaten" [disabled]="!metaData">
-      <alfa-vorgang-detail-meta-data
-        data-test-id="tab-meta-data"
-        [metaData]="metaData"
-      ></alfa-vorgang-detail-meta-data>
-    </mat-tab>
-    <mat-tab
-      label="Datenrepräsentation ({{ vorgangWithEingang.eingang.numberOfRepresentations }})"
-      [disabled]="vorgangWithEingang | notHasLink: vorgangWithEingangLinkRel.REPRESENTATIONS"
-    >
-      <ng-template matTabContent>
-        <alfa-vorgang-detail-representation-list
-          data-test-id="tab-representations-list"
-          [vorgangWithEingang]="vorgangWithEingang"
-        ></alfa-vorgang-detail-representation-list>
-      </ng-template>
-    </mat-tab>
     <mat-tab
-      label="Anhänge ({{ vorgangWithEingang.eingang.numberOfAttachments }})"
-      [disabled]="vorgangWithEingang | notHasLink: vorgangWithEingangLinkRel.ATTACHMENTS"
+      label="Dateien ({{ filesNumber }})"
+      [disabled]="
+        vorgangWithEingang
+          | notHasAnyLink
+            : vorgangWithEingangLinkRel.REPRESENTATIONS
+            : vorgangWithEingangLinkRel.ATTACHMENTS
+      "
     >
       <ng-template matTabContent>
-        <alfa-vorgang-detail-attachment-list
-          data-test-id="tab-attachments-list"
+        <alfa-vorgang-detail-dateien-container
+          *ngIf="vorgangWithEingang"
           [vorgangWithEingang]="vorgangWithEingang"
-        ></alfa-vorgang-detail-attachment-list>
+        ></alfa-vorgang-detail-dateien-container>
       </ng-template>
     </mat-tab>
     <mat-tab
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts
index dfe0151ba8bf70bb061b862471ec6b678e1b1952..83a309ba164e11fc7debead039783ae81e8aa925 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts
@@ -21,30 +21,27 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatTabsModule } from '@angular/material/tabs';
-import { NoopAnimationsModule } from '@angular/platform-browser/animations';
 import { HistorieContainerComponent } from '@alfa-client/historie';
-import { HasLinkPipe, NotHasLinkPipe } from '@alfa-client/tech-shared';
+import { HasLinkPipe } from '@alfa-client/tech-shared';
 import { getElementFromFixture } from '@alfa-client/test-utils';
 import { ExpansionPanelComponent } from '@alfa-client/ui';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatTabsModule } from '@angular/material/tabs';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { NotHasAnyLinkPipe } from 'libs/tech-shared/src/lib/pipe/not-has-any-link.pipe';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { VorgangDetailAntragDataComponent } from './vorgang-detail-antrag-data/vorgang-detail-antrag-data.component';
-import { VorgangDetailAttachmentListComponent } from './vorgang-detail-attachment-list/vorgang-detail-attachment-list.component';
+import { VorgangDetailDateienContainerComponent } from './vorgang-detail-dateien-container/vorgang-detail-dateien-container.component';
 import { VorgangDetailFormularDatenComponent } from './vorgang-detail-formular-daten.component';
-import { VorgangDetailMetaDataComponent } from './vorgang-detail-meta-data/vorgang-detail-meta-data.component';
-import { VorgangDetailRepresentationListComponent } from './vorgang-detail-representation-list/vorgang-detail-representation-list.component';
 
 describe('VorgangDetailFormularDatenComponent', () => {
   let component: VorgangDetailFormularDatenComponent;
   let fixture: ComponentFixture<VorgangDetailFormularDatenComponent>;
 
-  const tabMetaData: string = getTabByIndex(2);
-  const tabRepresentations: string = getTabByIndex(3);
-  const tabAttachments: string = getTabByIndex(4);
-  const tabHistorie: string = getTabByIndex(5);
+  const tabDateien: string = getTabByIndex(2);
+  const tabHistorie: string = getTabByIndex(3);
 
   function getTabByIndex(index: number): string {
     return `div[role=tab]:nth-child(${index})`;
@@ -62,12 +59,10 @@ describe('VorgangDetailFormularDatenComponent', () => {
       imports: [NoopAnimationsModule, MatTabsModule],
       declarations: [
         HasLinkPipe,
-        NotHasLinkPipe,
+        NotHasAnyLinkPipe,
         VorgangDetailFormularDatenComponent,
         MockComponent(VorgangDetailAntragDataComponent),
-        MockComponent(VorgangDetailMetaDataComponent),
-        MockComponent(VorgangDetailAttachmentListComponent),
-        MockComponent(VorgangDetailRepresentationListComponent),
+        MockComponent(VorgangDetailDateienContainerComponent),
         MockComponent(ExpansionPanelComponent),
         MockComponent(HistorieContainerComponent),
       ],
@@ -85,98 +80,82 @@ describe('VorgangDetailFormularDatenComponent', () => {
     expect(component).toBeTruthy();
   });
 
-  describe('Metadaten', () => {
-    it('should show tab enabled if Vorgang contains metadata', () => {
-      component.metaData = { test: 'testValue' };
+  describe('Tag Dateien', () => {
+    describe('Datenrepräsentation', () => {
+      const vorgangWithRepresentations: VorgangWithEingangResource =
+        createVorgangWithEingangResource([VorgangWithEingangLinkRel.REPRESENTATIONS]);
 
-      fixture.detectChanges();
-      const metaDataTab = getElementFromFixture(fixture, tabMetaData);
+      it('should be enabled and selected if representations links is present', () => {
+        component.vorgangWithEingang = vorgangWithRepresentations;
 
-      expect(metaDataTab).not.toHaveClass(disabledTabClass);
-    });
+        fixture.detectChanges();
 
-    it('should disable tab if Vorgang contains no metadata', () => {
-      fixture.detectChanges();
-      const metaDataTab = getElementFromFixture(fixture, tabMetaData);
+        const tab: HTMLElement = getElementFromFixture(fixture, tabDateien);
+        expect(tab).not.toHaveClass(disabledTabClass);
+        expect(tab).toHaveAttribute('aria-selected', 'true');
+      });
 
-      expect(metaDataTab).toHaveClass(disabledTabClass);
-    });
-
-    it('should show MetaData label', () => {
-      fixture.detectChanges();
-      const metaDataTab = getElementFromFixture(fixture, tabMetaData);
+      it('should be disable and not selected if representations link is NOT present', () => {
+        component.vorgangWithEingang = vorgangWithEingang;
 
-      expect(metaDataTab).toHaveTextContent('Metadaten');
-    });
-  });
+        fixture.detectChanges();
 
-  describe('Tab Datenrepräsentation', () => {
-    const vorgangWithRepresentations: VorgangWithEingangResource = createVorgangWithEingangResource(
-      [VorgangWithEingangLinkRel.REPRESENTATIONS],
-    );
+        const tab: HTMLElement = getElementFromFixture(fixture, tabDateien);
+        expect(tab).toHaveClass(disabledTabClass);
+        expect(tab).toHaveAttribute('aria-selected', 'false');
+      });
 
-    it('should be enabled and selected if representations links is present', () => {
-      component.vorgangWithEingang = vorgangWithRepresentations;
+      it('should show number of Representations in the label', () => {
+        component.vorgangWithEingang = {
+          ...vorgangWithRepresentations,
+          eingang: { ...vorgangWithRepresentations.eingang, numberOfAttachments: 0 },
+        };
 
-      fixture.detectChanges();
-      const tab = getElementFromFixture(fixture, tabRepresentations);
+        fixture.detectChanges();
 
-      expect(tab).not.toHaveClass(disabledTabClass);
-      expect(tab).toHaveAttribute('aria-selected', 'true');
+        const tab: HTMLElement = getElementFromFixture(fixture, tabDateien);
+        expect(tab).toHaveTextContent(
+          `Dateien (${vorgangWithRepresentations.eingang.numberOfRepresentations})`,
+        );
+      });
     });
 
-    it('should be disable and not selected if representations link is NOT present', () => {
-      component.vorgangWithEingang = vorgangWithEingang;
+    describe('Anhänge', () => {
+      const vorgangWithAttachments: VorgangWithEingangResource = createVorgangWithEingangResource([
+        VorgangWithEingangLinkRel.ATTACHMENTS,
+      ]);
 
-      fixture.detectChanges();
-      const tab = getElementFromFixture(fixture, tabRepresentations);
+      it('should be enabled if attachments link is present', () => {
+        component.vorgangWithEingang = vorgangWithAttachments;
 
-      expect(tab).toHaveClass(disabledTabClass);
-      expect(tab).toHaveAttribute('aria-selected', 'false');
-    });
-
-    it('should show number of Representations in the label', () => {
-      component.vorgangWithEingang = vorgangWithRepresentations;
-
-      fixture.detectChanges();
-      const tab = getElementFromFixture(fixture, tabRepresentations);
-      const tabLabel = `Datenrepräsentation (${vorgangWithRepresentations.eingang.numberOfRepresentations})`;
-
-      expect(tab).toHaveTextContent(tabLabel);
-    });
-  });
-
-  describe('Tab Anhänge', () => {
-    const vorgangWithAttachments: VorgangWithEingangResource = createVorgangWithEingangResource([
-      VorgangWithEingangLinkRel.ATTACHMENTS,
-    ]);
+        fixture.detectChanges();
 
-    it('should be enabled if attachments link is present', () => {
-      component.vorgangWithEingang = vorgangWithAttachments;
+        const tab: HTMLElement = getElementFromFixture(fixture, tabDateien);
+        expect(tab).not.toHaveClass(disabledTabClass);
+      });
 
-      fixture.detectChanges();
-      const tab = getElementFromFixture(fixture, tabAttachments);
-
-      expect(tab).not.toHaveClass(disabledTabClass);
-    });
-
-    it('should be disable if attachments link is NOT present', () => {
-      component.vorgangWithEingang = vorgangWithEingang;
+      it('should be disable if attachments link is NOT present', () => {
+        component.vorgangWithEingang = vorgangWithEingang;
 
-      fixture.detectChanges();
-      const tab = getElementFromFixture(fixture, tabAttachments);
+        fixture.detectChanges();
 
-      expect(tab).toHaveClass(disabledTabClass);
-    });
+        const tab: HTMLElement = getElementFromFixture(fixture, tabDateien);
+        expect(tab).toHaveClass(disabledTabClass);
+      });
 
-    it('should show number of Attachments in the label', () => {
-      component.vorgangWithEingang = vorgangWithAttachments;
+      it('should show number of Attachments in the label', () => {
+        component.vorgangWithEingang = {
+          ...vorgangWithAttachments,
+          eingang: { ...vorgangWithAttachments.eingang, numberOfRepresentations: 0 },
+        };
 
-      fixture.detectChanges();
-      const tab = getElementFromFixture(fixture, tabAttachments);
-      const tabLabel = `Anhänge (${vorgangWithAttachments.eingang.numberOfAttachments})`;
+        fixture.detectChanges();
 
-      expect(tab).toHaveTextContent(tabLabel);
+        const tab: HTMLElement = getElementFromFixture(fixture, tabDateien);
+        expect(tab).toHaveTextContent(
+          `Dateien (${vorgangWithAttachments.eingang.numberOfAttachments})`,
+        );
+      });
     });
   });
 
@@ -185,8 +164,8 @@ describe('VorgangDetailFormularDatenComponent', () => {
       component.vorgangWithEingang = vorgangWithHistorie;
 
       fixture.detectChanges();
-      const tab = getElementFromFixture(fixture, tabHistorie);
 
+      const tab: HTMLElement = getElementFromFixture(fixture, tabHistorie);
       expect(tab).toBeInTheDocument();
     });
 
@@ -194,8 +173,8 @@ describe('VorgangDetailFormularDatenComponent', () => {
       component.vorgangWithEingang = vorgangWithEingang;
 
       fixture.detectChanges();
-      const tab = getElementFromFixture(fixture, tabHistorie);
 
+      const tab: HTMLElement = getElementFromFixture(fixture, tabHistorie);
       expect(tab).not.toBeInTheDocument();
     });
 
@@ -203,8 +182,8 @@ describe('VorgangDetailFormularDatenComponent', () => {
       component.vorgangWithEingang = vorgangWithHistorie;
 
       fixture.detectChanges();
-      const metaDataTab = getElementFromFixture(fixture, tabHistorie);
 
+      const metaDataTab: HTMLElement = getElementFromFixture(fixture, tabHistorie);
       expect(metaDataTab).toHaveTextContent('Historie');
     });
   });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.ts
index 89c9894be1cd94b8e61ce7981abf3f4688c33caf..69a869b9ccdb4a363b3f9e0d75388f018cc1d22e 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.ts
@@ -21,8 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input, OnInit } from '@angular/core';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input, OnInit } from '@angular/core';
 import { hasLink } from '@ngxp/rest';
 
 @Component({
@@ -33,7 +33,6 @@ import { hasLink } from '@ngxp/rest';
 export class VorgangDetailFormularDatenComponent implements OnInit {
   @Input() vorgangWithEingang: VorgangWithEingangResource;
 
-  metaData: object;
   antragsData: object;
 
   readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel;
@@ -43,6 +42,13 @@ export class VorgangDetailFormularDatenComponent implements OnInit {
   }
 
   get defaultSelection(): number {
-    return hasLink(this.vorgangWithEingang, this.vorgangWithEingangLinkRel.REPRESENTATIONS) ? 2 : 0;
+    return hasLink(this.vorgangWithEingang, this.vorgangWithEingangLinkRel.REPRESENTATIONS) ? 1 : 0;
+  }
+
+  get filesNumber(): number {
+    return (
+      this.vorgangWithEingang.eingang.numberOfAttachments +
+      this.vorgangWithEingang.eingang.numberOfRepresentations
+    );
   }
 }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.html
deleted file mode 100644
index 993f0b128ebd152b9b054e1f2c76acd5c54fd198..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.html
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
-
--->
-<alfa-vorgang-detail-form-data-table
-  data-test-id="metadaten"
-  [formData]="metaData"
-></alfa-vorgang-detail-form-data-table>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.scss
deleted file mode 100644
index b571b3c71b2625b19658760f31f072dc3134468d..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-:host {
-  display: inline-block;
-  margin-top: 0.5rem;
-  overflow: hidden;
-}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.spec.ts
deleted file mode 100644
index 9a253e89f86b3dd11bfe9811f02f0839b141e315..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.spec.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MockComponent } from 'ng-mocks';
-import { VorgangDetailFormDataTableComponent } from '../vorgang-detail-form-data-table/vorgang-detail-form-data-table.component';
-import { VorgangDetailMetaDataComponent } from './vorgang-detail-meta-data.component';
-
-describe('VorgangDetailMetaDataComponent', () => {
-  let component: VorgangDetailMetaDataComponent;
-  let fixture: ComponentFixture<VorgangDetailMetaDataComponent>;
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [
-        VorgangDetailMetaDataComponent,
-        MockComponent(VorgangDetailFormDataTableComponent),
-      ],
-    }).compileComponents();
-  });
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(VorgangDetailMetaDataComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.ts
deleted file mode 100644
index 1ab47d3436611b4542506e51920f2e3dda936b6a..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { Component, Input } from '@angular/core';
-
-@Component({
-  selector: 'alfa-vorgang-detail-meta-data',
-  templateUrl: './vorgang-detail-meta-data.component.html',
-  styleUrls: ['./vorgang-detail-meta-data.component.scss'],
-})
-export class VorgangDetailMetaDataComponent {
-  @Input() metaData: object;
-}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.html
deleted file mode 100644
index 0c6b5172652511b4c53e0ace77438a6a55b0728a..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-
-    Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
-
--->
-<alfa-vertical-binary-file-list
-  [fileListResource]="fileListResource$ | async"
-  [downloadFileNamePrefix]="vorgangWithEingang.nummer"
->
-</alfa-vertical-binary-file-list>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.scss
deleted file mode 100644
index 9a08a5aabce6cc4cdbb268c4190a8d67f82f19e5..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.spec.ts
deleted file mode 100644
index 04a6e0a8f98a6568cade6dadaa49deeab04ebeab..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.spec.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { VerticalBinaryFileListComponent } from '@alfa-client/binary-file';
-import { mock } from '@alfa-client/test-utils';
-import {
-  VorgangService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
-import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
-import { MockComponent } from 'ng-mocks';
-import { VorgangDetailRepresentationListComponent } from './vorgang-detail-representation-list.component';
-
-describe('VorgangDetailRepresentationListComponent', () => {
-  let component: VorgangDetailRepresentationListComponent;
-  let fixture: ComponentFixture<VorgangDetailRepresentationListComponent>;
-
-  const vorgangService = mock(VorgangService);
-  const vorgangWithRepresentations: VorgangWithEingangResource = createVorgangWithEingangResource([
-    VorgangWithEingangLinkRel.REPRESENTATIONS,
-  ]);
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [
-        VorgangDetailRepresentationListComponent,
-        MockComponent(VerticalBinaryFileListComponent),
-      ],
-      providers: [
-        {
-          provide: VorgangService,
-          useValue: vorgangService,
-        },
-      ],
-    }).compileComponents();
-  });
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(VorgangDetailRepresentationListComponent);
-    component = fixture.componentInstance;
-    component.vorgangWithEingang = createVorgangWithEingangResource();
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-
-  describe('on vorgang with "representation" link', () => {
-    it('should call vorgangService methods', () => {
-      component.vorgangWithEingang = vorgangWithRepresentations;
-
-      component.ngOnInit();
-
-      expect(vorgangService.getRepresentations).toHaveBeenCalled();
-    });
-  });
-});
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.ts
deleted file mode 100644
index 2007d106199389a23bd6370bee91fd36f5cfca2f..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { Component, Input, OnInit } from '@angular/core';
-import { BinaryFileListResource } from '@alfa-client/binary-file-shared';
-import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
-import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
-import { Observable, of } from 'rxjs';
-
-@Component({
-  selector: 'alfa-vorgang-detail-representation-list',
-  templateUrl: './vorgang-detail-representation-list.component.html',
-  styleUrls: ['./vorgang-detail-representation-list.component.scss'],
-})
-export class VorgangDetailRepresentationListComponent implements OnInit {
-  @Input() vorgangWithEingang: VorgangWithEingangResource;
-
-  fileListResource$: Observable<StateResource<BinaryFileListResource>> = of(
-    createEmptyStateResource<BinaryFileListResource>(),
-  );
-
-  constructor(private vorgangService: VorgangService) {}
-
-  ngOnInit(): void {
-    this.fileListResource$ = this.vorgangService.getRepresentations();
-  }
-}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.spec.ts
index 9e29f9d8172e162e37e5187cb5729efe2dd45eaf..5c631ffeb6e6c4007028f95655df19047482b1b9 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.spec.ts
@@ -9,10 +9,10 @@ import {
 import { BinaryFileResource } from '@alfa-client/binary-file-shared';
 import { CommandLinkRel, CommandResource } from '@alfa-client/command-shared';
 import {
-  createStateResource,
   EMPTY_STRING,
-  formatForDatabase,
   StateResource,
+  createStateResource,
+  formatForDatabase,
 } from '@alfa-client/tech-shared';
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
@@ -114,6 +114,22 @@ describe('BescheidenFormService', () => {
 
       expect(service.sendByManual.value).toBeFalsy();
     });
+    it('should not emit if value not changed', () => {
+      service.sendByManual.next(true);
+      service.sendByManual.next = jest.fn();
+
+      service.updateSendByManual(BescheidSendBy.MANUAL);
+
+      expect(service.sendByManual.next).not.toHaveBeenCalled();
+    });
+    it('should emit on value change', () => {
+      service.sendByManual.next(false);
+      service.sendByManual.next = jest.fn();
+
+      service.updateSendByManual(BescheidSendBy.MANUAL);
+
+      expect(service.sendByManual.next).toHaveBeenCalled();
+    });
   });
 
   describe('initializeFormChanges', () => {
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
index d9e05716a5c15264f7f5b671ecec6a8f61cc1ca1..b079362062868d5fd121503655948db80538f466 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
@@ -10,14 +10,14 @@ import { BinaryFileResource } from '@alfa-client/binary-file-shared';
 import { CommandResource, tapOnCommandSuccessfullyDone } from '@alfa-client/command-shared';
 import {
   AbstractFormService,
-  convertToBoolean,
   EMPTY_STRING,
-  formatForDatabase,
   HttpError,
+  StateResource,
+  convertToBoolean,
+  formatForDatabase,
   isLoaded,
   isNotEmpty,
   isNotNil,
-  StateResource,
 } from '@alfa-client/tech-shared';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Injectable, OnDestroy } from '@angular/core';
@@ -28,18 +28,18 @@ import {
   UntypedFormControl,
   UntypedFormGroup,
 } from '@angular/forms';
-import { getUrl, hasLink, Resource, ResourceUri } from '@ngxp/rest';
+import { Resource, ResourceUri, getUrl, hasLink } from '@ngxp/rest';
 import { isEmpty, isNil, isUndefined } from 'lodash-es';
 import {
   BehaviorSubject,
+  Observable,
+  Subject,
+  Subscription,
   combineLatest,
   filter,
   first,
   map,
-  Observable,
   startWith,
-  Subject,
-  Subscription,
 } from 'rxjs';
 
 @Injectable()
@@ -92,7 +92,8 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
   }
 
   updateSendByManual(sendBy: BescheidSendBy): void {
-    this.sendByManual.next(sendBy === BescheidSendBy.MANUAL);
+    const isSendByManual = sendBy === BescheidSendBy.MANUAL;
+    if (isSendByManual !== this.sendByManual.value) this.sendByManual.next(isSendByManual);
   }
 
   initializeFormChanges(): void {
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-attachments/vorgang-detail-bescheiden-result-attachments.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-attachments/vorgang-detail-bescheiden-result-attachments.component.html
index 95e424d51d4542bce8bc97612cd8f632bca51b48..ff4e542e0d9181e9ee7bc98b468e62b2a1d23482 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-attachments/vorgang-detail-bescheiden-result-attachments.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-attachments/vorgang-detail-bescheiden-result-attachments.component.html
@@ -1,4 +1,4 @@
-<ods-attachment-container>
+<ods-attachment-wrapper>
   <alfa-binary-file2-container
     *ngFor="let attachment of existingAttachments"
     [file]="attachment"
@@ -27,4 +27,4 @@
       [isLoading]="uploadFileInProgress.loading"
     ></ods-attachment>
   </ng-container>
-</ods-attachment-container>
+</ods-attachment-wrapper>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-attachments/vorgang-detail-bescheiden-result-attachments.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-attachments/vorgang-detail-bescheiden-result-attachments.component.spec.ts
index 38a32fe726c44d6f7c0152e0caec38bfb8c90791..63758c537759f45fbe750b6c286b6b2e5778864d 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-attachments/vorgang-detail-bescheiden-result-attachments.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-attachments/vorgang-detail-bescheiden-result-attachments.component.spec.ts
@@ -14,11 +14,7 @@ import { existsAsHtmlElement, Mock, mock, notExistsAsHtmlElement } from '@alfa-c
 import { OzgcloudSvgIconComponent, SpinnerComponent } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIcon } from '@angular/material/icon';
-import {
-  AttachmentComponent,
-  AttachmentContainerComponent,
-  SpinnerIconComponent,
-} from '@ods/system';
+import { AttachmentComponent, AttachmentWrapperComponent, SpinnerIconComponent } from '@ods/system';
 import { MockComponent, MockPipe } from 'ng-mocks';
 import { BehaviorSubject, EMPTY, Observable, of, Subscription } from 'rxjs';
 import { createUploadFileInProgress } from '../../../../../../../bescheid-shared/src/test/bescheid';
@@ -58,7 +54,7 @@ describe('VorgangDetailBescheidenResultAttachmentsComponent', () => {
         MockPipe(ConvertApiErrorToErrorMessagesPipe),
         MockComponent(OzgcloudSvgIconComponent),
         MockComponent(SpinnerComponent),
-        MockComponent(AttachmentContainerComponent),
+        MockComponent(AttachmentWrapperComponent),
         MockComponent(BinaryFile2ContainerComponent),
         MockComponent(SpinnerIconComponent),
         MockComponent(AttachmentComponent),
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-dokument/vorgang-detail-bescheiden-result-dokument.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-dokument/vorgang-detail-bescheiden-result-dokument.component.html
index 2080ba5b2a7b977a0837a437c97ae3d1579ba396..bb762af88d7b449d222804be6eccd2be60690f5e 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-dokument/vorgang-detail-bescheiden-result-dokument.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-dokument/vorgang-detail-bescheiden-result-dokument.component.html
@@ -5,7 +5,7 @@
 >
   Bitte fügen Sie ein Bescheiddokument hinzu.
 </p>
-<ods-attachment-container>
+<ods-attachment-wrapper>
   <ng-container *ngIf="bescheidDocumentFile.resource">
     <alfa-binary-file2-container
       *ngIf="
@@ -39,4 +39,4 @@
     [errorMessages]="createDocumentErrorMessages"
     data-test-id="create-bescheid-document-attachment"
   ></ods-attachment>
-</ods-attachment-container>
+</ods-attachment-wrapper>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-dokument/vorgang-detail-bescheiden-result-dokument.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-dokument/vorgang-detail-bescheiden-result-dokument.component.spec.ts
index 15a99f1bea6f85d4287f1ca9d0a85fffc4144dbc..c61b90e368bb525ef644dfd2e95d156c06338d22 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-dokument/vorgang-detail-bescheiden-result-dokument.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-dokument/vorgang-detail-bescheiden-result-dokument.component.spec.ts
@@ -3,14 +3,14 @@ import { BinaryFile2ContainerComponent } from '@alfa-client/binary-file';
 import { CommandResource } from '@alfa-client/command-shared';
 import {
   ConvertApiErrorToErrorMessagesPipe,
+  StateResource,
   createEmptyStateResource,
   createStateResource,
-  StateResource,
 } from '@alfa-client/tech-shared';
-import { existsAsHtmlElement, Mock, mock, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { Mock, existsAsHtmlElement, mock, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { getUrl } from '@ngxp/rest';
-import { AttachmentComponent, AttachmentContainerComponent } from '@ods/system';
+import { AttachmentComponent, AttachmentWrapperComponent } from '@ods/system';
 import { createBescheidResource } from 'libs/bescheid-shared/src/test/bescheid';
 import { createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
@@ -47,7 +47,7 @@ describe('VorgangDetailBescheidenResultDokumentComponent', () => {
         VorgangDetailBescheidenResultDokumentComponent,
         MockComponent(BinaryFile2ContainerComponent),
         MockComponent(AttachmentComponent),
-        MockComponent(AttachmentContainerComponent),
+        MockComponent(AttachmentWrapperComponent),
         MockPipe(ConvertApiErrorToErrorMessagesPipe),
       ],
       providers: [
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.html
index 0b4b30cf95db4e50dbaec098d73c7b5fe1d0399b..5f5be409ae38611e4d72d5712e7beaae28677299 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result-nachricht/vorgang-detail-bescheiden-result-nachricht.component.html
@@ -12,6 +12,7 @@
     label="Betreff"
     placeholder="Betreff hier eingeben"
     [focus]="focusBetreff"
+    [isRequired]="true"
   >
   </ods-text-editor>
 
@@ -20,6 +21,7 @@
     label="Text"
     placeholder="Nachrichtentext hier eingeben"
     [focus]="focusNachricht"
+    [isRequired]="true"
   >
   </ods-textarea-editor>
 </div>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.spec.ts
index 63d46924cd75604ec3975f452e36034aecd854c0..22332fc5187c9ce1bc318ceb77b4b7ad0e30e833 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.spec.ts
@@ -59,6 +59,7 @@ describe('VorgangDetailBescheidenResultComponent', () => {
       new BehaviorSubject({ beschiedenAm: new Date(), bewilligt: false }),
     );
     formService.getActiveStep.mockReturnValue(EMPTY);
+    formService.isSendByManual.mockReturnValue(EMPTY);
 
     await TestBed.configureTestingModule({
       declarations: [
@@ -213,42 +214,18 @@ describe('VorgangDetailBescheidenResultComponent', () => {
       expect(bescheidService.getBescheidDocument).toHaveBeenCalled();
     });
 
-    it('should call formservice to get active step', () => {
-      component.ngOnInit();
-
-      expect(formService.getActiveStep).toHaveBeenCalled();
-    });
-
-    it.each([1, 2])('should reset save and send in progress in step %d', (step: number) => {
-      formService.getActiveStep.mockReturnValue(of(step));
-      component.resetSend = jest.fn();
-
-      component.ngOnInit();
-
-      component.activeStep$.subscribe();
-      expect(component.resetSend).toHaveBeenCalled();
-    });
-
-    it('should not reset save and send in progress in last step', () => {
-      formService.getActiveStep.mockReturnValue(of(3));
-      component.resetSend = jest.fn();
-
-      component.ngOnInit();
-
-      component.activeStep$.subscribe();
-      expect(component.resetSend).not.toHaveBeenCalled();
-    });
-
     it('should call formservice to get current bescheid/formular', () => {
       component.ngOnInit();
 
       expect(formService.getBescheidChanges).toHaveBeenCalled();
     });
 
-    it('should call formservice to get sendByManual', () => {
+    it('should get is send by manual', () => {
+      component.getIsSendManually = jest.fn();
+
       component.ngOnInit();
 
-      expect(formService.isSendByManual).toHaveBeenCalled();
+      expect(component.getIsSendManually).toHaveBeenCalled();
     });
 
     it('should call service to get upload bescheid document in progress', () => {
@@ -263,6 +240,14 @@ describe('VorgangDetailBescheidenResultComponent', () => {
       expect(bescheidService.getCreateBescheidDocumentInProgress).toHaveBeenCalled();
     });
 
+    it('should get active step', () => {
+      component.getActiveStep = jest.fn();
+
+      component.ngOnInit();
+
+      expect(component.getActiveStep).toHaveBeenCalled();
+    });
+
     describe('canSave$', () => {
       it('should emit true', () => {
         bescheidService.getBescheidDraft.mockReturnValue(
@@ -620,21 +605,93 @@ describe('VorgangDetailBescheidenResultComponent', () => {
     });
   });
 
-  describe('ifNotLastStep', () => {
-    it.each([1, 2])('should do it in step %d', (step: number) => {
-      const doIt = jest.fn();
+  describe('get active step', () => {
+    it('should call formService', () => {
+      component.getActiveStep().pipe(first()).subscribe();
+
+      expect(formService.getActiveStep).toHaveBeenCalled();
+    });
+
+    it.each([1, VorgangDetailBescheidenResultComponent.BESCHEID_VERSENDEN_STEP])(
+      'should call bescheidService to clear attachment upload on step %s',
+      (step: number) => {
+        formService.getActiveStep.mockReturnValue(of(step));
+
+        component.getActiveStep().pipe(first()).subscribe();
+
+        expect(bescheidService.clearAttachmentUpload).toHaveBeenCalled();
+      },
+    );
+
+    describe('reset send', () => {
+      beforeEach(() => {
+        component.resetSend = jest.fn();
+      });
+
+      it.each([1, VorgangDetailBescheidenResultComponent.ADD_DOCUMENTS_STEP])(
+        'should be called on step %s',
+        (step: number) => {
+          formService.getActiveStep.mockReturnValue(of(step));
+
+          component.getActiveStep().pipe(first()).subscribe();
+
+          expect(component.resetSend).toHaveBeenCalled();
+        },
+      );
+
+      it('should not be called on last step', () => {
+        formService.getActiveStep.mockReturnValue(of(3));
+
+        component.getActiveStep().pipe(first()).subscribe();
+
+        expect(component.resetSend).not.toHaveBeenCalled();
+      });
+    });
+  });
+
+  describe('reset send', () => {
+    it('should clear saveAndSendInProgress', (done) => {
+      component.saveAndSendInProgress$ = of(createCommandStateResource());
 
-      of(step).pipe(component.ifNotLastStep(doIt)).subscribe();
+      component.resetSend();
 
-      expect(doIt).toHaveBeenCalled();
+      component.saveAndSendInProgress$
+        .pipe(first())
+        .subscribe((saveAndSendInProgress: StateResource<CommandResource>) => {
+          expect(saveAndSendInProgress).toEqual(createEmptyStateResource());
+          done();
+        });
     });
 
-    it('should not do it in last step', () => {
-      const doIt = jest.fn();
+    it('should clear sendWithNachricht', () => {
+      component.sendWithNachricht$.next(createCommandStateResource());
+
+      component.resetSend();
 
-      of(3).pipe(component.ifNotLastStep(doIt)).subscribe();
+      expect(component.sendWithNachricht$.value).toEqual(createEmptyStateResource());
+    });
+  });
 
-      expect(doIt).not.toHaveBeenCalled();
+  describe('getIsSendManually', () => {
+    beforeEach(() => {
+      component.resetSend = jest.fn();
     });
+
+    it('should get is send by manual from from service', () => {
+      component.getIsSendManually();
+
+      expect(formService.isSendByManual).toHaveBeenCalled();
+    });
+
+    it.each([true, false])(
+      'should reset send if send by manual is %s',
+      (isSendByManual: boolean) => {
+        formService.isSendByManual.mockReturnValue(of(isSendByManual));
+
+        component.getIsSendManually().subscribe();
+
+        expect(component.resetSend).toHaveBeenCalled();
+      },
+    );
   });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
index 277c06197a06582d354c5f19e4985d97e7cef6c7..5b423f9fdb6be53a986356f5bab275490a479dc7 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
@@ -28,7 +28,8 @@ type sendBescheid = (
   templateUrl: './vorgang-detail-bescheiden-result.component.html',
 })
 export class VorgangDetailBescheidenResultComponent implements OnInit {
-  private static readonly LAST_STEP: number = 3;
+  static readonly ADD_DOCUMENTS_STEP: number = 2;
+  static readonly BESCHEID_VERSENDEN_STEP: number = 3;
 
   @Output() closeDialog: EventEmitter<void> = new EventEmitter();
 
@@ -81,11 +82,9 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
       this.bescheidService.getCreateBescheidDocumentInProgress();
     this.bescheidDocument$ = this.bescheidService.getBescheidDocument();
 
-    this.activeStep$ = this.formService
-      .getActiveStep()
-      .pipe(this.ifNotLastStep(() => this.resetSend()));
+    this.activeStep$ = this.getActiveStep();
     this.bescheid$ = this.formService.getBescheidChanges();
-    this.sendByManual$ = this.formService.isSendByManual();
+    this.sendByManual$ = this.getIsSendManually();
 
     this.canSave$ = this.bescheidDraftStateResource$.pipe(
       filter(isLoaded),
@@ -102,16 +101,27 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
     this.showMissingBescheidDocumentError$ = this.formService.getShowMissingBescheidDocumentError();
   }
 
-  ifNotLastStep(doIt: () => void): OperatorFunction<number, number> {
-    return (source: Observable<number>) => {
-      return source.pipe(
-        tap((step: number) => {
-          if (step < VorgangDetailBescheidenResultComponent.LAST_STEP) {
-            doIt();
-          }
-        }),
-      );
-    };
+  getActiveStep(): Observable<number> {
+    return this.formService
+      .getActiveStep()
+      .pipe(tap((step: number) => this.resetStateOnStepChange(step)));
+  }
+
+  getIsSendManually(): Observable<boolean> {
+    return this.formService.isSendByManual().pipe(tap(() => this.resetSend()));
+  }
+
+  private resetStateOnStepChange(step: number): void {
+    if (this.isNotLast(step)) this.resetSend();
+    if (this.shouldClearAttachmentInProgress(step)) this.bescheidService.clearAttachmentUpload();
+  }
+
+  private isNotLast(step: number): boolean {
+    return step < VorgangDetailBescheidenResultComponent.BESCHEID_VERSENDEN_STEP;
+  }
+
+  private shouldClearAttachmentInProgress(step: number): boolean {
+    return step != VorgangDetailBescheidenResultComponent.ADD_DOCUMENTS_STEP;
   }
 
   resetSend(): void {
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.html
index 5ebc616b3fa6376d2cb5437ccf98b74c90f2888b..3868f94249128b79fe4e08b15d228fac0498165d 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.html
@@ -1,3 +1,7 @@
-<button (click)="onClick()" class="absolute right-3 top-3 text-text" data-test-id="close-bescheid">
+<button
+  (click)="clickEmitter.emit()"
+  class="absolute right-3 top-3 text-text"
+  data-test-id="close-bescheid"
+>
   <mat-icon>close</mat-icon>
 </button>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.spec.ts
index 88edfcc33994a41c77e6ef8e46d7a53e6637ea0b..d143d1618f0b45bcf78d65061f489811034d219e 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.spec.ts
@@ -1,28 +1,15 @@
-import { Mock, mock } from '@alfa-client/test-utils';
-import { OzgcloudDialogService } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIcon } from '@angular/material/icon';
-import { VorgangDetailBescheidenAbbrechenDialogComponent } from '../vorgang-detail-bescheiden-abbrechen-dialog/vorgang-detail-bescheiden-abbrechen-dialog.component';
 import { VorgangDetailBescheidenAbbrechenButtonComponent } from './vorgang-detail-bescheiden-abbrechen-button.component';
 
 describe('VorgangDetailBescheidenAbbrechenButtonComponent', () => {
   let component: VorgangDetailBescheidenAbbrechenButtonComponent;
   let fixture: ComponentFixture<VorgangDetailBescheidenAbbrechenButtonComponent>;
 
-  let ozgcloudDialogService: Mock<OzgcloudDialogService>;
-
   beforeEach(async () => {
-    ozgcloudDialogService = mock(OzgcloudDialogService);
-
     await TestBed.configureTestingModule({
       declarations: [VorgangDetailBescheidenAbbrechenButtonComponent],
       imports: [MatIcon],
-      providers: [
-        {
-          provide: OzgcloudDialogService,
-          useValue: ozgcloudDialogService,
-        },
-      ],
     }).compileComponents();
 
     fixture = TestBed.createComponent(VorgangDetailBescheidenAbbrechenButtonComponent);
@@ -33,15 +20,4 @@ describe('VorgangDetailBescheidenAbbrechenButtonComponent', () => {
   it('should create', () => {
     expect(component).toBeTruthy();
   });
-
-  describe('onClick', () => {
-    it('should call ozgcloudDialogService.open', () => {
-      component.onClick();
-
-      expect(ozgcloudDialogService.openInCallingComponentContext).toHaveBeenCalledWith(
-        VorgangDetailBescheidenAbbrechenDialogComponent,
-        component.viewContainerRef,
-      );
-    });
-  });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.ts
index 41f0834080232437ba18c70f809071c2f9c3dc8a..4f1051d4c4c98c148725c077185d35463b916a6c 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component.ts
@@ -1,6 +1,4 @@
-import { OzgcloudDialogService } from '@alfa-client/ui';
-import { Component, ViewContainerRef } from '@angular/core';
-import { VorgangDetailBescheidenAbbrechenDialogComponent } from '../vorgang-detail-bescheiden-abbrechen-dialog/vorgang-detail-bescheiden-abbrechen-dialog.component';
+import { Component, EventEmitter, Output } from '@angular/core';
 
 @Component({
   selector: 'alfa-vorgang-detail-bescheiden-abbrechen-button',
@@ -8,15 +6,5 @@ import { VorgangDetailBescheidenAbbrechenDialogComponent } from '../vorgang-deta
   styles: [],
 })
 export class VorgangDetailBescheidenAbbrechenButtonComponent {
-  constructor(
-    private readonly ozgcloudDialogService: OzgcloudDialogService,
-    readonly viewContainerRef: ViewContainerRef,
-  ) {}
-
-  public onClick(): void {
-    this.ozgcloudDialogService.openInCallingComponentContext<VorgangDetailBescheidenAbbrechenDialogComponent>(
-      VorgangDetailBescheidenAbbrechenDialogComponent,
-      this.viewContainerRef,
-    );
-  }
+  @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
 }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.html
index e2427e885a079271ae20cac54e8a0ea1f168013f..f1e668502936106b848030aa3635d0fd7323b7f6 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.html
@@ -6,11 +6,13 @@
   data-test-id="bescheid-wizard"
 >
   <div class="fixed inset-0 z-10 w-screen overflow-y-auto">
-    <div class="flex h-full items-end items-center justify-center p-8">
+    <div class="flex h-full items-center justify-center p-8">
       <div
         class="relative h-full w-full max-w-7xl transform overflow-hidden rounded-lg bg-background-200 px-6 py-10 text-left shadow-xl transition-all"
       >
-        <alfa-vorgang-detail-bescheiden-abbrechen-button></alfa-vorgang-detail-bescheiden-abbrechen-button>
+        <alfa-vorgang-detail-bescheiden-abbrechen-button
+          (clickEmitter)="cancelWizard()"
+        ></alfa-vorgang-detail-bescheiden-abbrechen-button>
         <form [formGroup]="formService.form" class="flex h-full flex-row gap-11">
           <alfa-vorgang-detail-bescheiden-steps
             class="flex w-1/2"
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.spec.ts
index c82b596f3669350ebd42f569cae44749fa9c92f8..b201b90bf4bf872be0f5c3461dd719624462f58b 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.spec.ts
@@ -1,6 +1,7 @@
 import { BescheidResource, BescheidService } from '@alfa-client/bescheid-shared';
 import { PostfachService } from '@alfa-client/postfach-shared';
 import { Mock, dispatchEventFromFixture, mock, useFromMock } from '@alfa-client/test-utils';
+import { OzgcloudDialogService } from '@alfa-client/ui';
 import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
@@ -8,11 +9,13 @@ import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
 import { MatIcon } from '@angular/material/icon';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
+import { Subscription, of } from 'rxjs';
 import { createBescheidResource } from '../../../../../bescheid-shared/src/test/bescheid';
 import { createVorgangWithEingangResource } from '../../../../../vorgang-shared/test/vorgang';
 import { BescheidenFormService } from './bescheiden.formservice';
 import { VorgangDetailBescheidenResultComponent } from './vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component';
 import { VorgangDetailBescheidenAbbrechenButtonComponent } from './vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-button/vorgang-detail-bescheiden-abbrechen-button.component';
+import { VorgangDetailBescheidenAbbrechenDialogComponent } from './vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-dialog/vorgang-detail-bescheiden-abbrechen-dialog.component';
 import { VorgangDetailBescheidenStepsComponent } from './vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps.component';
 import { VorgangDetailBescheidenComponent } from './vorgang-detail-bescheiden.component';
 
@@ -23,8 +26,8 @@ describe('VorgangDetailBescheidenComponent', () => {
   let bescheidService: Mock<BescheidService>;
   let vorgangService: Mock<VorgangService>;
   let formService: BescheidenFormService;
-  let dialogRef: Mock<DialogRef>;
   let postfachService: Mock<PostfachService>;
+  let ozgcloudDialogService: Mock<OzgcloudDialogService>;
 
   let vorgangWithEingangResource: VorgangWithEingangResource;
   let bescheidDraftResource: BescheidResource;
@@ -35,8 +38,8 @@ describe('VorgangDetailBescheidenComponent', () => {
     bescheidService = mock(BescheidService);
     vorgangService = mock(VorgangService);
     formService = new BescheidenFormService(new UntypedFormBuilder(), useFromMock(bescheidService));
-    dialogRef = mock(DialogRef);
     postfachService = mock(PostfachService);
+    ozgcloudDialogService = mock(OzgcloudDialogService);
 
     vorgangWithEingangResource = createVorgangWithEingangResource();
     bescheidDraftResource = createBescheidResource();
@@ -70,7 +73,7 @@ describe('VorgangDetailBescheidenComponent', () => {
         },
         {
           provide: DialogRef,
-          useValue: dialogRef,
+          useValue: { keydownEvents: of(KeyboardEvent), close: jest.fn(), disableClose: false },
         },
         {
           provide: DIALOG_DATA,
@@ -80,12 +83,17 @@ describe('VorgangDetailBescheidenComponent', () => {
           provide: PostfachService,
           useValue: postfachService,
         },
+        {
+          provide: OzgcloudDialogService,
+          useValue: ozgcloudDialogService,
+        },
       ],
       imports: [ReactiveFormsModule],
     }).compileComponents();
 
     fixture = TestBed.createComponent(VorgangDetailBescheidenComponent);
     component = fixture.componentInstance;
+
     fixture.detectChanges();
   });
 
@@ -109,13 +117,40 @@ describe('VorgangDetailBescheidenComponent', () => {
 
       expect(patchValues).toBeCalledWith(bescheidDraftResource);
     });
+
+    it('should call handleEscapeKey', () => {
+      component.handleEscapeKey = jest.fn();
+
+      component.ngOnInit();
+
+      expect(component.handleEscapeKey).toHaveBeenCalled();
+    });
+  });
+
+  describe('handleEscapeKey', () => {
+    it('should subscribe to dialogRef.keydownEvents', () => {
+      component.handleEscapeKey();
+
+      expect(component.keydownEventsSubscription).toBeInstanceOf(Subscription);
+    });
+  });
+
+  describe('ngOnDestroy', () => {
+    it('should unsubscribe keydownEventsSubscription', () => {
+      component.keydownEventsSubscription = new Subscription();
+      jest.spyOn(component.keydownEventsSubscription, 'unsubscribe');
+
+      component.ngOnDestroy();
+
+      expect(component.keydownEventsSubscription.unsubscribe).toHaveBeenCalled();
+    });
   });
 
   describe('onClose', () => {
     it('should call dialogRef.close', () => {
       component.onClose();
 
-      expect(dialogRef.close).toHaveBeenCalled();
+      expect(component.dialogRef.close).toHaveBeenCalled();
     });
 
     it('should call vorgang service to reload current vorgang', () => {
@@ -135,7 +170,18 @@ describe('VorgangDetailBescheidenComponent', () => {
     it('should close dialog ref', () => {
       dispatchEventFromFixture(fixture, bescheidenResult, 'closeDialog');
 
-      expect(dialogRef.close).toHaveBeenCalled();
+      expect(component.dialogRef.close).toHaveBeenCalled();
+    });
+  });
+
+  describe('cancelWizard', () => {
+    it('should call ozgcloudDialogService.open', () => {
+      component.cancelWizard();
+
+      expect(ozgcloudDialogService.openInCallingComponentContext).toHaveBeenCalledWith(
+        VorgangDetailBescheidenAbbrechenDialogComponent,
+        component.viewContainerRef,
+      );
     });
   });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.ts
index c3a880423edbb95b2b2153db66b3202ae9dd7bad..a88075f699841c8e2b5d9c085023f6f087efc854 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.ts
@@ -1,19 +1,24 @@
 import { BescheidResource } from '@alfa-client/bescheid-shared';
 import { PostfachService } from '@alfa-client/postfach-shared';
+import { OzgcloudDialogService } from '@alfa-client/ui';
 import { VorgangService } from '@alfa-client/vorgang-shared';
 import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
-import { Component, Inject, OnInit } from '@angular/core';
+import { Component, Inject, OnDestroy, OnInit, ViewContainerRef } from '@angular/core';
+import { Subscription, filter } from 'rxjs';
 import { BescheidenFormService } from './bescheiden.formservice';
 import { BescheidenDialogData } from './bescheiden.model';
+import { VorgangDetailBescheidenAbbrechenDialogComponent } from './vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-abbrechen-dialog/vorgang-detail-bescheiden-abbrechen-dialog.component';
 
 @Component({
   selector: 'alfa-vorgang-detail-bescheiden',
   templateUrl: './vorgang-detail-bescheiden.component.html',
   providers: [BescheidenFormService],
 })
-export class VorgangDetailBescheidenComponent implements OnInit {
+export class VorgangDetailBescheidenComponent implements OnDestroy, OnInit {
   private readonly bescheidDraftResource: BescheidResource;
 
+  keydownEventsSubscription: Subscription;
+
   public activeStep: number = 1;
 
   constructor(
@@ -22,6 +27,8 @@ export class VorgangDetailBescheidenComponent implements OnInit {
     private readonly vorgangService: VorgangService,
     private readonly postfachService: PostfachService,
     @Inject(DIALOG_DATA) private readonly dialogData: BescheidenDialogData,
+    private readonly ozgcloudDialogService: OzgcloudDialogService,
+    readonly viewContainerRef: ViewContainerRef,
   ) {
     this.bescheidDraftResource = dialogData.bescheidDraftResource;
   }
@@ -29,6 +36,17 @@ export class VorgangDetailBescheidenComponent implements OnInit {
   ngOnInit(): void {
     this.formService.setVorgangWithEingangResource(this.dialogData.vorgangWithEingangResource);
     this.formService.patchValues(this.bescheidDraftResource);
+    this.handleEscapeKey();
+  }
+
+  handleEscapeKey(): void {
+    this.keydownEventsSubscription = this.dialogRef.keydownEvents
+      .pipe(filter((event) => event.key === 'Escape'))
+      .subscribe(() => this.cancelWizard());
+  }
+
+  ngOnDestroy(): void {
+    this.keydownEventsSubscription.unsubscribe();
   }
 
   public onClose(): void {
@@ -36,4 +54,11 @@ export class VorgangDetailBescheidenComponent implements OnInit {
     this.vorgangService.reloadCurrentVorgang();
     this.postfachService.setPostfachMailOnReload();
   }
+
+  public cancelWizard(): void {
+    this.ozgcloudDialogService.openInCallingComponentContext<VorgangDetailBescheidenAbbrechenDialogComponent>(
+      VorgangDetailBescheidenAbbrechenDialogComponent,
+      this.viewContainerRef,
+    );
+  }
 }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.spec.ts
index 7466616259f69afe3069e61596a3af74acb2b891..a3554bb8bab782f85f2d0924eeb5dd51c9a906d5 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.spec.ts
@@ -22,9 +22,20 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { LoeschAnforderungService } from '@alfa-client/loesch-anforderung-shared';
-import { StateResource, createStateResource } from '@alfa-client/tech-shared';
+import {
+  Issue,
+  MessageCode,
+  StateResource,
+  createErrorStateResource,
+  createStateResource,
+} from '@alfa-client/tech-shared';
 import { Mock, existsAsHtmlElement, mock, notExistsAsHtmlElement } from '@alfa-client/test-utils';
-import { SpinnerComponent, SpinnerTransparencyComponent } from '@alfa-client/ui';
+import {
+  Messages,
+  SnackBarService,
+  SpinnerComponent,
+  SpinnerTransparencyComponent,
+} from '@alfa-client/ui';
 import {
   VorgangCommandService,
   VorgangService,
@@ -34,11 +45,12 @@ import {
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatIcon } from '@angular/material/icon';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { createApiError, createIssue } from 'libs/tech-shared/test/error';
 import { ProgressBarComponent } from 'libs/ui/src/lib/ui/progress-bar/progress-bar.component';
 import { SubnavigationComponent } from 'libs/ui/src/lib/ui/subnavigation/subnavigation.component';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
-import { Subject } from 'rxjs';
+import { EMPTY, Subject, of } from 'rxjs';
 import { VorgangDetailActionButtonsComponent } from './vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component';
 import { VorgangDetailAreaComponent } from './vorgang-detail-area/vorgang-detail-area.component';
 import { VorgangDetailFormularButtonsComponent } from './vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component';
@@ -46,6 +58,9 @@ import { VorgangDetailBackButtonContainerComponent } from './vorgang-detail-back
 import { VorgangDetailMoreMenuComponent } from './vorgang-detail-more-menu/vorgang-detail-more-menu.component';
 import { VorgangDetailPageComponent } from './vorgang-detail-page.component';
 
+import { NavigationService } from '@alfa-client/navigation-shared';
+import * as ErrorUtil from 'libs/tech-shared/src/lib/error/error.util';
+
 type withGetVorgang = {
   getVorgangWithEingang: () => Subject<StateResource<VorgangWithEingang>>;
 };
@@ -58,6 +73,8 @@ describe('VorgangDetailPageComponent', () => {
   let vorgangService: Mock<VorgangService> | withGetVorgang;
   const vorgangCommandService = mock(VorgangCommandService);
   const loeschAnforderungService = mock(LoeschAnforderungService);
+  const navigationService: Mock<NavigationService> = mock(NavigationService);
+  const snackbarService: Mock<SnackBarService> = mock(SnackBarService);
 
   const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource();
 
@@ -100,6 +117,14 @@ describe('VorgangDetailPageComponent', () => {
           provide: LoeschAnforderungService,
           useValue: loeschAnforderungService,
         },
+        {
+          provide: NavigationService,
+          useValue: navigationService,
+        },
+        {
+          provide: SnackBarService,
+          useValue: snackbarService,
+        },
       ],
     });
 
@@ -114,7 +139,7 @@ describe('VorgangDetailPageComponent', () => {
 
   describe('ngOnInit', () => {
     it('should get vorgangWithEingang', () => {
-      vorgangService.getVorgangWithEingang = jest.fn();
+      vorgangService.getVorgangWithEingang = jest.fn().mockReturnValue(of(EMPTY));
 
       component.ngOnInit();
 
@@ -197,4 +222,62 @@ describe('VorgangDetailPageComponent', () => {
       existsAsHtmlElement(fixture, detailArea);
     });
   });
+
+  describe('handleApiError', () => {
+    afterEach(() => {
+      snackbarService.showInfo.mockClear();
+      navigationService.navigateToVorgangList.mockClear();
+    });
+
+    describe('with ApiError RESOURCE_NOT_FOUND', () => {
+      const issue: Issue = { ...createIssue(), messageCode: MessageCode.RESOURCE_NOT_FOUND };
+      const resource: StateResource<any> = createErrorStateResource(createApiError([issue]));
+
+      it('should call isResourceNotFoundError', () => {
+        const isResourceNotFoundError: jest.SpyInstance<boolean> = jest
+          .spyOn(ErrorUtil, 'isResourceNotFoundError')
+          .mockClear();
+
+        component.handleApiError(resource);
+
+        expect(isResourceNotFoundError).toHaveBeenCalled();
+      });
+
+      it('should call showSnackBarInfo', () => {
+        component.handleApiError(resource);
+
+        expect(snackbarService.showInfo).toHaveBeenCalledWith(
+          Messages.HTTP_STATUS_VORGANG_NOT_FOUND,
+        );
+      });
+
+      it('should call navigateToVorgangList', () => {
+        component.handleApiError(resource);
+
+        expect(navigationService.navigateToVorgangList).toHaveBeenCalled();
+      });
+    });
+
+    describe('without ApiError', () => {
+      it('should not call snackbarService.showInfo', () => {
+        const resource: StateResource<any> = createStateResource(
+          createVorgangWithEingangResource(),
+        );
+
+        component.handleApiError(resource);
+
+        expect(snackbarService.showInfo).not.toHaveBeenCalled();
+      });
+
+      it('should not call navigationService.navigateToVorgangList', () => {
+        const resource: StateResource<any> = createStateResource(
+          createVorgangWithEingangResource(),
+        );
+
+        component.handleApiError(resource);
+
+        expect(navigationService.navigateToVorgangList).not.toHaveBeenCalled();
+      });
+    });
+  });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.ts
index 8d51e40d64b5f8a1cc56566ff9a5bdcf733cfebb..97e2bae42d5480038b639184224643bf1b440318 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.ts
@@ -23,14 +23,16 @@
  */
 import { CommandResource } from '@alfa-client/command-shared';
 import { LoeschAnforderungService } from '@alfa-client/loesch-anforderung-shared';
-import { StateResource } from '@alfa-client/tech-shared';
+import { NavigationService } from '@alfa-client/navigation-shared';
+import { StateResource, isResourceNotFoundError } from '@alfa-client/tech-shared';
+import { Messages, SnackBarService } from '@alfa-client/ui';
 import {
   VorgangCommandService,
   VorgangService,
   VorgangWithEingangResource,
 } from '@alfa-client/vorgang-shared';
 import { Component, OnInit } from '@angular/core';
-import { Observable } from 'rxjs';
+import { Observable, tap } from 'rxjs';
 import { BescheidenFormService } from './vorgang-detail-bescheiden/bescheiden.formservice';
 
 @Component({
@@ -48,12 +50,25 @@ export class VorgangDetailPageComponent implements OnInit {
     private vorgangService: VorgangService,
     private vorgangCommandService: VorgangCommandService,
     private loeschAnforderungService: LoeschAnforderungService,
+    public snackbarService: SnackBarService,
+    public navigationService: NavigationService,
   ) {}
 
   ngOnInit(): void {
-    this.vorgangStateResource$ = this.vorgangService.getVorgangWithEingang();
+    this.vorgangStateResource$ = this.vorgangService
+      .getVorgangWithEingang()
+      .pipe(
+        tap((resource: StateResource<VorgangWithEingangResource>) => this.handleApiError(resource)),
+      );
     this.revokeCommandStateResource$ = this.vorgangCommandService.getRevokeCommand();
     this.vorgangLoeschenCommandStateResource$ =
       this.loeschAnforderungService.getEndgueltigLoeschenCommand();
   }
+
+  handleApiError(resource: StateResource<VorgangWithEingangResource>) {
+    if (isResourceNotFoundError(resource.error)) {
+      this.snackbarService.showInfo(Messages.HTTP_STATUS_VORGANG_NOT_FOUND);
+      this.navigationService.navigateToVorgangList();
+    }
+  }
 }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
index 910757039e1fdfe3e1b5ff885a2491687d92cfa2..5a6d84231e9b41aa3bc51655315edd6ff5e4e531 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
@@ -49,7 +49,7 @@ import {
 } from '@ods/component';
 import {
   AttachmentComponent,
-  AttachmentContainerComponent,
+  AttachmentWrapperComponent,
   BescheidGenerateIconComponent,
   BescheidStatusTextComponent,
   BescheidUploadIconComponent,
@@ -80,11 +80,9 @@ import { VorgangDetailAreaComponent } from './vorgang-detail-page/vorgang-detail
 import { VorgangDetailFormularButtonsComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component';
 import { VorgangDetailAntragDataComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component';
 import { VorgangDetailEingangHeaderComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component';
-import { VorgangDetailAttachmentListComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component';
+import { VorgangDetailDateienContainerComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-dateien-container/vorgang-detail-dateien-container.component';
 import { VorgangDetailFormDataTableComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component';
 import { VorgangDetailFormularDatenComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component';
-import { VorgangDetailMetaDataComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component';
-import { VorgangDetailRepresentationListComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component';
 import { VorgangDetailHeaderComponent } from './vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component';
 import { VorgangDetailBackButtonContainerComponent } from './vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component';
 import { VorgangDetailBackButtonComponent } from './vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component';
@@ -155,7 +153,7 @@ const routes: Routes = [
     BescheidUploadIconComponent,
     BescheidGenerateIconComponent,
     AttachmentComponent,
-    AttachmentContainerComponent,
+    AttachmentWrapperComponent,
     ButtonWithSpinnerComponent,
     FileUploadEditorComponent,
     SingleFileUploadEditorComponent,
@@ -185,9 +183,6 @@ const routes: Routes = [
     VorgangDetailBackButtonContainerComponent,
     VorgangDetailFormularDatenComponent,
     VorgangDetailAntragDataComponent,
-    VorgangDetailMetaDataComponent,
-    VorgangDetailAttachmentListComponent,
-    VorgangDetailRepresentationListComponent,
     VorgangDetailMoreMenuComponent,
     VorgangExportContainerComponent,
     ProcessVorgangContainerComponent,
@@ -216,13 +211,11 @@ const routes: Routes = [
     VorgangDetailBescheidenResultAttachmentsComponent,
     VorgangDetailBescheidenBescheidVersendenComponent,
     VorgangDetailBescheidenResultNachrichtComponent,
+    VorgangDetailDateienContainerComponent,
   ],
   exports: [
     VorgangDetailAntragstellerComponent,
     VorgangDetailAntragDataComponent,
-    VorgangDetailMetaDataComponent,
-    VorgangDetailAttachmentListComponent,
-    VorgangDetailRepresentationListComponent,
     VorgangDetailBescheidenComponent,
   ],
 })
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.html
index f1ac25eb71af847bdcb522fe3f231474f1341c78..dc08624feba50617540824639b130daa51881517 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.html
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.html
@@ -30,6 +30,7 @@
   class="search-field"
   data-test-id="search-form"
 >
+  <span aria-live="polite" class="sr-only" role="status">{{ searchResultPreviewLabel }}</span>
   <button
     #searchSubmitButton
     type="submit"
@@ -61,14 +62,14 @@
       (optionSelected)="formService.submitByPreviewList($event.option.value, searchString)"
     >
       <ozgcloud-spinner
-        [stateResource]="vorgangSearchPreviewList"
-        [class.autocomplete-spinner]="vorgangSearchPreviewList.loading"
+        [stateResource]="vorgangListPreview"
+        [class.autocomplete-spinner]="vorgangListPreview.loading"
       ></ozgcloud-spinner>
 
-      <ng-container *ngIf="vorgangSearchPreviewList.resource" data-test-id="search-preview-list">
+      <ng-container *ngIf="vorgangListPreview.resource" data-test-id="search-preview-list">
         <mat-option
           *ngFor="
-            let vorgang of vorgangSearchPreviewList.resource
+            let vorgang of vorgangListPreview.resource
               | toEmbeddedResources: vorgangListLinkRel.VORGANG_HEADER_LIST
           "
           [value]="vorgang"
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts
index 9fe1622edc1c551c7bff4d9ed5cb9ed910bceb40..ca73c782d282523f6ae32f0ef50fa9ec872d217f 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts
@@ -54,7 +54,11 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
 import { NavigationEnd, Router, RouterEvent } from '@angular/router';
 import { RouterTestingModule } from '@angular/router/testing';
 import { getDataTestClassOf, getDataTestIdOf } from 'libs/tech-shared/test/data-test';
-import { createVorgangListResource } from 'libs/vorgang-shared/test/vorgang';
+import {
+  createVorgangListResource,
+  createVorgangListResourceWithResource,
+  createVorgangResource,
+} from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { BehaviorSubject, ReplaySubject, Subject, of } from 'rxjs';
 import { VorgangSearchAutocompleteOptionsContentComponent } from './vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component';
@@ -186,6 +190,66 @@ describe('VorgangSearchComponent', () => {
     });
   });
 
+  describe('set vorgangSearchPreviewList', () => {
+    it('should set vorgangPreview', () => {
+      const vorgangList = createStateResource(createVorgangListResource());
+
+      component.vorgangSearchPreviewList = vorgangList;
+
+      expect(component.vorgangListPreview).toEqual(vorgangList);
+    });
+
+    it('should call buildSearchResultPreviewLabel', () => {
+      component.buildSearchResultPreviewLabel = jest.fn();
+      const vorgangList = createStateResource(createVorgangListResource());
+
+      component.vorgangSearchPreviewList = vorgangList;
+
+      expect(component.buildSearchResultPreviewLabel).toBeCalledWith(vorgangList);
+    });
+
+    it('should set previewLabel', () => {
+      component.buildSearchResultPreviewLabel = jest.fn(() => 'test');
+      const vorgangList = createStateResource(createVorgangListResource());
+
+      component.vorgangSearchPreviewList = vorgangList;
+
+      expect(component.searchResultPreviewLabel).toBe('test');
+    });
+  });
+
+  describe('buildSearchResultPreviewLabel', () => {
+    it('should return label for many search results', () => {
+      const vorgangList = createStateResource(createVorgangListResource());
+
+      const result = component.buildSearchResultPreviewLabel(vorgangList);
+
+      expect(result).toBe(
+        '10 Vorschläge werden angezeigt, nutze Pfeiltaste nach unten, um diese zu erreichen',
+      );
+    });
+
+    it('should return label for one search result', () => {
+      const vorgangList = createStateResource(
+        createVorgangListResourceWithResource([createVorgangResource()]),
+      );
+
+      const result = component.buildSearchResultPreviewLabel(vorgangList);
+
+      expect(result).toBe(
+        'Ein Vorschlag wird angezeigt, nutze Pfeiltaste nach unten, um den zu erreichen',
+      );
+    });
+
+    it('should return empty string', () => {
+      const vorgangList = createStateResource(null);
+
+      const result = component.buildSearchResultPreviewLabel(vorgangList);
+
+      expect(result).toBe(EMPTY_STRING);
+    });
+  });
+
   describe('search clear button', () => {
     beforeEach(() => {
       searchStringSubj.next('test');
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.ts
index 5375e849b6359a8ba54dd883b83ed8da5daae844..7857c502c95a7b38bed14c9a85ef50d8a748a68a 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.ts
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.ts
@@ -21,7 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { StateResource, isNotNil } from '@alfa-client/tech-shared';
+import {
+  EMPTY_STRING,
+  StateResource,
+  getEmbeddedResources,
+  isNotNil,
+} from '@alfa-client/tech-shared';
 import {
   VorgangHeaderLinkRel,
   VorgangListLinkRel,
@@ -51,7 +56,12 @@ import { VorgangSearchFormService } from './vorgang-search.formservice';
   providers: [VorgangSearchFormService],
 })
 export class VorgangSearchComponent implements OnInit, OnDestroy {
-  @Input() vorgangSearchPreviewList: StateResource<VorgangListResource>;
+  @Input() set vorgangSearchPreviewList(
+    vorgangListStateResource: StateResource<VorgangListResource>,
+  ) {
+    this.vorgangListPreview = vorgangListStateResource;
+    this.searchResultPreviewLabel = this.buildSearchResultPreviewLabel(vorgangListStateResource);
+  }
   @Input() searchString: string;
 
   @Output() public clearVorgangSearchPreviewList: EventEmitter<void> = new EventEmitter<void>();
@@ -60,6 +70,8 @@ export class VorgangSearchComponent implements OnInit, OnDestroy {
   @ViewChild('searchSubmitButton') searchSubmitButton: MatButton;
   @ViewChild('searchAutoComplete') searchAutoComplete: MatAutocomplete;
 
+  vorgangListPreview: StateResource<VorgangListResource>;
+  searchResultPreviewLabel: string = '';
   previouslyEnteredSearchValue: string;
   private subscription: Subscription;
 
@@ -101,6 +113,20 @@ export class VorgangSearchComponent implements OnInit, OnDestroy {
     }
   }
 
+  buildSearchResultPreviewLabel(
+    vorgangListStateResource: StateResource<VorgangListResource>,
+  ): string {
+    const previewListLength = getEmbeddedResources(
+      vorgangListStateResource,
+      this.vorgangListLinkRel.VORGANG_HEADER_LIST,
+    )?.length;
+    if (previewListLength === 1)
+      return 'Ein Vorschlag wird angezeigt, nutze Pfeiltaste nach unten, um den zu erreichen';
+    if (previewListLength > 1)
+      return `${previewListLength} Vorschläge werden angezeigt, nutze Pfeiltaste nach unten, um diese zu erreichen`;
+    return EMPTY_STRING;
+  }
+
   private isRelatedTargetSearchButton(event: FocusEvent): boolean {
     return event.relatedTarget === this.searchSubmitButton._elementRef.nativeElement;
   }
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.spec.ts
index f84d501a719fb4fe3a75a86a22a2ed92757f2850..e9d054d5197c95f9912ce6b5a787df923694d446 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.spec.ts
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.spec.ts
@@ -21,9 +21,6 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { FormControl, UntypedFormBuilder } from '@angular/forms';
-import { Params } from '@angular/router';
-import { faker } from '@faker-js/faker';
 import { NavigationService } from '@alfa-client/navigation-shared';
 import { EMPTY_STRING, encodeUrlForEmbedding } from '@alfa-client/tech-shared';
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
@@ -32,6 +29,9 @@ import {
   VorgangListService,
   VorgangResource,
 } from '@alfa-client/vorgang-shared';
+import { FormControl, UntypedFormBuilder } from '@angular/forms';
+import { Params } from '@angular/router';
+import { faker } from '@faker-js/faker';
 import { ResourceUri, getUrl } from '@ngxp/rest';
 import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang';
 import { Observable, of } from 'rxjs';
@@ -131,15 +131,6 @@ describe('VorgangSearchFormService', () => {
 
         expect(shouldSearch).toBeFalsy();
       });
-
-      it('on searchString is equals lastsearchString', () => {
-        formService.lastSearchString = VALID_SEARCH_STRING;
-        formService.isSearchInputNotPristine = jest.fn().mockReturnValue(true);
-
-        const shouldSearch: boolean = formService.shouldSearchForPreview(VALID_SEARCH_STRING);
-
-        expect(shouldSearch).toBeFalsy();
-      });
     });
 
     describe('should return true', () => {
@@ -148,7 +139,7 @@ describe('VorgangSearchFormService', () => {
         formService.isSearchInputNotPristine = jest.fn().mockReturnValue(true);
       });
 
-      it('on searchInput is NOT pristine, has minLength and is not lastSearchString', () => {
+      it('on searchInput is NOT pristine and has minLength', () => {
         const shouldSearch: boolean = formService.shouldSearchForPreview(VALID_SEARCH_STRING);
 
         expect(shouldSearch).toBeTruthy();
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.ts
index 3a65e9250ae11831cf30e208f7898e93a78ffeaf..bf88a1381c9a827c61a71dc204f5cbaf820ca63a 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.ts
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.ts
@@ -21,9 +21,6 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable, OnDestroy } from '@angular/core';
-import { FormGroup, UntypedFormBuilder, UntypedFormControl } from '@angular/forms';
-import { Params } from '@angular/router';
 import { NavigationService } from '@alfa-client/navigation-shared';
 import {
   EMPTY_STRING,
@@ -37,7 +34,10 @@ import {
   VorgangListService,
   VorgangResource,
 } from '@alfa-client/vorgang-shared';
-import { isEmpty, isEqual } from 'lodash-es';
+import { Injectable, OnDestroy } from '@angular/core';
+import { FormGroup, UntypedFormBuilder, UntypedFormControl } from '@angular/forms';
+import { Params } from '@angular/router';
+import { isEmpty } from 'lodash-es';
 import { Observable, Subscription } from 'rxjs';
 import { debounceTime, distinctUntilChanged, first, tap } from 'rxjs/operators';
 
@@ -100,9 +100,7 @@ export class VorgangSearchFormService implements OnDestroy {
 
   shouldSearchForPreview(value: string): boolean {
     return (
-      this.isSearchInputNotPristine() &&
-      hasMinLength(value, this.PREVIEW_SEARCH_STRING_MIN_LENGTH) &&
-      !isEqual(this.lastSearchString, value)
+      this.isSearchInputNotPristine() && hasMinLength(value, this.PREVIEW_SEARCH_STRING_MIN_LENGTH)
     );
   }
 
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.html
index 5e95367c03a46c38103869483604b2442dc0fa7b..9bf2265a277651fe8d40eff1a80ad736136077ea 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.html
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.html
@@ -6,6 +6,9 @@
     ></ozgcloud-svgicon>
   </ng-container>
   <ng-template #defaultFrist>
-    <ozgcloud-icon icon="update" data-test-class="wiedervorlage-icon-default"></ozgcloud-icon>
+    <ozgcloud-svgicon
+      svgIcon="update"
+      data-test-class="wiedervorlage-icon-default"
+    ></ozgcloud-svgicon>
   </ng-template>
 </div>
diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
index 508ab793ded8f30eb496de410dea11af6e79b417..57cfeeab38cb013afb230703102924d436b2acd0 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
@@ -64,6 +64,7 @@ export enum VorgangWithEingangLinkRel {
   BESCHEID_DRAFT = 'bescheidDraft',
   BESCHEIDE = 'bescheide',
   UEBERSPRINGEN_UND_ABSCHLIESSEN = 'ueberspringen_und_abschliessen',
+  DOWNLOAD_ATTACHMENTS = 'downloadAttachments',
 }
 
 export enum LoeschAnforderungLinkRel {
diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.html
index f0c81c71c4fc151f86c17011eabc9193f48f2cef..4ae91cb40e746eef978cc1682f431ec3ab17e9f1 100644
--- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.html
+++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.html
@@ -52,7 +52,7 @@
     </div>
   </div>
   <div class="flex min-w-0 flex-1 flex-col gap-2">
-    <div class="text-base font-medium">{{ vorgang.name }}</div>
+    <div data-test-id="name" class="text-base font-medium">{{ vorgang.name }}</div>
     <div>
       <alfa-vorgang-nummer class="vorgang-nummer" [vorgang]="vorgang"></alfa-vorgang-nummer>
     </div>
diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts
index 2d312f19021b016c3985e0b17b487fc982210f79..68e9ff8f95bb4ffb237ddc3b5863f15a84ffee44 100644
--- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts
+++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts
@@ -21,21 +21,25 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ApiRootLinkRel } from '@alfa-client/api-root-shared';
 import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
 import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
-import { OzgcloudIconComponent, PostfachIconComponent } from '@alfa-client/ui';
+import {
+  OzgcloudIconComponent,
+  OzgcloudSvgIconComponent,
+  PostfachIconComponent,
+} from '@alfa-client/ui';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
 import { HasAnyLinkPipe } from 'libs/tech-shared/src/lib/pipe/has-any-link.pipe';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangStatistic } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
+import { WiedervorlageIconComponent } from '../../../../../../vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component';
 import { VorgangSearchViewItemContainerComponent } from './vorgang-search-view-item-container/vorgang-search-view-item-container.component';
 import { VorgangViewItemContainerComponent } from './vorgang-view-item-container/vorgang-view-item-container.component';
 import { VorgangViewItemComponent } from './vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component';
 import { VorgangViewsMenuComponent } from './vorgang-views-menu.component';
-import { WiedervorlageIconComponent } from '../../../../../../vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component';
 
 describe('VorgangViewsMenuComponent', () => {
   let component: VorgangViewsMenuComponent;
@@ -63,6 +67,7 @@ describe('VorgangViewsMenuComponent', () => {
         MockComponent(VorgangViewItemComponent),
         MockComponent(VorgangSearchViewItemContainerComponent),
         MockComponent(OzgcloudIconComponent),
+        MockComponent(OzgcloudSvgIconComponent),
         MockComponent(PostfachIconComponent),
       ],
     }).compileComponents();
diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.model.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.model.ts
index b24c2d66850741f13a5f0b63a6f7b9284704a756..3029e68a26c92c943b277675a974bc2e1a47391d 100644
--- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.model.ts
+++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.model.ts
@@ -22,7 +22,6 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BinaryFileListResource } from '@alfa-client/binary-file-shared';
-import { CommandOrder, CreateCommand } from '@alfa-client/command-shared';
 import { ListResource, StateResource } from '@alfa-client/tech-shared';
 import { Resource, ResourceUri } from '@ngxp/rest';
 import { BehaviorSubject } from 'rxjs';
@@ -39,11 +38,6 @@ export interface Wiedervorlage {
 export interface WiedervorlageResource extends Wiedervorlage, Resource {}
 export interface WiedervorlageListResource extends ListResource {}
 
-export interface CreateWiedervorlageCommand extends CreateCommand {
-  order: CommandOrder;
-  wiedervorlage: Wiedervorlage;
-}
-
 export interface BinaryFileListByWiedervorlageUri {
   [uri: ResourceUri]: BehaviorSubject<StateResource<BinaryFileListResource>>;
 }
diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts
index a6fda05d4aae0d6cbc82268e5e0ac05f1655af0b..70080850adac9584f26c3c39f14134fa589a7e0f 100644
--- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts
+++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts
@@ -283,7 +283,7 @@ describe('WiedervorlageService', () => {
       expect(commandService.createCommand).toHaveBeenCalledWith(
         wiedervorlageResource,
         WiedervorlageLinkRel.EDIT,
-        { order: CommandOrder.EDIT_WIEDERVORLAGE, wiedervorlage, body: null },
+        { order: CommandOrder.EDIT_WIEDERVORLAGE, body: wiedervorlage },
       );
     });
 
@@ -339,7 +339,7 @@ describe('WiedervorlageService', () => {
     it('should call command service', () => {
       service.createWiedervorlage(wiedervorlage).subscribe();
 
-      const command = { order: CommandOrder.CREATE_WIEDERVORLAGE, wiedervorlage, body: null };
+      const command = { order: CommandOrder.CREATE_WIEDERVORLAGE, body: wiedervorlage };
       expect(commandService.createCommand).toHaveBeenCalledWith(
         service.wiedervorlageList$.value.resource,
         WiedervorlageListLinkRel.CREATE_WIEDERVORLAGE,
diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts
index c9633abfedc9521786c49655796b3304e4a3972e..821e6e7d19a57ef6dfe5b77cd0603985b3149296 100644
--- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts
+++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts
@@ -23,7 +23,6 @@
  */
 import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared';
 import {
-  Command,
   CommandOrder,
   CommandResource,
   CommandService,
@@ -54,7 +53,6 @@ import { WiedervorlageLinkRel, WiedervorlageListLinkRel } from './wiedervorlage.
 import { WiedervorlageMessages } from './wiedervorlage.message';
 import {
   BinaryFileListByWiedervorlageUri,
-  CreateWiedervorlageCommand,
   Wiedervorlage,
   WiedervorlageListResource,
   WiedervorlageResource,
@@ -274,8 +272,8 @@ export class WiedervorlageService implements OnDestroy {
     );
   }
 
-  private buildCreateWiedervorlageCommand(wiedervorlage: Wiedervorlage): Command {
-    return <any>{ order: CommandOrder.CREATE_WIEDERVORLAGE, wiedervorlage, body: null };
+  private buildCreateWiedervorlageCommand(wiedervorlage: Wiedervorlage): CreateCommand {
+    return { order: CommandOrder.CREATE_WIEDERVORLAGE, body: wiedervorlage };
   }
 
   public saveWiedervorlage(
@@ -311,8 +309,8 @@ export class WiedervorlageService implements OnDestroy {
     );
   }
 
-  private buildEditWiedervorlageCommand(wiedervorlage: Wiedervorlage): CreateWiedervorlageCommand {
-    return { order: CommandOrder.EDIT_WIEDERVORLAGE, wiedervorlage, body: null };
+  private buildEditWiedervorlageCommand(wiedervorlage: Wiedervorlage): CreateCommand {
+    return { order: CommandOrder.EDIT_WIEDERVORLAGE, body: wiedervorlage };
   }
 
   proceedAfterReceiveCommand(
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.html
index 62717bd101780a3e2c58031f1a1404640613ffcb..c472eaa9ff02c349f6db5a95cef29902f0a5a76a 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.html
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.html
@@ -24,7 +24,7 @@
 
 -->
 <alfa-vertical-binary-file-list
-  [fileListResource]="attachments$ | async"
+  [binaryFileListStateResource]="attachments$ | async"
   [deletable]="false"
   data-test-id="wiedervorlage-attachment-list"
 >
diff --git a/alfa-client/package-lock.json b/alfa-client/package-lock.json
index d98128ff37fbc9a75656282a0e5652ee59966c91..a7e9f6cfe77a4da3de7f151bdcbd299486c59c20 100644
--- a/alfa-client/package-lock.json
+++ b/alfa-client/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "alfa",
-  "version": "0.3.0-SNAPSHOT",
+  "version": "0.7.0-SNAPSHOT",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "alfa",
-      "version": "0.3.0-SNAPSHOT",
+      "version": "0.7.0-SNAPSHOT",
       "license": "MIT",
       "dependencies": {
         "@angular/animations": "17.3.10",
@@ -32,6 +32,7 @@
         "angular-oauth2-oidc-jwks": "17.0.2",
         "class-variance-authority": "^0.7.0",
         "date-fns": "^2.30.0",
+        "decompress": "^4.2.1",
         "file-saver": "2.0.5",
         "include-media": "^1.4.10",
         "js-base64": "^3.7.7",
@@ -88,7 +89,7 @@
         "autoprefixer": "^10.4.19",
         "cypress": "13.6.2",
         "cypress-file-upload": "5.0.8",
-        "cypress-mochawesome-reporter": "3.6.0",
+        "cypress-mochawesome-reporter": "3.8",
         "cypress-real-events": "^1.12.0",
         "cypress-timestamps": "^1.2.3",
         "eslint": "8.57.0",
@@ -6191,11 +6192,6 @@
         "url": "https://github.com/sponsors/epoberezkin"
       }
     },
-    "node_modules/@eslint/eslintrc/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
-    },
     "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
       "version": "1.1.11",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -6219,17 +6215,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
     "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
       "version": "0.4.1",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -6480,6 +6465,14 @@
         "node": ">=8"
       }
     },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
     "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
       "version": "4.1.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/find-up/-/find-up-4.1.0.tgz",
@@ -6492,6 +6485,18 @@
         "node": ">=8"
       }
     },
+    "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+      "version": "3.14.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
     "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
       "version": "5.0.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/locate-path/-/locate-path-5.0.0.tgz",
@@ -16124,6 +16129,26 @@
         "node": ">=14.15.0"
       }
     },
+    "node_modules/@yarnpkg/parsers/node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "node_modules/@yarnpkg/parsers/node_modules/js-yaml": {
+      "version": "3.14.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
     "node_modules/@zkochan/js-yaml": {
       "version": "0.0.6",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz",
@@ -16135,11 +16160,6 @@
         "js-yaml": "bin/js-yaml.js"
       }
     },
-    "node_modules/@zkochan/js-yaml/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
-    },
     "node_modules/abab": {
       "version": "2.0.6",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/abab/-/abab-2.0.6.tgz",
@@ -16498,12 +16518,9 @@
       "devOptional": true
     },
     "node_modules/argparse": {
-      "version": "1.0.10",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "dependencies": {
-        "sprintf-js": "~1.0.2"
-      }
+      "version": "2.0.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
     },
     "node_modules/aria-hidden": {
       "version": "1.2.4",
@@ -17731,15 +17748,36 @@
         "ieee754": "^1.1.13"
       }
     },
+    "node_modules/buffer-alloc": {
+      "version": "1.2.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+      "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+      "license": "MIT",
+      "dependencies": {
+        "buffer-alloc-unsafe": "^1.1.0",
+        "buffer-fill": "^1.0.0"
+      }
+    },
+    "node_modules/buffer-alloc-unsafe": {
+      "version": "1.1.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+      "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+      "license": "MIT"
+    },
     "node_modules/buffer-crc32": {
       "version": "0.2.13",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
       "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
-      "dev": true,
       "engines": {
         "node": "*"
       }
     },
+    "node_modules/buffer-fill": {
+      "version": "1.0.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/buffer-fill/-/buffer-fill-1.0.0.tgz",
+      "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==",
+      "license": "MIT"
+    },
     "node_modules/buffer-from": {
       "version": "1.1.2",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -19562,10 +19600,11 @@
       }
     },
     "node_modules/cypress-mochawesome-reporter": {
-      "version": "3.6.0",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/cypress-mochawesome-reporter/-/cypress-mochawesome-reporter-3.6.0.tgz",
-      "integrity": "sha512-NeYpeZVB5YCU10I3a1yA2qHt+YREo0jZw4Gj83JTJ7YX/ZLFfd8MYKl2O19d/yYC8np/fpMufp5gt3ympd9DWQ==",
+      "version": "3.8.2",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/cypress-mochawesome-reporter/-/cypress-mochawesome-reporter-3.8.2.tgz",
+      "integrity": "sha512-oJZkNzhNmN9ZD+LmZyFuPb8aWaIijyHyqYh52YOBvR6B6ckfJNCHP3A98a+/nG0H4t46CKTNwo+wNpMa4d2kjA==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "commander": "^10.0.1",
         "fs-extra": "^10.0.1",
@@ -19871,6 +19910,221 @@
         "node": ">=0.10"
       }
     },
+    "node_modules/decompress": {
+      "version": "4.2.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decompress/-/decompress-4.2.1.tgz",
+      "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==",
+      "license": "MIT",
+      "dependencies": {
+        "decompress-tar": "^4.0.0",
+        "decompress-tarbz2": "^4.0.0",
+        "decompress-targz": "^4.0.0",
+        "decompress-unzip": "^4.0.1",
+        "graceful-fs": "^4.1.10",
+        "make-dir": "^1.0.0",
+        "pify": "^2.3.0",
+        "strip-dirs": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/decompress-tar": {
+      "version": "4.1.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decompress-tar/-/decompress-tar-4.1.1.tgz",
+      "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
+      "license": "MIT",
+      "dependencies": {
+        "file-type": "^5.2.0",
+        "is-stream": "^1.1.0",
+        "tar-stream": "^1.5.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/decompress-tar/node_modules/bl": {
+      "version": "1.2.3",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/bl/-/bl-1.2.3.tgz",
+      "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
+      "license": "MIT",
+      "dependencies": {
+        "readable-stream": "^2.3.5",
+        "safe-buffer": "^5.1.1"
+      }
+    },
+    "node_modules/decompress-tar/node_modules/is-stream": {
+      "version": "1.1.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decompress-tar/node_modules/isarray": {
+      "version": "1.0.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+      "license": "MIT"
+    },
+    "node_modules/decompress-tar/node_modules/readable-stream": {
+      "version": "2.3.8",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/readable-stream/-/readable-stream-2.3.8.tgz",
+      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+      "license": "MIT",
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/decompress-tar/node_modules/string_decoder": {
+      "version": "1.1.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "node_modules/decompress-tar/node_modules/tar-stream": {
+      "version": "1.6.2",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/tar-stream/-/tar-stream-1.6.2.tgz",
+      "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
+      "license": "MIT",
+      "dependencies": {
+        "bl": "^1.0.0",
+        "buffer-alloc": "^1.2.0",
+        "end-of-stream": "^1.0.0",
+        "fs-constants": "^1.0.0",
+        "readable-stream": "^2.3.0",
+        "to-buffer": "^1.1.1",
+        "xtend": "^4.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/decompress-tarbz2": {
+      "version": "4.1.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
+      "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
+      "license": "MIT",
+      "dependencies": {
+        "decompress-tar": "^4.1.0",
+        "file-type": "^6.1.0",
+        "is-stream": "^1.1.0",
+        "seek-bzip": "^1.0.5",
+        "unbzip2-stream": "^1.0.9"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/decompress-tarbz2/node_modules/file-type": {
+      "version": "6.2.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/file-type/-/file-type-6.2.0.tgz",
+      "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/decompress-tarbz2/node_modules/is-stream": {
+      "version": "1.1.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decompress-targz": {
+      "version": "4.1.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decompress-targz/-/decompress-targz-4.1.1.tgz",
+      "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
+      "license": "MIT",
+      "dependencies": {
+        "decompress-tar": "^4.1.1",
+        "file-type": "^5.2.0",
+        "is-stream": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/decompress-targz/node_modules/is-stream": {
+      "version": "1.1.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decompress-unzip": {
+      "version": "4.0.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
+      "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==",
+      "license": "MIT",
+      "dependencies": {
+        "file-type": "^3.8.0",
+        "get-stream": "^2.2.0",
+        "pify": "^2.3.0",
+        "yauzl": "^2.4.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/decompress-unzip/node_modules/file-type": {
+      "version": "3.9.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/file-type/-/file-type-3.9.0.tgz",
+      "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decompress-unzip/node_modules/get-stream": {
+      "version": "2.3.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/get-stream/-/get-stream-2.3.1.tgz",
+      "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==",
+      "license": "MIT",
+      "dependencies": {
+        "object-assign": "^4.0.1",
+        "pinkie-promise": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/decompress/node_modules/make-dir": {
+      "version": "1.3.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/make-dir/-/make-dir-1.3.0.tgz",
+      "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+      "license": "MIT",
+      "dependencies": {
+        "pify": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/decompress/node_modules/make-dir/node_modules/pify": {
+      "version": "3.0.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/pify/-/pify-3.0.0.tgz",
+      "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/deep-equal": {
       "version": "2.2.3",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/deep-equal/-/deep-equal-2.2.3.tgz",
@@ -20907,11 +21161,6 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
-    "node_modules/eslint/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
-    },
     "node_modules/eslint/node_modules/brace-expansion": {
       "version": "1.1.11",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -20995,17 +21244,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/eslint/node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
     "node_modules/eslint/node_modules/json-schema-traverse": {
       "version": "0.4.1",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -21631,7 +21869,6 @@
       "version": "1.1.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/fd-slicer/-/fd-slicer-1.1.0.tgz",
       "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
-      "dev": true,
       "dependencies": {
         "pend": "~1.2.0"
       }
@@ -21703,6 +21940,15 @@
         "node": ">=14.14"
       }
     },
+    "node_modules/file-type": {
+      "version": "5.2.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/file-type/-/file-type-5.2.0.tgz",
+      "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
     "node_modules/file-uri-to-path": {
       "version": "1.0.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
@@ -24049,6 +24295,12 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/is-natural-number": {
+      "version": "4.0.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/is-natural-number/-/is-natural-number-4.0.1.tgz",
+      "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==",
+      "license": "MIT"
+    },
     "node_modules/is-number": {
       "version": "7.0.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/is-number/-/is-number-7.0.0.tgz",
@@ -26076,12 +26328,11 @@
       "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
     },
     "node_modules/js-yaml": {
-      "version": "3.14.1",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-3.14.1.tgz",
-      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "version": "4.1.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
       "dependencies": {
-        "argparse": "^1.0.7",
-        "esprima": "^4.0.0"
+        "argparse": "^2.0.1"
       },
       "bin": {
         "js-yaml": "bin/js-yaml.js"
@@ -27588,13 +27839,6 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
-    "node_modules/mocha/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true,
-      "peer": true
-    },
     "node_modules/mocha/node_modules/chokidar": {
       "version": "3.5.3",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/chokidar/-/chokidar-3.5.3.tgz",
@@ -27689,19 +27933,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/mocha/node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dev": true,
-      "peer": true,
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
     "node_modules/mocha/node_modules/minimatch": {
       "version": "5.0.1",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/minimatch/-/minimatch-5.0.1.tgz",
@@ -29491,11 +29722,6 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
-    "node_modules/nx/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
-    },
     "node_modules/nx/node_modules/chalk": {
       "version": "4.1.2",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/chalk/-/chalk-4.1.2.tgz",
@@ -29530,17 +29756,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/nx/node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
     "node_modules/nx/node_modules/jsonc-parser": {
       "version": "3.2.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
@@ -29593,7 +29808,6 @@
       "version": "4.1.1",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
-      "devOptional": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -30383,8 +30597,7 @@
     "node_modules/pend": {
       "version": "1.2.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/pend/-/pend-1.2.0.tgz",
-      "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
-      "dev": true
+      "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
     },
     "node_modules/performance-now": {
       "version": "2.1.0",
@@ -30416,6 +30629,27 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/pinkie": {
+      "version": "2.0.4",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/pinkie/-/pinkie-2.0.4.tgz",
+      "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/pinkie-promise": {
+      "version": "2.0.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+      "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
+      "license": "MIT",
+      "dependencies": {
+        "pinkie": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/pirates": {
       "version": "4.0.6",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/pirates/-/pirates-4.0.6.tgz",
@@ -31062,11 +31296,6 @@
         }
       }
     },
-    "node_modules/postcss-loader/node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
-    },
     "node_modules/postcss-loader/node_modules/cosmiconfig": {
       "version": "9.0.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
@@ -31092,17 +31321,6 @@
         }
       }
     },
-    "node_modules/postcss-loader/node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
     "node_modules/postcss-logical": {
       "version": "5.0.4",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/postcss-logical/-/postcss-logical-5.0.4.tgz",
@@ -33380,6 +33598,25 @@
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/secure-compare/-/secure-compare-3.0.1.tgz",
       "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw=="
     },
+    "node_modules/seek-bzip": {
+      "version": "1.0.6",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/seek-bzip/-/seek-bzip-1.0.6.tgz",
+      "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==",
+      "license": "MIT",
+      "dependencies": {
+        "commander": "^2.8.1"
+      },
+      "bin": {
+        "seek-bunzip": "bin/seek-bunzip",
+        "seek-table": "bin/seek-bzip-table"
+      }
+    },
+    "node_modules/seek-bzip/node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "license": "MIT"
+    },
     "node_modules/select-hose": {
       "version": "2.0.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/select-hose/-/select-hose-2.0.0.tgz",
@@ -34642,6 +34879,15 @@
         "node": ">=8"
       }
     },
+    "node_modules/strip-dirs": {
+      "version": "2.1.0",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/strip-dirs/-/strip-dirs-2.1.0.tgz",
+      "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
+      "license": "MIT",
+      "dependencies": {
+        "is-natural-number": "^4.0.1"
+      }
+    },
     "node_modules/strip-final-newline": {
       "version": "2.0.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
@@ -35442,6 +35688,12 @@
       "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==",
       "dev": true
     },
+    "node_modules/to-buffer": {
+      "version": "1.1.1",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/to-buffer/-/to-buffer-1.1.1.tgz",
+      "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==",
+      "license": "MIT"
+    },
     "node_modules/to-fast-properties": {
       "version": "2.0.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -36098,6 +36350,16 @@
         "node": ">=0.8.0"
       }
     },
+    "node_modules/unbzip2-stream": {
+      "version": "1.4.3",
+      "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
+      "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
+      "license": "MIT",
+      "dependencies": {
+        "buffer": "^5.2.1",
+        "through": "^2.3.8"
+      }
+    },
     "node_modules/undici": {
       "version": "6.11.1",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/undici/-/undici-6.11.1.tgz",
@@ -37784,7 +38046,6 @@
       "version": "4.0.2",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/xtend/-/xtend-4.0.2.tgz",
       "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
-      "dev": true,
       "engines": {
         "node": ">=0.4"
       }
@@ -37887,7 +38148,6 @@
       "version": "2.10.0",
       "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yauzl/-/yauzl-2.10.0.tgz",
       "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
-      "dev": true,
       "dependencies": {
         "buffer-crc32": "~0.2.3",
         "fd-slicer": "~1.1.0"
diff --git a/alfa-client/package.json b/alfa-client/package.json
index 941615e48c676d90e015854377c3441e18a98a3e..8dc2364f58bb67444d25979f3fd75136efdac63e 100644
--- a/alfa-client/package.json
+++ b/alfa-client/package.json
@@ -1,6 +1,6 @@
 {
   "name": "alfa",
-  "version": "0.3.0-SNAPSHOT",
+  "version": "0.7.0-SNAPSHOT",
   "license": "MIT",
   "scripts": {
     "start": "nx run alfa:serve --port 4300 --disable-host-check",
@@ -43,7 +43,8 @@
     "cypress:install": "npx cypress install",
     "cypress:open": "npx cypress open --project apps/alfa-e2e",
     "workspace-generator": "nx workspace-generator",
-    "storybook": "nx storybook design-system"
+    "storybook": "nx storybook design-system",
+    "ci-storybook": "nx build-storybook design-system && nx container design-system"
   },
   "private": true,
   "dependencies": {
@@ -70,6 +71,7 @@
     "angular-oauth2-oidc-jwks": "17.0.2",
     "class-variance-authority": "^0.7.0",
     "date-fns": "^2.30.0",
+    "decompress": "^4.2.1",
     "file-saver": "2.0.5",
     "include-media": "^1.4.10",
     "js-base64": "^3.7.7",
@@ -126,7 +128,7 @@
     "autoprefixer": "^10.4.19",
     "cypress": "13.6.2",
     "cypress-file-upload": "5.0.8",
-    "cypress-mochawesome-reporter": "3.6.0",
+    "cypress-mochawesome-reporter": "3.8",
     "cypress-real-events": "^1.12.0",
     "cypress-timestamps": "^1.2.3",
     "eslint": "8.57.0",
@@ -159,4 +161,4 @@
     "ts-node": "10.9.1",
     "typescript": "5.4.5"
   }
-}
\ No newline at end of file
+}
diff --git a/alfa-client/pom.xml b/alfa-client/pom.xml
index 57beed7ab6d0d58e675a3475c8bf14a5603b8923..31c038a64e63e52771d87ecb1085e907e9af2cb8 100644
--- a/alfa-client/pom.xml
+++ b/alfa-client/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>de.ozgcloud.alfa</groupId>
 		<artifactId>alfa</artifactId>
-		<version>2.10.0-SNAPSHOT</version>
+		<version>2.11.0-SNAPSHOT</version>
 	</parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/alfa-server/pom.xml b/alfa-server/pom.xml
index 3b98d77c4c8185451f105def421e6d428750e002..5124be2c496ebd8623a1445b16fdcb0a2074c4f0 100644
--- a/alfa-server/pom.xml
+++ b/alfa-server/pom.xml
@@ -5,7 +5,7 @@
 	<parent>
 		<groupId>de.ozgcloud.alfa</groupId>
 		<artifactId>alfa</artifactId>
-		<version>2.10.0-SNAPSHOT</version>
+		<version>2.11.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>alfa-server</artifactId>
diff --git a/alfa-server/src/main/resources/application-dev.yml b/alfa-server/src/main/resources/application-dev.yml
index 942555d4746e7ec791959ee5b1e41b6995d8f3a6..52ca56a22d8fa5ded4dcecfae01b3e22553c2da1 100644
--- a/alfa-server/src/main/resources/application-dev.yml
+++ b/alfa-server/src/main/resources/application-dev.yml
@@ -9,9 +9,7 @@ server:
 
 ozgcloud:
   feature:
-    vorgang-export: true
     reply-always-allowed: true
-    bescheid-wizard: true
   production: false
   stage:
     production: false
diff --git a/alfa-server/src/main/resources/application-e2e.yml b/alfa-server/src/main/resources/application-e2e.yml
index 2aec3140c37abf27f274da5e99909f1cc0e7d251..585c3a5f701bd2f11ccc56211468786f077bfcd4 100644
--- a/alfa-server/src/main/resources/application-e2e.yml
+++ b/alfa-server/src/main/resources/application-e2e.yml
@@ -8,9 +8,7 @@ keycloak:
 
 ozgcloud:
   feature:
-    vorgang-export: true
     reply-always-allowed: true
-    bescheid-wizard: true
   forwarding:
     lninfo:
       url: classpath:files/LandesnetzInfo.html
diff --git a/alfa-server/src/main/resources/application-local.yml b/alfa-server/src/main/resources/application-local.yml
index a0ed2b50fa6eb31acfb21af7156aa2c0590a7cc9..b113a7052d27746ebf67fdd3600b381e7e658dd5 100644
--- a/alfa-server/src/main/resources/application-local.yml
+++ b/alfa-server/src/main/resources/application-local.yml
@@ -17,9 +17,7 @@ grpc:
 
 ozgcloud:
   feature:
-    vorgang-export: true
     reply-always-allowed: true
-    bescheid-wizard: true
   production: false
   user-assistance:
     documentation:
@@ -28,10 +26,6 @@ ozgcloud:
     url: http://localhost:9092
     profile-template: /api/userProfiles/%s
     search-template: /api/userProfiles/?searchBy={searchBy}
-  xdomea:
-    behoerdenschluessel: "behoerdenschluesselWirdÜberHelmGesetzt"
-    behoerdenschluesselUri: "behoerdenschluesselUriWirdÜberHelmGesetzt"
-    behoerdenschluesselVersion: "behoerdenschluesselVersionWirdÜberHelmGesetzt"
 
 keycloak:
   auth-server-url: http://localhost:8088
diff --git a/alfa-server/src/main/resources/application.yml b/alfa-server/src/main/resources/application.yml
index 8e17178fea49083f2e1a5035d0b27d50c6670e50..ac930de36a83c9b7d962e72dca5ef29eae2fdd57 100644
--- a/alfa-server/src/main/resources/application.yml
+++ b/alfa-server/src/main/resources/application.yml
@@ -91,4 +91,8 @@ ozgcloud:
         - image/jpeg
   user-manager:
     profile-template: /api/userProfiles/%s
-    search-template: /api/userProfiles/?searchBy={searchBy}
\ No newline at end of file
+    search-template: /api/userProfiles/?searchBy={searchBy}
+  xdomea:
+    behoerdenschluessel:
+    behoerdenschluessel-uri:
+    behoerdenschluessel-version:
diff --git a/alfa-service/pom.xml b/alfa-service/pom.xml
index f57d5f690a4cabf8e13bb94d2c7fd98a24a2949e..f2e9a4141f8dc1c75e3769a1671b1ca511714d8c 100644
--- a/alfa-service/pom.xml
+++ b/alfa-service/pom.xml
@@ -31,7 +31,7 @@
 	<parent>
 		<groupId>de.ozgcloud.alfa</groupId>
 		<artifactId>alfa</artifactId>
-		<version>2.10.0-SNAPSHOT</version>
+		<version>2.11.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>alfa-service</artifactId>
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/attachment/AttachmentController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/attachment/AttachmentController.java
index e708645828f0bd692f4763859586a3725db45f12..1211543468abb21bc9b39b98408cd8075adc1710 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/attachment/AttachmentController.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/attachment/AttachmentController.java
@@ -23,33 +23,70 @@
  */
 package de.ozgcloud.alfa.attachment;
 
-import org.springframework.beans.factory.annotation.Autowired;
+import java.io.OutputStream;
+
 import org.springframework.hateoas.CollectionModel;
 import org.springframework.hateoas.EntityModel;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 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.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
 
 import de.ozgcloud.alfa.common.binaryfile.BinaryFileModelAssembler;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileService;
+import de.ozgcloud.alfa.common.zipdownload.ZipDownloadService;
+import de.ozgcloud.alfa.vorgang.VorgangController;
+import lombok.RequiredArgsConstructor;
 
 @RestController
-@RequestMapping(AttachmentController.ATTACHMENT_PATH)
+@RequestMapping(AttachmentController.PATH)
+@RequiredArgsConstructor
 public class AttachmentController {
 
-	static final String ATTACHMENT_PATH = "/api/attachments"; // NOSONAR
+	static final String PATH = "/api/attachments"; // NOSONAR
 
 	static final String PARAM_EINGANG_ID = "eingangId";
 
-	@Autowired
-	private OzgFileService fileService;
-	@Autowired
-	private BinaryFileModelAssembler modelAssembler;
+	private final OzgFileService fileService;
+	private final BinaryFileModelAssembler modelAssembler;
 
 	@GetMapping(params = PARAM_EINGANG_ID)
 	public CollectionModel<EntityModel<OzgFile>> getAllByEingang(@RequestParam String eingangId) {
 		return modelAssembler.toCollectionModel(fileService.getAttachmentsByEingang(eingangId));
 	}
+
+	@RestController
+	@RequestMapping(AttachmentsByVorgangController.PATH)
+	@RequiredArgsConstructor
+	public static class AttachmentsByVorgangController {
+		static final String PATH = "/api/vorgang/{vorgangId}/attachments"; // NOSONAR
+
+		private final OzgFileService fileService;
+		private final ZipDownloadService zipDownloadService;
+		private final VorgangController vorgangController;
+
+		@GetMapping(params = PARAM_EINGANG_ID, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+		public ResponseEntity<StreamingResponseBody> download(@PathVariable String vorgangId, @RequestParam String eingangId) {
+			return ResponseEntity.ok()
+					.header(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s", buildZipName(vorgangId)))
+					.contentType(MediaType.APPLICATION_OCTET_STREAM)
+					.body(out -> createZipFile(out, eingangId));
+		}
+
+		String buildZipName(String vorgangId) {
+			return vorgangController.getVorgang(vorgangId).getNummer() + "_Anhaenge.zip";
+		}
+
+		void createZipFile(OutputStream out, String eingangId) {
+			var ozgFiles = fileService.getAttachmentsByEingang(eingangId);
+			zipDownloadService.write(ozgFiles.toList(), out);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidHistorieProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidHistorieProcessor.java
index 3a134ac79f67c11e6168fe0116bcebbbfe94b24f..836adfdc95b6ca002dc00e842398b34b93279560 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidHistorieProcessor.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidHistorieProcessor.java
@@ -39,6 +39,9 @@ class BescheidHistorieProcessor implements HistorieProcessor {
 	private static final Predicate<Command> IS_NOT_UPDATE_ATTACHED_ITEM = Predicate
 			.not(command -> command.getCommandOrder() == CommandOrder.UPDATE_ATTACHED_ITEM
 					&& IS_BESCHEID_ATTACHED_ITEM.test(command));
+	private static final Predicate<Command> IS_NOT_PATCH_ATTACHED_ITEM = Predicate
+			.not(command -> command.getCommandOrder() == CommandOrder.PATCH_ATTACHED_ITEM
+					&& IS_BESCHEID_ATTACHED_ITEM.test(command));
 
 	@Override
 	public List<Command> process(List<Command> commands) {
@@ -52,6 +55,7 @@ class BescheidHistorieProcessor implements HistorieProcessor {
 				.filter(IS_NOT_DELETE_BESCHEID_COMMAND)
 				.filter(IS_NOT_CREATE_ATTACHED_ITEM)
 				.filter(IS_NOT_UPDATE_ATTACHED_ITEM)
+				.filter(IS_NOT_PATCH_ATTACHED_ITEM)
 				.toList();
 	}
 
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessor.java
index 1977b5ffb63dbf495578eeac0ebce27d6d7a4af5..1846ef681a80e682b12b20e191be1412107212f2 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessor.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessor.java
@@ -12,7 +12,6 @@ import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
 import org.springframework.stereotype.Component;
 
 import de.ozgcloud.alfa.bescheid.BescheidController.BescheidByVorgangController;
-import de.ozgcloud.alfa.common.FeatureToggleProperties;
 import de.ozgcloud.alfa.common.ModelBuilder;
 import de.ozgcloud.alfa.common.command.CommandController.CommandByRelationController;
 import de.ozgcloud.alfa.common.user.CurrentUserService;
@@ -30,7 +29,6 @@ class BescheidVorgangProcessor implements RepresentationModelProcessor<EntityMod
 	static final LinkRelation REL_BESCHEIDE = LinkRelation.of("bescheide");
 
 	private final BescheidService bescheidService;
-	private final FeatureToggleProperties featureToggleProperties;
 	private final CurrentUserService currentUserService;
 
 	@Override
@@ -66,11 +64,11 @@ class BescheidVorgangProcessor implements RepresentationModelProcessor<EntityMod
 	}
 
 	BooleanSupplier isRetrievingDraftAllowed(Vorgang vorgang) {
-		return () -> featureToggleProperties.isBescheidWizard() && isVorgangInBearbeitung(vorgang) && draftExists(vorgang);
+		return () -> isVorgangInBearbeitung(vorgang) && draftExists(vorgang);
 	}
 
 	BooleanSupplier isCreatingDraftAllowed(Vorgang vorgang) {
-		return () -> featureToggleProperties.isBescheidWizard() && isVorgangInBearbeitung(vorgang) && !draftExists(vorgang);
+		return () -> isVorgangInBearbeitung(vorgang) && !draftExists(vorgang);
 	}
 
 	boolean isVorgangInBearbeitung(Vorgang vorgang) {
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/DocumentRemoteService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/DocumentRemoteService.java
index 0cef6022ccd7c3ec41b83c090e732d467d7492a3..628f7a930eb4fd1df57ee334722661b43a980728 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/DocumentRemoteService.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/bescheid/DocumentRemoteService.java
@@ -1,13 +1,9 @@
 package de.ozgcloud.alfa.bescheid;
 
-import java.util.UUID;
-
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import de.ozgcloud.alfa.common.GrpcUtil;
-import de.ozgcloud.alfa.common.binaryfile.FileId;
 import de.ozgcloud.document.DocumentServiceGrpc.DocumentServiceBlockingStub;
 import de.ozgcloud.document.GrpcGetDocumentRequest;
 import net.devh.boot.grpc.client.inject.GrpcClient;
@@ -21,14 +17,6 @@ class DocumentRemoteService {
 	private DocumentMapper documentMapper;
 
 	public Document getDocument(String documentId) {
-		// DUMMY
-		if (StringUtils.equals(documentId, "DOCUMENT_URI")) {
-			return Document.builder()
-					.id(UUID.randomUUID().toString())
-					.fileId(FileId.from("DOCUMENT_FILE_URI"))
-					.build();
-		}
-		//
 		var response = documentServiceStub.getDocument(GrpcGetDocumentRequest.newBuilder().setId(documentId).build());
 		return documentMapper.fromGrpc(response.getDocument());
 	}
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java
index a186d5a1b013d3b0175c22e6be86c07fdfe95963..80238fccb22376ea6e2ff8201f1d7b497a968dae 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java
@@ -12,18 +12,8 @@ import lombok.Setter;
 @ConfigurationProperties(prefix = "ozgcloud.feature")
 public class FeatureToggleProperties {
 
-	/**
-	 * Enable vorgang export(xdomea) feature.
-	 */
-	private boolean vorgangExport = false;
-
 	/**
 	 * Enable mail reply option regardless of other configuration.
 	 */
 	private boolean replyAlwaysAllowed = false;
-
-	/**
-	 * Enable/Disable bescheid wizard feature.
-	 */
-	private boolean bescheidWizard = false;
 }
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandBody.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandBody.java
index 55b885acd5287b15b723de70261722f444ddce02..8bdf5bbab7eee1d9c6040bdc844cc568546e88bd 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandBody.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandBody.java
@@ -44,8 +44,10 @@ import de.ozgcloud.alfa.wiedervorlage.Wiedervorlage;
 		@Type(value = PostfachMail.class, name = "RESEND_POSTFACH_MAIL"),
 		@Type(value = AssignUserCommandBody.class, name = "ASSIGN_USER"),
 		@Type(value = RedirectRequest.class, name = "REDIRECT_VORGANG"),
-		@Type(value = Wiedervorlage.class, name = "WIEDERVORLAGE"),
-		@Type(value = Kommentar.class, name = "KOMMENTAR"),
+		@Type(value = Wiedervorlage.class, name = "CREATE_WIEDERVORLAGE"),
+		@Type(value = Wiedervorlage.class, name = "EDIT_WIEDERVORLAGE"),
+		@Type(value = Kommentar.class, name = "CREATE_KOMMENTAR"),
+		@Type(value = Kommentar.class, name = "EDIT_KOMMENTAR"),
 		@Type(value = LoeschAnforderung.class, name = "LOESCH_ANFORDERUNG"),
 		@Type(value = DeleteLoeschAnforderung.class, name = "DELETE_LOESCH_ANFORDERUNG"),
 		@Type(value = Bescheid.class, name = "CREATE_BESCHEID"),
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/zipdownload/ZipDownloadService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/zipdownload/ZipDownloadService.java
new file mode 100644
index 0000000000000000000000000000000000000000..46ddd81e4099efc42772a94ce7e3fd33f1198d3d
--- /dev/null
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/zipdownload/ZipDownloadService.java
@@ -0,0 +1,58 @@
+package de.ozgcloud.alfa.common.zipdownload;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.springframework.stereotype.Service;
+
+import de.ozgcloud.alfa.common.binaryfile.BinaryFileService;
+import de.ozgcloud.alfa.common.file.OzgFile;
+import de.ozgcloud.common.binaryfile.TempFileUtils;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.RequiredArgsConstructor;
+
+@Service
+@RequiredArgsConstructor
+public class ZipDownloadService {
+
+	private final BinaryFileService binaryFileService;
+
+	public void write(List<OzgFile> ozgFiles, OutputStream out) {
+		writeZipFileContent(createZipFile(ozgFiles), out);
+	}
+
+	File createZipFile(List<OzgFile> ozgFiles) {
+		var file = TempFileUtils.createTmpFile().toFile();
+		try (var zipOutputStream = new ZipOutputStream(new FileOutputStream(file))) {
+			ozgFiles.forEach(ozgFile -> addOzgFileToZip(ozgFile, zipOutputStream));
+			return file;
+		} catch (Exception e) {
+			throw new TechnicalException("Error creating zip file", e);
+		}
+	}
+
+	void addOzgFileToZip(OzgFile ozgFile, ZipOutputStream zipOutputStream) {
+		try {
+			zipOutputStream.putNextEntry(new ZipEntry(ozgFile.getName()));
+			binaryFileService.writeFileContent(ozgFile.getId(), zipOutputStream);
+			zipOutputStream.closeEntry();
+		} catch (IOException e) {
+			throw new TechnicalException("Cannot add file to ZIP.", e);
+		}
+	}
+
+	void writeZipFileContent(File zipFile, OutputStream outputStream) {
+		try (var fileInputStream = new FileInputStream(zipFile)) {
+			fileInputStream.transferTo(outputStream);
+		} catch (Exception e) {
+			throw new TechnicalException("Error writing zip file to output stream", e);
+		}
+	}
+
+}
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarCommand.java b/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarCommand.java
deleted file mode 100644
index 5612b0af7dca140289899ef1ecbda0ba7e89dcee..0000000000000000000000000000000000000000
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.alfa.kommentar;
-
-import jakarta.validation.Valid;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-import de.ozgcloud.alfa.common.command.CommandStatus;
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@Builder
-@Getter
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-@AllArgsConstructor(access = AccessLevel.PACKAGE)
-@EqualsAndHashCode
-class KommentarCommand {
-
-	@JsonIgnore
-	private String id;
-
-	private String order;
-
-	@JsonIgnore
-	private CommandStatus status;
-
-	@Valid
-	private Kommentar kommentar;
-}
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarCommandController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarCommandController.java
index a11c25251682cbc0f3792bb58a810deeee0fd900..85cdc5c7545d2d467f53352c7290b2e2e80264a9 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarCommandController.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarCommandController.java
@@ -35,6 +35,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import de.ozgcloud.alfa.common.command.Command;
 import de.ozgcloud.alfa.common.command.CommandController;
+import de.ozgcloud.alfa.common.command.CreateCommand;
 
 @RestController
 @RequestMapping(KommentarCommandController.KOMMENTAR_COMMANDS)
@@ -46,9 +47,9 @@ public class KommentarCommandController {
 	private KommentarService service;
 
 	@PostMapping
-	public ResponseEntity<Void> editKommentar(@RequestBody KommentarCommand kommentarCommand, @PathVariable String kommentarId,
+	public ResponseEntity<Void> editKommentar(@RequestBody CreateCommand command, @PathVariable String kommentarId,
 			@PathVariable long kommentarVersion) {
-		var createdCommand = service.editKommentar(kommentarCommand.getKommentar(), kommentarId, kommentarVersion);
+		var createdCommand = service.editKommentar((Kommentar) command.getBody(), kommentarId, kommentarVersion);
 
 		return buildResponseLink(createdCommand);
 	}
@@ -67,8 +68,8 @@ public class KommentarCommandController {
 		private KommentarService service;
 
 		@PostMapping
-		public ResponseEntity<Void> createKommentar(@RequestBody KommentarCommand command, @PathVariable String vorgangId) {
-			var createdCommand = service.createKommentar(command.getKommentar(), vorgangId);
+		public ResponseEntity<Void> createKommentar(@RequestBody CreateCommand command, @PathVariable String vorgangId) {
+			var createdCommand = service.createKommentar((Kommentar) command.getBody(), vorgangId);
 
 			return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build();
 		}
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarMapper.java b/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarMapper.java
index d95bb89ce7b65a0167269a71cc1e245d0bc8efb5..57e5fc50b48e34a9bc789f293b4baa7b380d8093 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarMapper.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/kommentar/KommentarMapper.java
@@ -27,16 +27,12 @@ import java.time.ZonedDateTime;
 import java.util.Map;
 
 import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
-import org.mapstruct.MappingConstants;
 import org.mapstruct.NullValueCheckStrategy;
 import org.mapstruct.ReportingPolicy;
-import org.mapstruct.ValueMapping;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import de.ozgcloud.alfa.attachment.AttachmentMapper;
 import de.ozgcloud.vorgang.common.grpc.GrpcObjectMapper;
-import de.ozgcloud.vorgang.grpc.command.GrpcCommand;
 import de.ozgcloud.vorgang.vorgangAttachedItem.GrpcVorgangAttachedItem;
 
 @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
@@ -51,12 +47,6 @@ abstract class KommentarMapper {
 	@Autowired
 	private GrpcObjectMapper grpcObjectMapper;
 
-	@Mapping(target = "kommentar", ignore = true)
-	@Mapping(target = "order", source = "orderString")
-	@ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL)
-	@ValueMapping(source = "UNDEFINED", target = MappingConstants.NULL)
-	abstract KommentarCommand toKommentarCommand(GrpcCommand command);
-
 	public Kommentar fromItem(GrpcVorgangAttachedItem vorgangAttachedItem) {
 		return fromItemMap(grpcObjectMapper.mapFromGrpc(vorgangAttachedItem.getItem()), vorgangAttachedItem.getVersion());
 	}
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/representation/RepresentationController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/representation/RepresentationController.java
index ec181a8640f7f38d35ab43d06714ab8afd48411d..28913930a067740c12c8bf214423b59426f22c54 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/representation/RepresentationController.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/representation/RepresentationController.java
@@ -23,7 +23,6 @@
  */
 package de.ozgcloud.alfa.representation;
 
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.hateoas.CollectionModel;
 import org.springframework.hateoas.EntityModel;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -34,22 +33,23 @@ import org.springframework.web.bind.annotation.RestController;
 import de.ozgcloud.alfa.common.binaryfile.BinaryFileModelAssembler;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileService;
+import lombok.RequiredArgsConstructor;
 
 @RestController
-@RequestMapping(RepresentationController.REPRESENTATIONS_PATH)
+@RequestMapping(RepresentationController.PATH)
+@RequiredArgsConstructor
 public class RepresentationController {
 
-	static final String REPRESENTATIONS_PATH = "/api/representations"; // NOSONAR
+	static final String PATH = "/api/representations"; // NOSONAR
 
 	static final String PARAM_EINGANG_ID = "eingangId";
 
-	@Autowired
-	private OzgFileService fileService;
-	@Autowired
-	private BinaryFileModelAssembler modelAssembler;
+	private final OzgFileService fileService;
+	private final BinaryFileModelAssembler modelAssembler;
 
 	@GetMapping(params = PARAM_EINGANG_ID)
 	public CollectionModel<EntityModel<OzgFile>> getAllByEingang(@RequestParam String eingangId) {
 		return modelAssembler.toCollectionModel(fileService.getRepresentationsByEingang(eingangId));
 	}
+
 }
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProcessor.java
index 6cac7c1b0c048c6b403de6f1065bf5b3bbe974ba..6b111ac3c55ed436df4b141e6115ba419d599905 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProcessor.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProcessor.java
@@ -37,6 +37,7 @@ import org.springframework.hateoas.server.RepresentationModelProcessor;
 import org.springframework.stereotype.Component;
 
 import de.ozgcloud.alfa.attachment.AttachmentController;
+import de.ozgcloud.alfa.attachment.AttachmentController.AttachmentsByVorgangController;
 import de.ozgcloud.alfa.common.ModelBuilder;
 import de.ozgcloud.alfa.common.command.CommandController.CommandByRelationController;
 import de.ozgcloud.alfa.common.user.CurrentUserService;
@@ -56,6 +57,7 @@ class VorgangWithEingangProcessor implements RepresentationModelProcessor<Entity
 
 	static final LinkRelation REL_KOMMENTARE = LinkRelation.of("kommentare");
 	static final LinkRelation REL_ATTACHMENTS = LinkRelation.of("attachments");
+	static final LinkRelation REL_DOWNLOAD_ATTACHMENTS = LinkRelation.of("downloadAttachments");
 	static final LinkRelation REL_REPRESENTATIONS = LinkRelation.of("representations");
 	static final LinkRelation REL_POSTFACH_MAILS = LinkRelation.of("postfachMails");
 	static final LinkRelation REL_VORGANG_FORWARDING = LinkRelation.of("forwarding");
@@ -89,8 +91,10 @@ class VorgangWithEingangProcessor implements RepresentationModelProcessor<Entity
 		return ModelBuilder.fromModel(model)
 				.addLink(linkTo(KommentarByVorgangController.class).slash(vorgang.getId()).slash("kommentars").withRel(REL_KOMMENTARE))
 				.ifMatch(HAS_ATTACHMENTS)
-				.addLink(vorgangWithEingang -> linkTo(methodOn(AttachmentController.class).getAllByEingang(vorgangWithEingang.getEingang().getId()))
-						.withRel(REL_ATTACHMENTS))
+				.addLinks(linkTo(methodOn(AttachmentController.class).getAllByEingang(vorgang.getEingang().getId()))
+						.withRel(REL_ATTACHMENTS),
+						linkTo(methodOn(AttachmentsByVorgangController.class).download(vorgang.getId(), vorgang.getEingang().getId()))
+								.withRel(REL_DOWNLOAD_ATTACHMENTS))
 				.ifMatch(HAS_REPRESENTATIONS)
 				.addLink(vorgangWithEingang -> linkTo(
 						methodOn(RepresentationController.class).getAllByEingang(vorgangWithEingang.getEingang().getId()))
@@ -101,7 +105,7 @@ class VorgangWithEingangProcessor implements RepresentationModelProcessor<Entity
 				.addLink(linkTo(methodOn(ForwardingController.class).findByVorgangId(vorgang.getId())).withRel(REL_VORGANG_FORWARDING))
 				.addLink(linkTo(methodOn(HistorieController.class).getAll(vorgang.getId())).withRel(REL_HISTORIE))
 				.ifMatch(() -> userManagerUrlProvider.isConfiguredForSearchUserProfile() && hasOrganisationsEinheitId(vorgang))
-				.addLink(() -> buildSearchUserProfilesLink(vorgang))
+				.addLink(this::buildSearchUserProfilesLink)
 				.ifMatch(this::isProcessable)
 				.addLink(
 						() -> linkTo(methodOn(CommandByRelationController.class).createCommand(vorgang.getId(), vorgang.getId(), vorgang.getVersion(),
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommand.java b/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommand.java
deleted file mode 100644
index a9cb0e0ea5aa30f4958672fbb168341d2976d0d1..0000000000000000000000000000000000000000
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommand.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.alfa.wiedervorlage;
-
-import jakarta.validation.Valid;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-import de.ozgcloud.alfa.common.command.CommandStatus;
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@Builder(toBuilder = true)
-@Getter
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-@AllArgsConstructor(access = AccessLevel.PACKAGE)
-@EqualsAndHashCode
-class WiedervorlageCommand {
-
-	@JsonIgnore
-	private String id;
-
-	private String order;
-
-	@JsonIgnore
-	private CommandStatus status;
-
-	@Valid
-	private Wiedervorlage wiedervorlage;
-}
\ No newline at end of file
diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandController.java
index 9435cef625d6ce8c64681ea60bc92ec1e73d6091..d621a01dd99a332de8fe0dd6b2b754ccdc9a351a 100644
--- a/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandController.java
+++ b/alfa-service/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandController.java
@@ -34,6 +34,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import de.ozgcloud.alfa.common.command.Command;
 import de.ozgcloud.alfa.common.command.CommandController;
+import de.ozgcloud.alfa.common.command.CreateCommand;
 import de.ozgcloud.alfa.common.command.LegacyOrder;
 import de.ozgcloud.common.errorhandling.TechnicalException;
 import lombok.RequiredArgsConstructor;
@@ -48,7 +49,7 @@ public class WiedervorlageCommandController {
 	private final WiedervorlageService service;
 
 	@PostMapping
-	public ResponseEntity<Void> updateWiedervorlage(@RequestBody WiedervorlageCommand command, @PathVariable String wiedervorlageId,
+	public ResponseEntity<Void> updateWiedervorlage(@RequestBody CreateCommand command, @PathVariable String wiedervorlageId,
 			@PathVariable long wiedervorlageVersion) {
 		var wiedervorlage = service.getById(wiedervorlageId);
 		var createdCommand = createCommand(wiedervorlage, command);
@@ -58,7 +59,7 @@ public class WiedervorlageCommandController {
 		return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build();
 	}
 
-	Command createCommand(Wiedervorlage wiedervorlage, WiedervorlageCommand command) {
+	Command createCommand(Wiedervorlage wiedervorlage, CreateCommand command) {
 		switch (command.getOrder()) {
 			case LegacyOrder.WIEDERVORLAGE_ERLEDIGEN: {
 				return service.erledigen(wiedervorlage);
@@ -67,7 +68,8 @@ public class WiedervorlageCommandController {
 				return service.wiedereroeffnen(wiedervorlage);
 			}
 			case LegacyOrder.EDIT_WIEDERVORLAGE: {
-				return service.editWiedervorlage(updateWiedervorlageByCommand(wiedervorlage, command), wiedervorlage.getId(),
+				return service.editWiedervorlage(updateWiedervorlageByCommand(wiedervorlage, (Wiedervorlage) command.getBody()),
+						wiedervorlage.getId(),
 						wiedervorlage.getVersion());
 			}
 			default:
@@ -75,12 +77,12 @@ public class WiedervorlageCommandController {
 		}
 	}
 
-	Wiedervorlage updateWiedervorlageByCommand(Wiedervorlage wiedervorlage, WiedervorlageCommand command) {
+	Wiedervorlage updateWiedervorlageByCommand(Wiedervorlage wiedervorlage, Wiedervorlage requestBody) {
 		return wiedervorlage.toBuilder()
-				.clearAttachments().attachments(command.getWiedervorlage().getAttachments())
-				.betreff(command.getWiedervorlage().getBetreff())
-				.beschreibung(command.getWiedervorlage().getBeschreibung())
-				.frist(command.getWiedervorlage().getFrist()).build();
+				.clearAttachments().attachments(requestBody.getAttachments())
+				.betreff(requestBody.getBetreff())
+				.beschreibung(requestBody.getBeschreibung())
+				.frist(requestBody.getFrist()).build();
 	}
 
 	@RestController
@@ -93,8 +95,8 @@ public class WiedervorlageCommandController {
 		private final WiedervorlageService service;
 
 		@PostMapping
-		public ResponseEntity<Void> createWiedervorlage(@RequestBody WiedervorlageCommand command, @PathVariable String vorgangId) {
-			var createdCommand = service.createWiedervorlage(command.getWiedervorlage(), vorgangId);
+		public ResponseEntity<Void> createWiedervorlage(@RequestBody CreateCommand command, @PathVariable String vorgangId) {
+			var createdCommand = service.createWiedervorlage((Wiedervorlage) command.getBody(), vorgangId);
 
 			service.updateNextFrist(vorgangId);
 
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/attachment/AttachmentControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/attachment/AttachmentControllerTest.java
index 801e18a6bde57ae9c7d1a6c12a9190a438cee89b..7e7b3a6e20a4aa2ca117acb79ece432c7d5cf57c 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/attachment/AttachmentControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/attachment/AttachmentControllerTest.java
@@ -36,24 +36,29 @@ import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentMatchers;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
 import de.ozgcloud.alfa.common.binaryfile.BinaryFileModelAssembler;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileService;
 import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
+import de.ozgcloud.alfa.common.zipdownload.ZipDownloadService;
+import lombok.SneakyThrows;
 
 class AttachmentControllerTest {
 
-	private final String PATH = AttachmentController.ATTACHMENT_PATH;
-
+	@Spy
 	@InjectMocks
 	private AttachmentController controller;
 	@Mock
 	private BinaryFileModelAssembler modelAssembler;
 	@Mock
 	private OzgFileService fileService;
+	@Mock
+	private ZipDownloadService zipDownloadService;
 
 	private MockMvc mockMvc;
 
@@ -70,27 +75,33 @@ class AttachmentControllerTest {
 			when(fileService.getAttachmentsByEingang(anyString())).thenReturn(Stream.of(OzgFileTestFactory.create()));
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCallEndpoint() throws Exception {
-			callEndpoint();
+		void shouldResponseWithStatusOk() {
+			var result = callEndpoint();
+
+			result.andExpect(status().isOk());
 		}
 
+		@SneakyThrows
 		@Test
-		void shoudlCallFileService() throws Exception {
+		void shoudlCallFileService() {
 			callEndpoint();
 
 			verify(fileService).getAttachmentsByEingang(any());
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCallModelAssembler() throws Exception {
+		void shouldCallModelAssembler() {
 			callEndpoint();
 
 			verify(modelAssembler).toCollectionModel(ArgumentMatchers.<Stream<OzgFile>>any());
 		}
 
-		private void callEndpoint() throws Exception {
-			mockMvc.perform(get(PATH).param(AttachmentController.PARAM_EINGANG_ID, "1")).andExpect(status().isOk());
+		@SneakyThrows
+		private ResultActions callEndpoint() {
+			return mockMvc.perform(get(AttachmentController.PATH).param(AttachmentController.PARAM_EINGANG_ID, "1"));
 		}
 	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/attachment/AttachmentsByVorgangControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/attachment/AttachmentsByVorgangControllerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..54638cb8a8390236ab8fc1c155d8ff3e33759779
--- /dev/null
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/attachment/AttachmentsByVorgangControllerTest.java
@@ -0,0 +1,179 @@
+package de.ozgcloud.alfa.attachment;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+import java.io.OutputStream;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.alfa.attachment.AttachmentController.AttachmentsByVorgangController;
+import de.ozgcloud.alfa.common.binaryfile.BinaryFileModelAssembler;
+import de.ozgcloud.alfa.common.file.OzgFileService;
+import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
+import de.ozgcloud.alfa.common.zipdownload.ZipDownloadService;
+import de.ozgcloud.alfa.vorgang.EingangTestFactory;
+import de.ozgcloud.alfa.vorgang.VorgangController;
+import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
+import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
+import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
+import lombok.SneakyThrows;
+
+class AttachmentsByVorgangControllerTest {
+
+	@Spy
+	@InjectMocks
+	private AttachmentsByVorgangController controller;
+	@Mock
+	private BinaryFileModelAssembler modelAssembler;
+	@Mock
+	private OzgFileService fileService;
+	@Mock
+	private ZipDownloadService zipDownloadService;
+	@Mock
+	private VorgangController vorgangController;
+
+	private MockMvc mockMvc;
+
+	@BeforeEach
+	void initTest() {
+		mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
+	}
+
+	@DisplayName("Download")
+	@Nested
+	class TestDownload {
+		private final String filename = LoremIpsum.getInstance().getWords(1);
+
+		@BeforeEach
+		void setUpMock() {
+			doReturn(filename).when(controller).buildZipName(VorgangHeaderTestFactory.ID);
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldRespondWithStatusOk() {
+			var response = doRequest();
+
+			response.andExpect(status().isOk());
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldBuildZipName() {
+			doRequest();
+
+			verify(controller).buildZipName(VorgangHeaderTestFactory.ID);
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldHaveContentDispositonHeader() {
+			var response = doRequest();
+
+			response.andExpect(header().string(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename));
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldHaveContentType() {
+			var response = doRequest();
+
+			response.andExpect(header().string(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE));
+		}
+
+		@SneakyThrows
+		@Test
+		void shouldWriteZipFile() {
+			doRequest();
+
+			verify(controller).createZipFile(any(), eq(EingangTestFactory.ID));
+		}
+
+		@SneakyThrows
+		private ResultActions doRequest() {
+			return mockMvc.perform(asyncDispatch(
+					mockMvc.perform(get(AttachmentsByVorgangController.PATH.replace("{vorgangId}", VorgangHeaderTestFactory.ID) + "?eingangId="
+							+ EingangTestFactory.ID)
+									.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_OCTET_STREAM_VALUE))
+							.andReturn()))
+					.andExpect(status().isOk());
+		}
+	}
+
+	@Nested
+	class TestBuildZipName {
+		private final String vorgangId = UUID.randomUUID().toString();
+
+		private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create();
+
+		@BeforeEach
+		void mockVorgangController() {
+			when(vorgangController.getVorgang(vorgangId)).thenReturn(vorgang);
+		}
+
+		@Test
+		void shouldCallVorgangController() {
+			callController();
+
+			verify(vorgangController).getVorgang(vorgangId);
+		}
+
+		@Test
+		void shouldReturnFileName() {
+			var resultFileName = callController();
+
+			assertThat(resultFileName).isEqualTo(vorgang.getNummer() + "_Anhaenge.zip");
+		}
+
+		private String callController() {
+			return controller.buildZipName(vorgangId);
+		}
+	}
+
+	@Nested
+	class TestCreateZipFile {
+		@Mock
+		private OutputStream outputStream;
+
+		@Test
+		void shouldGetAttachments() {
+			callController();
+
+			verify(fileService).getAttachmentsByEingang(EingangTestFactory.ID);
+		}
+
+		@Test
+		void shouldCallZipDownloadService() {
+			var ozgFile = OzgFileTestFactory.create();
+			when(fileService.getAttachmentsByEingang(EingangTestFactory.ID)).thenReturn(Stream.of(ozgFile));
+
+			callController();
+
+			verify(zipDownloadService).write(List.of(ozgFile), outputStream);
+		}
+
+		private void callController() {
+			controller.createZipFile(outputStream, EingangTestFactory.ID);
+		}
+	}
+}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidHistorieProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidHistorieProcessorTest.java
index ac60d058d4b2b3a315ac2312cae6375a160275d6..b3a68ed0ad5e3d441a2705cf6181e802882d0e55 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidHistorieProcessorTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidHistorieProcessorTest.java
@@ -79,7 +79,7 @@ class BescheidHistorieProcessorTest {
 		@ParameterizedTest
 		@EnumSource(mode = Mode.INCLUDE, names = { "CREATE_BESCHEID", "DELETE_BESCHEID" })
 		void shouldFilterCommandWithOrder(CommandOrder order) {
-			var command = CommandTestFactory.createBuilder().order(order.toString()).build();
+			var command = CommandTestFactory.createBuilder().order(order.name()).build();
 
 			var commands = processor.filterByOrder(Collections.singletonList(command));
 
@@ -89,30 +89,19 @@ class BescheidHistorieProcessorTest {
 		@ParameterizedTest
 		@EnumSource(mode = Mode.EXCLUDE, names = { "CREATE_BESCHEID", "DELETE_BESCHEID" })
 		void shouldKeepCommandWithOrder(CommandOrder order) {
-			var command = CommandTestFactory.createBuilder().order(order.toString()).build();
+			var command = CommandTestFactory.createBuilder().order(order.name()).build();
 
 			var commands = processor.filterByOrder(Collections.singletonList(command));
 
 			assertThat(commands).containsExactly(command);
 		}
 
-		@DisplayName("should filter bescheid related create attached item command")
-		@Test
-		void shouldFilterCreateAttachedItemCommand() {
-			var command = CommandTestFactory.createBuilder().order(CommandOrder.CREATE_ATTACHED_ITEM.toString())
-					.body(Map.of(VorgangAttachedItem.FIELD_ITEM_NAME, BescheidHistorieProcessor.BESCHEID_ITEM_NAME))
-					.build();
-
-			var commands = processor.filterByOrder(Collections.singletonList(command));
-
-			assertThat(commands).isEmpty();
-		}
-
-		@DisplayName("should filter bescheid related update attached item command")
-		@Test
-		void shouldFilterUpdateAttachedItemCommand() {
-			var command = CommandTestFactory.createBuilder().order(CommandOrder.UPDATE_ATTACHED_ITEM.toString())
-					.body(Map.of(VorgangAttachedItem.FIELD_ITEM_NAME, BescheidHistorieProcessor.BESCHEID_ITEM_NAME))
+		@ParameterizedTest
+		@EnumSource(mode = Mode.INCLUDE, names = { "CREATE_ATTACHED_ITEM", "UPDATE_ATTACHED_ITEM", "PATCH_ATTACHED_ITEM" })
+		@DisplayName("should filter bescheid related command")
+		void shouldFilterAttachedItemCommand(CommandOrder order) {
+			var command = CommandTestFactory.createBuilder().order(order.name())
+					.body(Collections.singletonMap(VorgangAttachedItem.FIELD_ITEM_NAME, BescheidHistorieProcessor.BESCHEID_ITEM_NAME))
 					.build();
 
 			var commands = processor.filterByOrder(Collections.singletonList(command));
@@ -156,17 +145,17 @@ class BescheidHistorieProcessorTest {
 		private final Command sendBescheidCommand = CommandTestFactory.createBuilder()
 				.id(UUID.randomUUID().toString())
 				.relationId(BescheidTestFactory.ID)
-				.order(CommandOrder.SEND_BESCHEID.toString())
+				.order(CommandOrder.SEND_BESCHEID.name())
 				.build();
 		private final Command updateBescheidCommand = CommandTestFactory.createBuilder()
 				.id(UUID.randomUUID().toString())
 				.relationId(BescheidTestFactory.ID)
-				.order(CommandOrder.UPDATE_BESCHEID.toString())
+				.order(CommandOrder.UPDATE_BESCHEID.name())
 				.build();
 		private final Command updateBescheidCommandOfBescheidNotSent = CommandTestFactory.createBuilder()
 				.id(UUID.randomUUID().toString())
 				.relationId(UUID.randomUUID().toString())
-				.order(CommandOrder.UPDATE_BESCHEID.toString())
+				.order(CommandOrder.UPDATE_BESCHEID.name())
 				.build();
 		private final List<Command> commands = List.of(sendBescheidCommand, updateBescheidCommand, updateBescheidCommandOfBescheidNotSent);
 
@@ -197,7 +186,7 @@ class BescheidHistorieProcessorTest {
 		private final Command sendBescheidCommand = CommandTestFactory.createBuilder()
 				.id(UUID.randomUUID().toString())
 				.relationId(BescheidTestFactory.ID)
-				.order(CommandOrder.SEND_BESCHEID.toString()).build();
+				.order(CommandOrder.SEND_BESCHEID.name()).build();
 
 		private final Command relatedUpdateBescheidCommand = CommandTestFactory.createBuilder().id(UUID.randomUUID().toString())
 				.createdAt(ZonedDateTime.now()).build();
@@ -293,7 +282,6 @@ class BescheidHistorieProcessorTest {
 
 		private Map<String, Object> createBescheidMap(SendBy sendBy) {
 			var item = BescheidTestFactory.createAsMap();
-			item.remove(Bescheid.SEND_BY_FIELD);
 			item.put(Bescheid.SEND_BY_FIELD, sendBy);
 			return item;
 		}
@@ -317,7 +305,7 @@ class BescheidHistorieProcessorTest {
 		@ParameterizedTest
 		@EnumSource(mode = Mode.INCLUDE, names = { "UPDATE_BESCHEID" })
 		void shouldKeepUpdateBescheidCommandsOnly(CommandOrder order) {
-			var commandWithNonMatchingOrder = CommandTestFactory.createBuilder().order(order.toString()).build();
+			var commandWithNonMatchingOrder = CommandTestFactory.createBuilder().order(order.name()).build();
 
 			var relatedCommands = processor.getRelatedUpdateBescheidCommands(command, Collections.singletonList(commandWithNonMatchingOrder));
 
@@ -327,7 +315,7 @@ class BescheidHistorieProcessorTest {
 		@ParameterizedTest
 		@EnumSource(mode = Mode.EXCLUDE, names = { "UPDATE_BESCHEID" })
 		void shouldFilterNonUpdateBescheidCommands(CommandOrder order) {
-			var commandWithNonMatchingOrder = CommandTestFactory.createBuilder().order(order.toString()).build();
+			var commandWithNonMatchingOrder = CommandTestFactory.createBuilder().order(order.name()).build();
 
 			var relatedCommands = processor.getRelatedUpdateBescheidCommands(command, Collections.singletonList(commandWithNonMatchingOrder));
 
@@ -381,7 +369,8 @@ class BescheidHistorieProcessorTest {
 
 		@Test
 		void shouldThrowOnMissingSendBy() {
-			assertThatThrownBy(() -> processor.isManualSent(Map.of())).isInstanceOf(NullPointerException.class);
+			var bescheidItemMap = Collections.<String, Object>emptyMap();
+			assertThatThrownBy(() -> processor.isManualSent(bescheidItemMap)).isInstanceOf(NullPointerException.class);
 		}
 	}
 
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessorTest.java
index ec24740d58cd87f75c86a04801232b5076fe03f3..fc714d41d1e45acb791372084e94c4c0b0bddab8 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessorTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/bescheid/BescheidVorgangProcessorTest.java
@@ -20,7 +20,6 @@ import org.mockito.Spy;
 import org.springframework.hateoas.EntityModel;
 import org.springframework.hateoas.Link;
 
-import de.ozgcloud.alfa.common.FeatureToggleProperties;
 import de.ozgcloud.alfa.common.UserProfileUrlProvider;
 import de.ozgcloud.alfa.common.user.CurrentUserService;
 import de.ozgcloud.alfa.common.user.UserRole;
@@ -43,9 +42,6 @@ class BescheidVorgangProcessorTest {
 	@Mock
 	private CurrentUserService currentUserService;
 
-	@Mock
-	private FeatureToggleProperties featureToggleProperties;
-
 	@Nested
 	class TestProcess {
 
@@ -215,7 +211,6 @@ class BescheidVorgangProcessorTest {
 
 		@Test
 		void shouldReturnTrue() {
-			givenFeatureToggleEnabled(true);
 			givenVorgangInBearbeitung(true);
 			givenDraftExists(true);
 
@@ -224,18 +219,8 @@ class BescheidVorgangProcessorTest {
 			assertThat(booleanSupplier.getAsBoolean()).isTrue();
 		}
 
-		@Test
-		void shouldReturnFalseIfFeatureToggleIsDisabled() {
-			givenFeatureToggleEnabled(false);
-
-			var booleanSupplier = callMethod();
-
-			assertThat(booleanSupplier.getAsBoolean()).isFalse();
-		}
-
 		@Test
 		void shouldReturnFalseIfVorgangNotInBearbeitung() {
-			givenFeatureToggleEnabled(true);
 			givenVorgangInBearbeitung(false);
 
 			var booleanSupplier = callMethod();
@@ -245,7 +230,6 @@ class BescheidVorgangProcessorTest {
 
 		@Test
 		void shouldReturnFalseIfDraftDoesNotExist() {
-			givenFeatureToggleEnabled(true);
 			givenVorgangInBearbeitung(true);
 			givenDraftExists(false);
 
@@ -264,7 +248,6 @@ class BescheidVorgangProcessorTest {
 
 		@Test
 		void shouldReturnTrue() {
-			givenFeatureToggleEnabled(true);
 			givenVorgangInBearbeitung(true);
 			givenDraftExists(false);
 
@@ -273,18 +256,8 @@ class BescheidVorgangProcessorTest {
 			assertThat(booleanSupplier.getAsBoolean()).isTrue();
 		}
 
-		@Test
-		void shouldReturnFalseIfFeatureToggleIsDisabled() {
-			givenFeatureToggleEnabled(false);
-
-			var booleanSupplier = callMethod();
-
-			assertThat(booleanSupplier.getAsBoolean()).isFalse();
-		}
-
 		@Test
 		void shouldReturnFalseIfVorgangNotInBearbeitung() {
-			givenFeatureToggleEnabled(true);
 			givenVorgangInBearbeitung(false);
 
 			var booleanSupplier = callMethod();
@@ -294,7 +267,6 @@ class BescheidVorgangProcessorTest {
 
 		@Test
 		void shouldReturnFalseIfDraftExists() {
-			givenFeatureToggleEnabled(true);
 			givenVorgangInBearbeitung(true);
 			givenDraftExists(true);
 
@@ -360,10 +332,6 @@ class BescheidVorgangProcessorTest {
 		}
 	}
 
-	private void givenFeatureToggleEnabled(boolean enabled) {
-		when(featureToggleProperties.isBescheidWizard()).thenReturn(enabled);
-	}
-
 	private void givenVorgangInBearbeitung(boolean inBearbeitung) {
 		doReturn(inBearbeitung).when(processor).isVorgangInBearbeitung(vorgang);
 	}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/TestUtils.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/AlfaTestUtils.java
similarity index 96%
rename from alfa-service/src/test/java/de/ozgcloud/alfa/common/TestUtils.java
rename to alfa-service/src/test/java/de/ozgcloud/alfa/common/AlfaTestUtils.java
index a11339d1baaf6b7e7afd691970664dbc28416e58..9792108f3aabc21d4a8bf09e1aa3477ce6b93144 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/TestUtils.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/AlfaTestUtils.java
@@ -10,7 +10,7 @@ import java.util.stream.Stream;
 
 import org.apache.commons.lang3.RandomStringUtils;
 
-public class TestUtils {
+public class AlfaTestUtils {
 
 	public static final String UUID_REGEX = "[0-9a-f]{8,8}-[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]{12,12}";
 
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/file/OzgFileTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/file/OzgFileTestFactory.java
index e4ccd038bdafc2decf7f352cdb8a5f042a30c5c1..66615affbbf4b7af0970568c6bb8453aaf56c244 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/file/OzgFileTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/file/OzgFileTestFactory.java
@@ -23,7 +23,7 @@
  */
 package de.ozgcloud.alfa.common.file;
 
-import static de.ozgcloud.alfa.common.TestUtils.*;
+import static de.ozgcloud.alfa.common.AlfaTestUtils.*;
 
 import de.ozgcloud.alfa.common.binaryfile.BinaryFileTestFactory;
 import de.ozgcloud.alfa.common.binaryfile.FileId;
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/zipdownload/ZipDownloadServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/zipdownload/ZipDownloadServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..943488ca0faf1f231ab479314884ed9c522d4de4
--- /dev/null
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/zipdownload/ZipDownloadServiceTest.java
@@ -0,0 +1,262 @@
+package de.ozgcloud.alfa.common.zipdownload;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockedConstruction;
+import org.mockito.Spy;
+
+import de.ozgcloud.alfa.common.binaryfile.BinaryFileService;
+import de.ozgcloud.alfa.common.file.OzgFile;
+import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
+import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.SneakyThrows;
+
+public class ZipDownloadServiceTest {
+
+	@Spy
+	@InjectMocks
+	private ZipDownloadService service;
+
+	@Mock
+	private BinaryFileService binaryFileService;
+
+	@Nested
+	class TestWrite {
+		private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+		private final List<OzgFile> ozgFiles = List.of(OzgFileTestFactory.create());
+		@Mock
+		private File zipFile;
+
+		@Test
+		void shouldCreateZipFile() {
+			callService();
+
+			verify(service).createZipFile(ozgFiles);
+		}
+
+		@Test
+		void shouldWriteZipFileContent() {
+			doReturn(zipFile).when(service).createZipFile(ozgFiles);
+			doNothing().when(service).writeZipFileContent(zipFile, outputStream);
+
+			callService();
+
+			verify(service).writeZipFileContent(zipFile, outputStream);
+		}
+
+		private void callService() {
+			service.write(ozgFiles, outputStream);
+		}
+	}
+
+	@Nested
+	class TestCreateZipFile {
+		private final OzgFile file1 = OzgFileTestFactory.createWithUniqueId();
+		private final OzgFile file2 = OzgFileTestFactory.createWithUniqueId();
+		private final List<OzgFile> ozgFiles = List.of(file1, file2);
+
+		private MockedConstruction<FileOutputStream> mockFileOutputStream;
+		private MockedConstruction<ZipOutputStream> mockZipOutputStream;
+		private File file;
+		private FileOutputStream fileOutputStream;
+
+		@BeforeEach
+		void setUpMocks() {
+			mockFileOutputStream = mockConstruction(FileOutputStream.class,
+					(mock, context) -> {
+						file = (File) context.arguments().get(0);
+					});
+			mockZipOutputStream = mockConstruction(ZipOutputStream.class,
+					(mock, context) -> {
+						fileOutputStream = (FileOutputStream) context.arguments().get(0);
+					});
+		}
+
+		@AfterEach
+		void cleanUp() {
+			mockFileOutputStream.close();
+			mockZipOutputStream.close();
+		}
+
+		@Test
+		void shouldCreateZipOutputStream() {
+			callService();
+
+			assertThat(mockZipOutputStream.constructed()).hasSize(1);
+			assertThat(fileOutputStream).isEqualTo(mockFileOutputStream.constructed().get(0));
+		}
+
+		@Test
+		void shouldAddOzgFilesToZip() {
+			callService();
+
+			verify(service).addOzgFileToZip(file1, mockZipOutputStream.constructed().get(0));
+			verify(service).addOzgFileToZip(file2, mockZipOutputStream.constructed().get(0));
+		}
+
+		@Test
+		void shouldReturnFile() {
+			var resultFile = callService();
+
+			assertThat(resultFile).isEqualTo(file);
+		}
+
+		@Test
+		void shouldThrowTechnicalException() {
+			doThrow(TechnicalException.class).when(service).addOzgFileToZip(any(), any());
+
+			assertThrows(TechnicalException.class, this::callService);
+		}
+
+		private File callService() {
+			return service.createZipFile(ozgFiles);
+		}
+	}
+
+	@Nested
+	class TestAddOzgFileToZip {
+		private final OzgFile ozgFile = OzgFileTestFactory.create();
+
+		@Mock
+		private ZipOutputStream zipOutputStream;
+
+		private MockedConstruction<ZipEntry> mockZipEntry;
+		private String entryName;
+
+		@BeforeEach
+		void setUpMocks() {
+			mockZipEntry = mockConstruction(ZipEntry.class,
+					(mock, context) -> {
+						entryName = (String) context.arguments().get(0);
+					});
+		}
+
+		@AfterEach
+		void cleanUp() {
+			mockZipEntry.close();
+		}
+
+		@Test
+		void shouldCreateZipEntry() {
+			callService();
+
+			assertThat(mockZipEntry.constructed()).hasSize(1);
+		}
+
+		@Test
+		void shouldSetZipEntryName() {
+			callService();
+
+			assertThat(entryName).isEqualTo(ozgFile.getName());
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldPutNextEntry() {
+			callService();
+
+			verify(zipOutputStream).putNextEntry(mockZipEntry.constructed().get(0));
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldWriteContent() {
+			callService();
+
+			verify(binaryFileService).writeFileContent(ozgFile.getId(), zipOutputStream);
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldCloseEntry() {
+			callService();
+
+			verify(zipOutputStream).closeEntry();
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldThrowTechnicalException() {
+			doThrow(IOException.class).when(zipOutputStream).putNextEntry(any());
+
+			assertThrows(TechnicalException.class, this::callService);
+		}
+
+		private void callService() {
+			service.addOzgFileToZip(ozgFile, zipOutputStream);
+		}
+	}
+
+	@Nested
+	class TestWriteZipFileContent {
+		private MockedConstruction<FileInputStream> mockFileInputStream;
+
+		private File argumentFile;
+		@Mock
+		private File file;
+
+		@Mock
+		private FileOutputStream fileOutputStream;
+
+		@AfterEach
+		void cleanUp() {
+			mockFileInputStream.close();
+		}
+
+		@Test
+		void shouldCreateFileInputStreamWithFileArgument() {
+			mockFileInputStream = mockConstruction(FileInputStream.class,
+					(mock, context) -> {
+						argumentFile = (File) context.arguments().get(0);
+					});
+
+			callService();
+
+			assertThat(mockFileInputStream.constructed()).hasSize(1);
+			assertThat(argumentFile).isEqualTo(file);
+		}
+
+		@Test
+		@SneakyThrows
+		void shouldTransferToOutputStream() {
+			mockFileInputStream = mockConstruction(FileInputStream.class);
+
+			callService();
+
+			verify(mockFileInputStream.constructed().get(0)).transferTo(fileOutputStream);
+		}
+
+		@Test
+		void shouldThrowTechnicalException() {
+			mockFileInputStream = mockConstruction(FileInputStream.class,
+					(mock, context) -> {
+						when(mock.transferTo(fileOutputStream)).thenThrow(IOException.class);
+					});
+
+			assertThrows(TechnicalException.class, this::callService);
+		}
+
+		private void callService() {
+			service.writeZipFileContent(file, fileOutputStream);
+		}
+
+	}
+}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/historie/VorgangChangeHistoryServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/historie/VorgangChangeHistoryServiceTest.java
index 451b3e9b0d1fceb0cfcced85d257679f7466b837..1e02f31be3dc179716b1b3eae020820a9a8c4d89 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/historie/VorgangChangeHistoryServiceTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/historie/VorgangChangeHistoryServiceTest.java
@@ -1,6 +1,6 @@
 package de.ozgcloud.alfa.historie;
 
-import static de.ozgcloud.alfa.common.TestUtils.*;
+import static de.ozgcloud.alfa.common.AlfaTestUtils.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandControllerTest.java
index 31cde4a9e360d9affef6708551760353f0f19ce6..b8e51c4a1f9bb378e5989c7cf3716959b4dacbb9 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandControllerTest.java
@@ -23,7 +23,6 @@
  */
 package de.ozgcloud.alfa.kommentar;
 
-import static de.ozgcloud.alfa.kommentar.KommentarCommandTestFactory.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
@@ -44,8 +43,10 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
 import de.ozgcloud.alfa.common.command.CommandTestFactory;
 import de.ozgcloud.alfa.common.command.CreateCommand;
+import de.ozgcloud.alfa.common.command.LegacyOrder;
 import de.ozgcloud.alfa.kommentar.KommentarCommandController.KommentarCommandByVorgangController;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
+import lombok.SneakyThrows;
 
 class KommentarCommandControllerTest {
 
@@ -70,22 +71,25 @@ class KommentarCommandControllerTest {
 			when(service.createKommentar(any(), any())).thenReturn(CommandTestFactory.create());
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCallService() throws Exception {
+		void shouldCallService() {
 			doRequest();
 
 			verify(service).createKommentar(any(Kommentar.class), eq(VorgangHeaderTestFactory.ID));
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldReturnCreated() throws Exception {
+		void shouldReturnCreated() {
 			doRequest().andExpect(status().isCreated());
 		}
 
-		private ResultActions doRequest() throws Exception {
+		@SneakyThrows
+		private ResultActions doRequest() {
 			return mockMvc.perform(
 					post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID)
-							.content(createValidRequestContent()).contentType(MediaType.APPLICATION_JSON))
+							.content(createRequestContent()).contentType(MediaType.APPLICATION_JSON))
 					.andExpect(status().is2xxSuccessful());
 		}
 	}
@@ -93,7 +97,7 @@ class KommentarCommandControllerTest {
 	@Nested
 	class TestCreateEditKommentarCommand {
 
-		private final static String REPONSE_HEADER = "http://localhost/api/commands/" + KommentarCommandTestFactory.ID;
+		private final static String REPONSE_HEADER = "http://localhost/api/commands/" + CommandTestFactory.ID;
 
 		@Spy
 		@InjectMocks
@@ -111,27 +115,35 @@ class KommentarCommandControllerTest {
 		}
 
 		@Test
-		void shouldCallService() throws Exception {
+		void shouldCallService() {
 			doRequest();
 
 			verify(service).editKommentar(any(Kommentar.class), eq(KommentarTestFactory.ID), eq(KommentarTestFactory.VERSION));
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldReturnCreated() throws Exception {
+		void shouldReturnCreated() {
 			doRequest().andExpect(status().isCreated());
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldRespondWithLocationHeader() throws Exception {
+		void shouldRespondWithLocationHeader() {
 			doRequest().andExpect(header().string("Location", REPONSE_HEADER));
 		}
 
-		private ResultActions doRequest() throws Exception {
-			String content = createValidRequestContent();
+		@SneakyThrows
+		private ResultActions doRequest() {
 			return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID, KommentarTestFactory.VERSION)
-					.content(content).contentType(MediaType.APPLICATION_JSON))
+					.content(createRequestContent()).contentType(MediaType.APPLICATION_JSON))
 					.andExpect(status().is2xxSuccessful());
 		}
 	}
+
+	private String createRequestContent() {
+		return KommentarTestFactory
+				.createRequestContent(CommandTestFactory.createCreateCommandBuilder().body(KommentarTestFactory.create())
+						.order(LegacyOrder.CREATE_KOMMENTAR).build());
+	}
 }
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandITCase.java
index 5cf825978a7a5f179f9c67cf8c635764665ee293..87d5be0da2eae911f865f47380307fe8a7fa61b5 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandITCase.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandITCase.java
@@ -23,7 +23,6 @@
  */
 package de.ozgcloud.alfa.kommentar;
 
-import static de.ozgcloud.alfa.kommentar.KommentarCommandTestFactory.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
@@ -46,7 +45,6 @@ import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.ResultActions;
 
 import de.ozgcloud.alfa.common.ValidationMessageCodes;
-import de.ozgcloud.alfa.common.command.CommandOrder;
 import de.ozgcloud.alfa.common.command.CommandRemoteService;
 import de.ozgcloud.alfa.common.command.CommandTestFactory;
 import de.ozgcloud.alfa.common.command.LegacyOrder;
@@ -54,6 +52,7 @@ import de.ozgcloud.alfa.common.user.CurrentUserService;
 import de.ozgcloud.alfa.common.user.UserProfileTestFactory;
 import de.ozgcloud.alfa.kommentar.KommentarCommandController.KommentarCommandByVorgangController;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
+import lombok.SneakyThrows;
 
 @AutoConfigureMockMvc
 @SpringBootTest
@@ -80,21 +79,31 @@ class KommentarCommandITCase {
 			when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create());
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCreateCommand() throws Exception {
+		void shouldCreateCommand() {
 			doRequestByKommentarId(createValidRequestContent()).andExpect(status().isCreated());
 
 			verify(commandRemoteService).createCommand(any());
 		}
 
+		private String createValidRequestContent() {
+			return KommentarTestFactory
+					.createRequestContent(CommandTestFactory.createCreateCommandBuilder()
+							.order(LegacyOrder.CREATE_KOMMENTAR)
+							.body(KommentarTestFactory.create())
+							.build());
+		}
+
 		@WithMockUser
 		@DisplayName("should return validation error")
 		@Nested
 		class TestValidation {
 
+			@SneakyThrows
 			@DisplayName("for null Text")
 			@Test
-			void createCommandWithInvalidText() throws Exception {
+			void createCommandWithInvalidText() {
 				String content = buildContentWithText(null);
 
 				doRequestByKommentarId(content).andExpect(status().isUnprocessableEntity())
@@ -103,9 +112,10 @@ class KommentarCommandITCase {
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
+			@SneakyThrows
 			@DisplayName("for empty String in Text")
 			@Test
-			void createcommandWithShortText() throws Exception {
+			void createcommandWithShortText() {
 				String content = buildContentWithText(StringUtils.EMPTY);
 
 				doRequestByKommentarId(content).andExpect(status().isUnprocessableEntity())
@@ -113,9 +123,10 @@ class KommentarCommandITCase {
 
 			}
 
+			@SneakyThrows
 			@DisplayName("for invalid text should have parameter")
 			@Test
-			void minMaxParameter() throws Exception {
+			void minMaxParameter() {
 				String content = buildContentWithText(StringUtils.EMPTY);
 
 				doRequestByKommentarId(content).andExpect(status().isUnprocessableEntity())
@@ -123,14 +134,17 @@ class KommentarCommandITCase {
 			}
 
 			private String buildContentWithText(String text) {
-				return createRequestContent(KommentarCommandTestFactory.createBuilder()
-						.order(CommandOrder.CREATE_ATTACHED_ITEM.name())
-						.kommentar(KommentarTestFactory.createBuilder().text(text).build())
-						.build());
+				var kommentar = KommentarTestFactory.createBuilder().text(text).build();
+				var createCommand = CommandTestFactory.createCreateCommandBuilder()
+						.order(LegacyOrder.CREATE_KOMMENTAR)
+						.body(kommentar)
+						.build();
+				return KommentarTestFactory.createRequestContent(createCommand);
 			}
 		}
 
-		private ResultActions doRequestByKommentarId(String content) throws Exception {
+		@SneakyThrows
+		private ResultActions doRequestByKommentarId(String content) {
 			return mockMvc
 					.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID, KommentarTestFactory.VERSION).with(csrf())
 							.contentType(MediaType.APPLICATION_JSON)
@@ -152,9 +166,14 @@ class KommentarCommandITCase {
 			doReturn(UserProfileTestFactory.ID).when(userService).getUserId();
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCreateCommand() throws Exception {
-			doRequestByVorgangId(createValidRequestContent()).andExpect(status().isCreated());
+		void shouldCreateCommand() {
+			var content = KommentarTestFactory
+					.createRequestContent(CommandTestFactory.createCreateCommandBuilder()
+							.order(LegacyOrder.CREATE_KOMMENTAR)
+							.body(KommentarTestFactory.create()).build());
+			doRequestByVorgangId(content).andExpect(status().isCreated());
 
 			verify(commandRemoteService).createCommand(any());
 		}
@@ -164,9 +183,10 @@ class KommentarCommandITCase {
 		@Nested
 		class TestValidation {
 
+			@SneakyThrows
 			@DisplayName("for null Text")
 			@Test
-			void createCommandWithInvalidText() throws Exception {
+			void createCommandWithInvalidText() {
 				String content = buildContentWithText(null);
 
 				doRequestByVorgangId(content).andExpect(status().isUnprocessableEntity())
@@ -175,9 +195,10 @@ class KommentarCommandITCase {
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
+			@SneakyThrows
 			@DisplayName("for empty String in Text")
 			@Test
-			void createcommandWithShortText() throws Exception {
+			void createcommandWithShortText() {
 				String content = buildContentWithText(StringUtils.EMPTY);
 
 				doRequestByVorgangId(content).andExpect(status().isUnprocessableEntity())
@@ -185,9 +206,10 @@ class KommentarCommandITCase {
 
 			}
 
+			@SneakyThrows
 			@DisplayName("for invalid text should have parameter")
 			@Test
-			void minMaxParameter() throws Exception {
+			void minMaxParameter() {
 				String content = buildContentWithText(StringUtils.EMPTY);
 
 				doRequestByVorgangId(content).andExpect(status().isUnprocessableEntity())
@@ -195,14 +217,17 @@ class KommentarCommandITCase {
 			}
 
 			private String buildContentWithText(String text) {
-				return createRequestContent(KommentarCommandTestFactory.createBuilder()
+				var kommentar = KommentarTestFactory.createBuilder().text(text).build();
+				var createCommand = CommandTestFactory.createCreateCommandBuilder()
 						.order(LegacyOrder.CREATE_KOMMENTAR)
-						.kommentar(KommentarTestFactory.createBuilder().text(text).build())
-						.build());
+						.body(kommentar)
+						.build();
+				return KommentarTestFactory.createRequestContent(createCommand);
 			}
 		}
 
-		private ResultActions doRequestByVorgangId(String content) throws Exception {
+		@SneakyThrows
+		private ResultActions doRequestByVorgangId(String content) {
 			return mockMvc.perform(post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID,
 					RELATION_ID_ON_CREATE).with(csrf())
 							.contentType(MediaType.APPLICATION_JSON)
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandTestFactory.java
deleted file mode 100644
index d9bdbad1c831c6f39681b446748faf0fac54fd28..0000000000000000000000000000000000000000
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarCommandTestFactory.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.alfa.kommentar;
-
-import java.util.Objects;
-
-import de.ozgcloud.alfa.common.command.CommandTestFactory;
-import de.ozgcloud.alfa.common.command.LegacyOrder;
-import de.ozgcloud.common.test.TestUtils;
-
-public class KommentarCommandTestFactory {
-
-	public static final String ID = CommandTestFactory.ID;
-	public static final String ORDER = LegacyOrder.CREATE_KOMMENTAR;
-
-	public static KommentarCommand create() {
-		return createBuilder().build();
-	}
-
-	public static KommentarCommand.KommentarCommandBuilder createBuilder() {
-		return KommentarCommand.builder()
-				.id(ID)
-				.order(ORDER)
-				.kommentar(KommentarTestFactory.create());
-	}
-
-	public static String createValidRequestContent() {
-		return createRequestContent(create());
-	}
-
-	public static String createRequestContent(KommentarCommand command) {
-		return TestUtils.loadTextFile("jsonTemplates/command/createCommandWithKommentar.json.tmpl",
-				command.getOrder(),
-				addTuedelchen(command.getKommentar().getText()));
-	}
-
-	private static String addTuedelchen(String str) {
-		return Objects.isNull(str) ? null : String.format("\"%s\"", str);
-	}
-}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarTestFactory.java
index dc82e3ab1ca130feea7c764a1685e10d5f18c7c1..d7d48c46bda778c523aca310648828cddf27efe1 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/kommentar/KommentarTestFactory.java
@@ -31,17 +31,19 @@ import java.util.Map;
 import com.thedeanda.lorem.Lorem;
 import com.thedeanda.lorem.LoremIpsum;
 
-import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.AlfaTestUtils;
 import de.ozgcloud.alfa.common.binaryfile.BinaryFileTestFactory;
 import de.ozgcloud.alfa.common.binaryfile.FileId;
+import de.ozgcloud.alfa.common.command.CreateCommand;
 import de.ozgcloud.alfa.common.user.UserProfileTestFactory;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
+import de.ozgcloud.common.test.TestUtils;
 
 public class KommentarTestFactory {
 
 	private static Lorem lorem = LoremIpsum.getInstance();
 
-	public static final String ID = TestUtils.createMongoDbObjectId();
+	public static final String ID = AlfaTestUtils.createMongoDbObjectId();
 	public static final long VERSION = 73;
 
 	public static final String CREATED_BY = UserProfileTestFactory.ID.toString();
@@ -76,4 +78,10 @@ public class KommentarTestFactory {
 				KommentarMapper.ATTACHMENTS, ATTACHMENTS);
 	}
 
-}
+	public static String createRequestContent(CreateCommand command) {
+		var kommentar = (Kommentar) command.getBody();
+		return TestUtils.loadTextFile("jsonTemplates/command/createCommandWithKommentar.json.tmpl",
+				command.getOrder(),
+				TestUtils.addQuote(kommentar.getText()));
+	}
+}
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/representation/RepresentationControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/representation/RepresentationControllerTest.java
index 689c5630291732fc004ab4529f3a97ca83d8b3b1..baa2ecbbff4cb2b1ddf4e43ac192d10109088069 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/representation/RepresentationControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/representation/RepresentationControllerTest.java
@@ -36,6 +36,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentMatchers;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Spy;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
@@ -43,11 +44,11 @@ import de.ozgcloud.alfa.common.binaryfile.BinaryFileModelAssembler;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileService;
 import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
+import lombok.SneakyThrows;
 
 class RepresentationControllerTest {
 
-	private final String PATH = RepresentationController.REPRESENTATIONS_PATH;
-
+	@Spy
 	@InjectMocks
 	private RepresentationController controller;
 	@Mock
@@ -70,27 +71,32 @@ class RepresentationControllerTest {
 			when(fileService.getRepresentationsByEingang(anyString())).thenReturn(Stream.of(OzgFileTestFactory.create()));
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCallEndpoint() throws Exception {
+		void shouldCallEndpoint() {
 			callEndpoint();
 		}
 
+		@SneakyThrows
 		@Test
-		void shoudlCallFileService() throws Exception {
+		void shouldCallFileService() {
 			callEndpoint();
 
 			verify(fileService).getRepresentationsByEingang(any());
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCallModelAssembler() throws Exception {
+		void shouldCallModelAssembler() {
 			callEndpoint();
 
 			verify(modelAssembler).toCollectionModel(ArgumentMatchers.<Stream<OzgFile>>any());
 		}
 
-		private void callEndpoint() throws Exception {
-			mockMvc.perform(get(PATH).param(RepresentationController.PARAM_EINGANG_ID, "1")).andExpect(status().isOk());
+		@SneakyThrows
+		private void callEndpoint() {
+			mockMvc.perform(get(RepresentationController.PATH).param(RepresentationController.PARAM_EINGANG_ID, "1")).andExpect(status().isOk());
 		}
 	}
+
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangHeaderTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangHeaderTestFactory.java
index b557d223d8864f48d72a0b65978ab00083293b95..ffe87bd60e28af75e1c0ee6e815ffaeeb3ff0727 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangHeaderTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangHeaderTestFactory.java
@@ -23,7 +23,7 @@
  */
 package de.ozgcloud.alfa.vorgang;
 
-import static de.ozgcloud.alfa.common.TestUtils.*;
+import static de.ozgcloud.alfa.common.AlfaTestUtils.*;
 
 import java.time.ZonedDateTime;
 
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProcessorTest.java
index 6c309bf3c60219b325b52a5a296249f7b3868261..988b8cd04b8df6ae58cb6923785235828ebd5447 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProcessorTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProcessorTest.java
@@ -69,30 +69,59 @@ class VorgangWithEingangProcessorTest {
 
 	private UserProfileUrlProvider urlProvider = new UserProfileUrlProvider();
 
+	@DisplayName("Attachments")
 	@Nested
-	class TestAttachmentsLink {
-
-		private final LinkRelation linkRel = VorgangWithEingangProcessor.REL_ATTACHMENTS;
-		private final String PATH = "/api/attachments?eingangId=" + EingangTestFactory.ID;
+	class TestAttachments {
 
 		@BeforeEach
 		void init() {
 			initUserProfileUrlProvider(urlProvider);
 		}
 
-		@DisplayName("should be present on numberOfAttachments > 0")
-		@Test
-		void shouldBePresentByAttachments() {
-			var link = processor.process(buildModelWithAttachments(1)).getLink(linkRel);
+		@DisplayName("link")
+		@Nested
+		class TestLink {
 
-			assertThat(link).isPresent().get().extracting(Link::getHref).isEqualTo(PATH);
+			private static final String PATH = "/api/attachments?eingangId=" + EingangTestFactory.ID;
+			private final LinkRelation linkRel = VorgangWithEingangProcessor.REL_ATTACHMENTS;
+
+			@DisplayName("should be present if attachments exists")
+			@Test
+			void shouldBePresent() {
+				var link = processor.process(buildModelWithAttachments(1)).getLink(linkRel);
+
+				assertThat(link).isPresent().get().extracting(Link::getHref).isEqualTo(PATH);
+			}
+
+			@Test
+			void shouldNotBePresent() {
+				var link = processor.process(buildModelWithAttachments(0)).getLink(linkRel);
+
+				assertThat(link).isNotPresent();
+			}
 		}
 
-		@Test
-		void shouldNotBePresent() {
-			var link = processor.process(buildModelWithAttachments(0)).getLink(linkRel);
+		@DisplayName("download link")
+		@Nested
+		class TestDownloadLink {
 
-			assertThat(link).isNotPresent();
+			private static final String PATH = "/api/vorgang/" + VorgangHeaderTestFactory.ID + "/attachments?eingangId=" + EingangTestFactory.ID;
+			private final LinkRelation linkRel = VorgangWithEingangProcessor.REL_DOWNLOAD_ATTACHMENTS;
+
+			@DisplayName("should be present if attachments exists")
+			@Test
+			void shouldBePresent() {
+				var link = processor.process(buildModelWithAttachments(1)).getLink(linkRel);
+
+				assertThat(link).isPresent().get().extracting(Link::getHref).isEqualTo(PATH);
+			}
+
+			@Test
+			void shouldNotBePresent() {
+				var link = processor.process(buildModelWithAttachments(0)).getLink(linkRel);
+
+				assertThat(link).isNotPresent();
+			}
 		}
 
 		private EntityModel<VorgangWithEingang> buildModelWithAttachments(int numberOfAttachments) {
@@ -106,15 +135,22 @@ class VorgangWithEingangProcessorTest {
 		}
 	}
 
+	@DisplayName("Representations")
 	@Nested
 	class TestRepresentationsLink {
 
+		@BeforeEach
+		void init() {
+			initUserProfileUrlProvider(urlProvider);
+		}
+
+		private static final String PATH = "/api/representations?eingangId=" + EingangTestFactory.ID;
+
 		private final LinkRelation linkRel = VorgangWithEingangProcessor.REL_REPRESENTATIONS;
-		private final String PATH = "/api/representations?eingangId=" + EingangTestFactory.ID;
 
-		@DisplayName("should be present on numberOfRepresentations > 0")
+		@DisplayName("should be present if representations exist")
 		@Test
-		void shouldBePresentByRepresentations() {
+		void shouldBePresent() {
 			var link = processor.process(buildModelWithRepresentation(1)).getLink(linkRel);
 
 			assertThat(link).isPresent().get().extracting(Link::getHref).isEqualTo(PATH);
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java
index decfe1c9660d52cc4116c2468c7842eaec89b1ba..74d31babe720c7877812b0422b00cb1d76b377c2 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java
@@ -47,9 +47,11 @@ import de.ozgcloud.alfa.common.binaryfile.BinaryFileTestFactory;
 import de.ozgcloud.alfa.common.command.CommandController.CommandByRelationController;
 import de.ozgcloud.alfa.common.command.CommandTestFactory;
 import de.ozgcloud.alfa.common.command.CreateCommand;
+import de.ozgcloud.alfa.common.command.LegacyOrder;
 import de.ozgcloud.alfa.common.user.CurrentUserService;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
 import de.ozgcloud.alfa.wiedervorlage.WiedervorlageCommandController.WiedervorlageCommandByVorgangController;
+import lombok.SneakyThrows;
 
 class WiedervorlageCommandByVorgangControllerTest {
 
@@ -88,33 +90,42 @@ class WiedervorlageCommandByVorgangControllerTest {
 		class ServiceMethod {
 
 			@Test
-			void shouldCallService() throws Exception {
+			void shouldCallService() {
 				doRequest();
 
 				verify(service).createWiedervorlage(wiedervorlageCaptor.capture(), eq(VorgangHeaderTestFactory.ID));
-				assertThat(wiedervorlageCaptor.getValue().getAttachments().get(0)).isEqualTo(BinaryFileTestFactory.FILE_ID);
+				assertThat(wiedervorlageCaptor.getValue().getAttachments().getFirst()).isEqualTo(BinaryFileTestFactory.FILE_ID);
 			}
 
 			@Test
-			void shouldCallServiceToUpdateNextFrist() throws Exception {
+			void shouldCallServiceToUpdateNextFrist() {
 				doRequest();
 
 				verify(service).updateNextFrist(VorgangHeaderTestFactory.ID);
 			}
 
+			@SneakyThrows
 			@Test
-			void returnReturnCreated() throws Exception {
+			void returnReturnCreated() {
 				doRequest().andExpect(status().isCreated());
 			}
 		}
 	}
 
-	private ResultActions doRequest() throws Exception {
+	@SneakyThrows
+	private ResultActions doRequest() {
 		return mockMvc.perform(
 				post(WiedervorlageCommandByVorgangController.WIEDERVORLAGE_COMMANDS_BY_VORGANG,
 						VorgangHeaderTestFactory.ID)
-								.content(WiedervorlageCommandTestFactory.createValidRequestContent())
+								.content(createRequestContent())
 								.contentType(MediaType.APPLICATION_JSON))
 				.andExpect(status().is2xxSuccessful());
 	}
+
+	private String createRequestContent() {
+		var createCommand = CommandTestFactory.createCreateCommandBuilder().body(WiedervorlageTestFactory.create())
+				.order(LegacyOrder.EDIT_WIEDERVORLAGE)
+				.build();
+		return WiedervorlageTestFactory.createRequestContent(createCommand);
+	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandControllerTest.java
index 00536e559a99dec6a358f7304669248bb5e2da8e..74bc2df86a8f6f8d98dc1fe34365654ef44c2e0e 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandControllerTest.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandControllerTest.java
@@ -35,8 +35,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
@@ -54,6 +52,7 @@ import de.ozgcloud.alfa.common.command.CreateCommand;
 import de.ozgcloud.alfa.common.command.LegacyOrder;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
 import de.ozgcloud.common.errorhandling.TechnicalException;
+import lombok.SneakyThrows;
 
 class WiedervorlageCommandControllerTest {
 
@@ -64,10 +63,6 @@ class WiedervorlageCommandControllerTest {
 	private CommandService commandService;
 	@Mock
 	private WiedervorlageService service;
-	@Captor
-	private ArgumentCaptor<WiedervorlageCommand> commandCaptor;
-	@Captor
-	private ArgumentCaptor<CreateCommand> createCommandCaptor;
 
 	private MockMvc mockMvc;
 
@@ -80,7 +75,7 @@ class WiedervorlageCommandControllerTest {
 	@Nested
 	class TestUpdateWiedervorlage {
 
-		private static final String RESPONSE_HEADER = "http://localhost/api/commands/" + WiedervorlageCommandTestFactory.ID;
+		private static final String RESPONSE_HEADER = "http://localhost/api/commands/" + CommandTestFactory.ID;
 
 		@Nested
 		class ControllerMethods {
@@ -93,43 +88,60 @@ class WiedervorlageCommandControllerTest {
 						.body(WiedervorlageTestFactory.createAsMap()).build());
 			}
 
+			@SneakyThrows
 			@Test
-			void shouldCallServiceGetById() throws Exception {
+			void shouldCallServiceGetById() {
 				doRequest();
 
 				verify(service).getById(WiedervorlageTestFactory.ID);
 			}
 
 			@Test
-			void shouldCallServiceUpdateNextFrist() throws Exception {
+			void shouldCallServiceUpdateNextFrist() {
 				doRequest();
 
 				verify(service).updateNextFrist(VorgangHeaderTestFactory.ID);
 			}
 
+			@SneakyThrows
 			@Test
-			void shouldReturnCreatedStatus() throws Exception {
-				doRequest().andExpect(status().isCreated());
+			void shouldReturnCreatedStatus() {
+				var response = doRequest();
+
+				response.andExpect(status().isCreated());
 			}
 
+			@SneakyThrows
 			@Test
-			void shouldResponseWithLocationHeader() throws Exception {
-				doRequest().andExpect(header().string("Location", RESPONSE_HEADER));
+			void shouldResponseWithLocationHeader() {
+				var response = doRequest();
+
+				response.andExpect(header().string("Location", RESPONSE_HEADER));
 			}
 
 			@Test
-			void shouldCreateCommand() throws Exception {
+			void shouldCreateCommand() {
 				doRequest();
 
-				verify(controller).createCommand(any(Wiedervorlage.class), any(WiedervorlageCommand.class));
+				verify(controller).createCommand(any(Wiedervorlage.class), any(CreateCommand.class));
 			}
 
-			private ResultActions doRequest() throws Exception {
+			@SneakyThrows
+			private ResultActions doRequest() {
 				return mockMvc.perform(
 						post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION)
-								.content(WiedervorlageCommandTestFactory.createValidRequestContent()).contentType(MediaType.APPLICATION_JSON))
+								.content(createRequestContent()).contentType(MediaType.APPLICATION_JSON))
 						.andExpect(status().is2xxSuccessful());
 			}
+
+			private String createRequestContent() {
+				return WiedervorlageTestFactory
+						.createRequestContent(
+								CommandTestFactory.createCreateCommandBuilder()
+										.order("EDIT_WIEDERVORLAGE")
+										.body(WiedervorlageTestFactory.create())
+										.build());
+			}
 		}
 
 		@DisplayName("create command")
@@ -176,10 +188,10 @@ class WiedervorlageCommandControllerTest {
 				@Nested
 				class TestUpdateWiedervorlageByCommand {
 
-					private final FileId ATTACHMENT_ID = FileId.from("73");
-					private final String BETREFF = "Neuer Betreff";
-					private final String BESCHREIBUNG = "Neuer Beschreibung";
-					private final LocalDate FRIST = LocalDate.now();
+					private final static FileId ATTACHMENT_ID = FileId.from("73");
+					private final static String BETREFF = "Neuer Betreff";
+					private final static String BESCHREIBUNG = "Neuer Beschreibung";
+					private final static LocalDate FRIST = LocalDate.now();
 
 					@Test
 					void shouldHaveSetAttachments() {
@@ -211,17 +223,16 @@ class WiedervorlageCommandControllerTest {
 					}
 
 					private Wiedervorlage update() {
-						return controller.updateWiedervorlageByCommand(WiedervorlageTestFactory.create(), buildWiedervorlageCommand());
+						return controller.updateWiedervorlageByCommand(WiedervorlageTestFactory.create(), buildWiedervorlage());
 					}
 
-					private WiedervorlageCommand buildWiedervorlageCommand() {
-						var commandWiedervorlage = WiedervorlageTestFactory.createBuilder()
+					private Wiedervorlage buildWiedervorlage() {
+						return WiedervorlageTestFactory.createBuilder()
 								.clearAttachments().attachment(ATTACHMENT_ID)
 								.betreff(BETREFF)
 								.beschreibung(BESCHREIBUNG)
 								.frist(FRIST)
 								.build();
-						return WiedervorlageCommandTestFactory.createBuilder().wiedervorlage(commandWiedervorlage).build();
 					}
 				}
 			}
@@ -232,7 +243,9 @@ class WiedervorlageCommandControllerTest {
 				@Test
 				void shouldThrowException() {
 					var wiedervorlage = WiedervorlageTestFactory.create();
-					var command = WiedervorlageCommandTestFactory.createBuilder().order(CommandOrder.CREATE_ATTACHED_ITEM.name()).build();
+					var command = CommandTestFactory.createCreateCommandBuilder()
+							.order(CommandOrder.CREATE_ATTACHED_ITEM.name())
+							.body(wiedervorlage).build();
 
 					assertThatExceptionOfType(TechnicalException.class)
 							.isThrownBy(() -> controller.createCommand(wiedervorlage, command));
@@ -241,7 +254,9 @@ class WiedervorlageCommandControllerTest {
 
 			private Command callCreateCommand(String order) {
 				return controller.createCommand(WiedervorlageTestFactory.create(),
-						WiedervorlageCommandTestFactory.createBuilder().order(order).build());
+						CommandTestFactory.createCreateCommandBuilder().body(WiedervorlageTestFactory.create())
+								.order(order)
+								.build());
 			}
 		}
 	}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandITCase.java
index fe84f65889cd73f0b065003e7e3b1dffb07964f2..88a17b72ba185204edb3514e4a2bfcd90bcf53a6 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandITCase.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandITCase.java
@@ -23,7 +23,6 @@
  */
 package de.ozgcloud.alfa.wiedervorlage;
 
-import static de.ozgcloud.alfa.wiedervorlage.WiedervorlageCommandTestFactory.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;
@@ -50,11 +49,13 @@ import org.springframework.test.web.servlet.ResultActions;
 import de.ozgcloud.alfa.common.ValidationMessageCodes;
 import de.ozgcloud.alfa.common.command.CommandRemoteService;
 import de.ozgcloud.alfa.common.command.CommandTestFactory;
+import de.ozgcloud.alfa.common.command.CreateCommand;
 import de.ozgcloud.alfa.common.command.LegacyOrder;
 import de.ozgcloud.alfa.common.user.CurrentUserService;
 import de.ozgcloud.alfa.common.user.UserProfileTestFactory;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
 import de.ozgcloud.alfa.wiedervorlage.WiedervorlageCommandController.WiedervorlageCommandByVorgangController;
+import lombok.SneakyThrows;
 
 @AutoConfigureMockMvc
 @SpringBootTest
@@ -82,9 +83,10 @@ class WiedervorlageCommandITCase {
 			when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create());
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCreateCommand() throws Exception {
-			doRequest(WiedervorlageCommandTestFactory.createValidRequestContent()).andExpect(status().isCreated());
+		void shouldCreateCommand() {
+			doRequest(createEditWiedervorlageRequestContent()).andExpect(status().isCreated());
 
 			verify(commandRemoteService).createCommand(any());
 		}
@@ -94,9 +96,10 @@ class WiedervorlageCommandITCase {
 		@Nested
 		class TestValidation {
 
+			@SneakyThrows
 			@DisplayName("for null Betreff")
 			@Test
-			void createCommandWithInvalidBetreff() throws Exception {
+			void createCommandWithInvalidBetreff() {
 				String content = buildContentWithBetreff(null);
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
@@ -105,9 +108,10 @@ class WiedervorlageCommandITCase {
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
+			@SneakyThrows
 			@DisplayName("for only 1 character in Betreff")
 			@Test
-			void createcommandWithShortBetreff() throws Exception {
+			void createcommandWithShortBetreff() {
 				String content = buildContentWithBetreff("a");
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
@@ -115,17 +119,19 @@ class WiedervorlageCommandITCase {
 
 			}
 
+			@SneakyThrows
 			@DisplayName("for invalid betreff should have paramter")
 			@Test
-			void minMaxParameter() throws Exception {
+			void minMaxParameter() {
 				String content = buildContentWithBetreff("a");
 
 				doRequest(content).andExpect(status().isUnprocessableEntity()).andExpect(jsonPath("$.issues[0].parameters.length()").value(2));
 			}
 
+			@SneakyThrows
 			@DisplayName("for 41 character in Betreff")
 			@Test
-			void createCommandWithLongBetreff() throws Exception {
+			void createCommandWithLongBetreff() {
 				var content = buildContentWithBetreff(RandomStringUtils.random(41));
 
 				doRequest(content).andExpect(status().isUnprocessableEntity());
@@ -135,9 +141,10 @@ class WiedervorlageCommandITCase {
 				return createEditContent(WiedervorlageTestFactory.createBuilder().betreff(betreff).build());
 			}
 
+			@SneakyThrows
 			@DisplayName("for frist in past")
 			@Test
-			void createCommandWithInvalidDate() throws Exception {
+			void createCommandWithInvalidDate() {
 				String content = createEditContent(WiedervorlageTestFactory.createBuilder().frist(LocalDate.parse("2020-01-01")).build());
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
@@ -146,9 +153,10 @@ class WiedervorlageCommandITCase {
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_DATE_PAST));
 			}
 
+			@SneakyThrows
 			@DisplayName("for empty frist")
 			@Test
-			void createCommandWithoutDate() throws Exception {
+			void createCommandWithoutDate() {
 				String content = createEditContent(WiedervorlageTestFactory.createBuilder().frist(null).build());
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
@@ -158,12 +166,14 @@ class WiedervorlageCommandITCase {
 			}
 
 			private String createEditContent(Wiedervorlage wiedervorlage) {
-				return createRequestContent(createWithWiedervorlage(wiedervorlage).toBuilder().order(LegacyOrder.EDIT_WIEDERVORLAGE).build());
+				return WiedervorlageTestFactory
+						.createRequestContent(createWithWiedervorlage(wiedervorlage).toBuilder().order(LegacyOrder.EDIT_WIEDERVORLAGE).build());
 			}
 
 		}
 
-		private ResultActions doRequest(String content) throws Exception {
+		@SneakyThrows
+		private ResultActions doRequest(String content) {
 			return mockMvc.perform(
 					post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION)
 							.with(csrf())
@@ -187,21 +197,31 @@ class WiedervorlageCommandITCase {
 			doReturn(UserProfileTestFactory.ID).when(userService).getUserId();
 		}
 
+		@SneakyThrows
 		@Test
-		void shouldCreateCommand() throws Exception {
-			doRequest(createValidRequestContent()).andExpect(status().isCreated());
+		void shouldCallCreateCommand() {
+			doRequest(createEditWiedervorlageRequestContent());
 
 			verify(commandRemoteService).createCommand(any());
 		}
 
+		@SneakyThrows
+		@Test
+		void shouldReturnCreatedStatus() {
+			var response = doRequest(createEditWiedervorlageRequestContent());
+
+			response.andExpect(status().isCreated());
+		}
+
 		@WithMockUser
 		@DisplayName("should return validation error")
 		@Nested
 		class TestValidation {
 
+			@SneakyThrows
 			@DisplayName("for null Betreff")
 			@Test
-			void createCommandWithInvalidBetreff() throws Exception {
+			void createCommandWithInvalidBetreff() {
 				String content = buildContentWithBetreff(null);
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
@@ -210,9 +230,10 @@ class WiedervorlageCommandITCase {
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY));
 			}
 
+			@SneakyThrows
 			@DisplayName("for only 1 character in Betreff")
 			@Test
-			void createcommandWithShortBetreff() throws Exception {
+			void createcommandWithShortBetreff() {
 				String content = buildContentWithBetreff("a");
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
@@ -220,30 +241,34 @@ class WiedervorlageCommandITCase {
 
 			}
 
+			@SneakyThrows
 			@DisplayName("for invalid betreff should have paramter")
 			@Test
-			void minMaxParameter() throws Exception {
+			void minMaxParameter() {
 				String content = buildContentWithBetreff("a");
 
 				doRequest(content).andExpect(status().isUnprocessableEntity()).andExpect(jsonPath("$.issues[0].parameters.length()").value(2));
 			}
 
+			@SneakyThrows
 			@DisplayName("for 41 character in Betreff")
 			@Test
-			void createCommandWithLongBetreff() throws Exception {
+			void createCommandWithLongBetreff() {
 				var content = buildContentWithBetreff(RandomStringUtils.randomAlphanumeric(41));
 
 				doRequest(content).andExpect(status().isUnprocessableEntity());
 			}
 
 			private String buildContentWithBetreff(String betreff) {
-				return createRequestContent(createWithWiedervorlage(WiedervorlageTestFactory.createBuilder().betreff(betreff).build()));
+				return WiedervorlageTestFactory
+						.createRequestContent(createWithWiedervorlage(WiedervorlageTestFactory.createBuilder().betreff(betreff).build()));
 			}
 
+			@SneakyThrows
 			@DisplayName("for frist in past")
 			@Test
-			void createCommandWithInvalidDate() throws Exception {
-				String content = createRequestContent(
+			void createCommandWithInvalidDate() {
+				String content = WiedervorlageTestFactory.createRequestContent(
 						createWithWiedervorlage(WiedervorlageTestFactory.createBuilder().frist(LocalDate.parse("2020-01-01")).build()));
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
@@ -252,10 +277,11 @@ class WiedervorlageCommandITCase {
 						.andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_DATE_PAST));
 			}
 
+			@SneakyThrows
 			@DisplayName("for empty frist")
 			@Test
-			void createCommandWithoutDate() throws Exception {
-				String content = createRequestContent(
+			void createCommandWithoutDate() {
+				String content = WiedervorlageTestFactory.createRequestContent(
 						createWithWiedervorlage(WiedervorlageTestFactory.createBuilder().frist(null).build()));
 
 				doRequest(content).andExpect(status().isUnprocessableEntity())
@@ -266,7 +292,8 @@ class WiedervorlageCommandITCase {
 
 		}
 
-		private ResultActions doRequest(String content) throws Exception {
+		@SneakyThrows
+		private ResultActions doRequest(String content) {
 			return mockMvc.perform(post(WiedervorlageCommandByVorgangController.WIEDERVORLAGE_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID,
 					RELATION_ID_ON_CREATE)
 							.with(csrf())
@@ -274,4 +301,17 @@ class WiedervorlageCommandITCase {
 							.content(content));
 		}
 	}
+
+	private String createEditWiedervorlageRequestContent() {
+		var createCommand = CommandTestFactory.createCreateCommandBuilder().body(WiedervorlageTestFactory.create())
+				.order(LegacyOrder.EDIT_WIEDERVORLAGE).build();
+		return WiedervorlageTestFactory.createRequestContent(createCommand);
+	}
+
+	private CreateCommand createWithWiedervorlage(Wiedervorlage wiedervorlage) {
+		return CommandTestFactory.createCreateCommandBuilder()
+				.body(wiedervorlage)
+				.order("EDIT_WIEDERVORLAGE")
+				.build();
+	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandTestFactory.java
deleted file mode 100644
index 2b2d67f630017f8219c40b3168bea482fdc95ee5..0000000000000000000000000000000000000000
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandTestFactory.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-package de.ozgcloud.alfa.wiedervorlage;
-
-import java.util.Objects;
-import java.util.Optional;
-
-import org.apache.commons.lang3.StringUtils;
-
-import de.ozgcloud.alfa.common.binaryfile.BinaryFileTestFactory;
-import de.ozgcloud.alfa.common.command.CommandOrder;
-import de.ozgcloud.alfa.common.command.CommandTestFactory;
-import de.ozgcloud.alfa.common.command.LegacyOrder;
-import de.ozgcloud.common.test.TestUtils;
-
-public class WiedervorlageCommandTestFactory {
-
-	public static final String ID = CommandTestFactory.ID;
-	public static final String ORDER = LegacyOrder.EDIT_WIEDERVORLAGE;
-
-	public static WiedervorlageCommand create() {
-		return createBuilder().build();
-	}
-
-	public static WiedervorlageCommand createWithWiedervorlage(Wiedervorlage wiedervorlage) {
-		return createBuilder().wiedervorlage(wiedervorlage).build();
-	}
-
-	public static WiedervorlageCommand.WiedervorlageCommandBuilder createBuilder() {
-		return WiedervorlageCommand.builder()
-				.id(ID)
-				.order(ORDER)
-				.wiedervorlage(WiedervorlageTestFactory.create());
-	}
-
-	public static String createValidRequestContent() {
-		return createRequestContent(create());
-	}
-
-	public static String createRequestContent(WiedervorlageCommand command) {
-		return TestUtils.loadTextFile("jsonTemplates/command/createCommandWithWiedervorlage.json.tmpl",
-				command.getOrder(),
-				addTuedelchen(command.getWiedervorlage().getBetreff()),
-				command.getWiedervorlage().getBeschreibung(),
-				Optional.ofNullable(command.getWiedervorlage().getFrist()).map(Object::toString).orElse(StringUtils.EMPTY),
-				"/api/binaryFiles/" + BinaryFileTestFactory.FILE_ID);
-	}
-
-	private static String addTuedelchen(String str) {
-		return Objects.isNull(str) ? null : String.format("\"%s\"", str);
-	}
-
-	public static String createRequestContent(CommandOrder order) {
-		return TestUtils.loadTextFile("jsonTemplates/command/createWiedervorlageOrderCommand.json.tmpl", order.name());
-	}
-}
diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageTestFactory.java
index 06078c97e7b7def4a61368ca6eb6f97740f78a94..be94298693d45e299a297c108c5fb5df5ccc1ac5 100644
--- a/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageTestFactory.java
+++ b/alfa-service/src/test/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageTestFactory.java
@@ -26,12 +26,17 @@ package de.ozgcloud.alfa.wiedervorlage;
 import java.time.LocalDate;
 import java.time.ZonedDateTime;
 import java.util.Map;
+import java.util.Optional;
 import java.util.UUID;
 
+import org.apache.commons.lang3.StringUtils;
+
 import com.thedeanda.lorem.LoremIpsum;
 
 import de.ozgcloud.alfa.common.binaryfile.BinaryFileTestFactory;
+import de.ozgcloud.alfa.common.command.CreateCommand;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
+import de.ozgcloud.common.test.TestUtils;
 
 public class WiedervorlageTestFactory {
 
@@ -78,4 +83,14 @@ public class WiedervorlageTestFactory {
 				WiedervorlageMapper.CREATED_AT, CREATED_AT_STR,
 				WiedervorlageMapper.ATTACHMENTS, BinaryFileTestFactory.ID);
 	}
+
+	public static String createRequestContent(CreateCommand command) {
+		var wiedervorlage = (Wiedervorlage) command.getBody();
+		return TestUtils.loadTextFile("jsonTemplates/command/createCommandWithWiedervorlage.json.tmpl",
+				command.getOrder(),
+				TestUtils.addQuote(wiedervorlage.getBetreff()),
+				wiedervorlage.getBeschreibung(),
+				Optional.ofNullable(wiedervorlage.getFrist()).map(String::valueOf).orElse(StringUtils.EMPTY),
+				"/api/binaryFiles/" + BinaryFileTestFactory.FILE_ID);
+	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/resources/jsonTemplates/command/createCommandWithKommentar.json.tmpl b/alfa-service/src/test/resources/jsonTemplates/command/createCommandWithKommentar.json.tmpl
index fbe55525a6dd55f400f08c0f8baec92b15af7c72..072af9c1c4afb4c6546c741b4fe0f0479be53e11 100644
--- a/alfa-service/src/test/resources/jsonTemplates/command/createCommandWithKommentar.json.tmpl
+++ b/alfa-service/src/test/resources/jsonTemplates/command/createCommandWithKommentar.json.tmpl
@@ -1,7 +1,7 @@
 {
 	"order": "%s",
-	"kommentar": {
+	"body": {
 		"text": %s,
-    "attachments": []
+    	"attachments": []
 	}
 }
\ No newline at end of file
diff --git a/alfa-service/src/test/resources/jsonTemplates/command/createCommandWithWiedervorlage.json.tmpl b/alfa-service/src/test/resources/jsonTemplates/command/createCommandWithWiedervorlage.json.tmpl
index fa1665155401142608bf6e6f08b1502a358ae8ca..4ef1fb4b5dbf2c90689c192c210ed32157bece63 100644
--- a/alfa-service/src/test/resources/jsonTemplates/command/createCommandWithWiedervorlage.json.tmpl
+++ b/alfa-service/src/test/resources/jsonTemplates/command/createCommandWithWiedervorlage.json.tmpl
@@ -1,6 +1,6 @@
 {
 	"order": "%s",
-	"wiedervorlage": {
+	"body": {
 		"betreff": %s,
 		"beschreibung": "%s",
 		"frist": "%s",
diff --git a/alfa-service/src/test/resources/jsonTemplates/command/createWiedervorlageOrderCommand.json.tmpl b/alfa-service/src/test/resources/jsonTemplates/command/createWiedervorlageOrderCommand.json.tmpl
deleted file mode 100644
index 64d27c8846dd5cd0654e7af502fded4231eb7b4e..0000000000000000000000000000000000000000
--- a/alfa-service/src/test/resources/jsonTemplates/command/createWiedervorlageOrderCommand.json.tmpl
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-	"order": "%s"
-}
\ No newline at end of file
diff --git a/alfa-xdomea/pom.xml b/alfa-xdomea/pom.xml
index ee34595691b9d2da7c53e3e963a12708ace55e4e..6f92cd2bc38e598b1dc2ab97a546ab4c331c7139 100644
--- a/alfa-xdomea/pom.xml
+++ b/alfa-xdomea/pom.xml
@@ -31,7 +31,7 @@
 	<parent>
 		<groupId>de.ozgcloud.alfa</groupId>
 		<artifactId>alfa</artifactId>
-		<version>2.10.0-SNAPSHOT</version>
+		<version>2.11.0-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>alfa-xdomea</artifactId>
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DefaultXdomeaProperties.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DefaultXdomeaProperties.java
deleted file mode 100644
index 32861d97bc2c68ae07e572d05b8316b526aaec90..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/DefaultXdomeaProperties.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-@ConditionalOnProperty(value = "ozgcloud.feature.vorgang-export", havingValue = "false", matchIfMissing = true)
-public class DefaultXdomeaProperties implements XdomeaProperties {
-
-	private static final String EXCEPTION_MESSAGE = "The feature vorgang-export must be active to access this property.";
-
-	@Override
-	public String getBehoerdenschluessel() {
-		throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
-	}
-
-	@Override
-	public String getBehoerdenschluesselUri() {
-		throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
-	}
-
-	@Override
-	public String getBehoerdenschluesselVersion() {
-		throw new UnsupportedOperationException(EXCEPTION_MESSAGE);
-	}
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportConfiguration.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportConfiguration.java
index 8840c0ac344b8d8d84fde3d7d48a96ec76794267..1ad1ea37461edf34756e2f478e3b56cc74e2bd88 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportConfiguration.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportConfiguration.java
@@ -3,12 +3,12 @@ package de.ozgcloud.alfa.export;
 import java.util.HashMap;
 import java.util.Map;
 
-import jakarta.xml.bind.Marshaller;
-
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+import org.springframework.validation.Validator;
 
+import jakarta.xml.bind.Marshaller;
 import lombok.RequiredArgsConstructor;
 
 @RequiredArgsConstructor
@@ -21,6 +21,11 @@ class ExportConfiguration {
 
 	private final XdomeaNamespacePrefixMapper prefixMapper;
 
+	@Bean
+	static Validator configurationPropertiesValidator() {
+		return new XdomeaPropertiesValidator();
+	}
+
 	@Bean
 	Jaxb2Marshaller marshaller() {
 		var marshaller = new Jaxb2Marshaller();
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangProcessor.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangProcessor.java
index cd93a4d4c15df7e7f57bcc02668076f4c2efdd15..b7621e342cb52f19593b07ee03384b25285feb6e 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangProcessor.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportVorgangProcessor.java
@@ -10,7 +10,6 @@ import org.springframework.hateoas.LinkRelation;
 import org.springframework.hateoas.server.RepresentationModelProcessor;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.alfa.common.FeatureToggleProperties;
 import de.ozgcloud.alfa.common.ModelBuilder;
 import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus;
 import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
@@ -20,13 +19,10 @@ import lombok.RequiredArgsConstructor;
 @Component
 class ExportVorgangProcessor implements RepresentationModelProcessor<EntityModel<VorgangWithEingang>> {
 
-	private final Predicate<VorgangWithEingang> isExportEnabled = vorgang -> isExportEnabled();
 	private static final Predicate<VorgangWithEingang> IS_VORGANG_ABGESCHLOSSEN = vorgang -> vorgang.getStatus() == VorgangStatus.ABGESCHLOSSEN;
 
 	static final LinkRelation REL_EXPORT = LinkRelation.of("export");
 
-	private final FeatureToggleProperties featureToggleProperties;
-
 	@Override
 	public EntityModel<VorgangWithEingang> process(EntityModel<VorgangWithEingang> model) {
 		var vorgang = model.getContent();
@@ -36,12 +32,8 @@ class ExportVorgangProcessor implements RepresentationModelProcessor<EntityModel
 		}
 
 		return ModelBuilder.fromModel(model)
-				.ifMatch(isExportEnabled.and(IS_VORGANG_ABGESCHLOSSEN))
+				.ifMatch(IS_VORGANG_ABGESCHLOSSEN)
 				.addLink(linkTo(methodOn(ExportVorgangController.class).exportToXdomea(vorgang.getId())).withRel(REL_EXPORT))
 				.buildModel();
 	}
-
-	private boolean isExportEnabled() {
-		return featureToggleProperties.isVorgangExport();
-	}
 }
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExternalXdomeaProperties.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExternalXdomeaProperties.java
deleted file mode 100644
index 924bc8c28890c805e728af255a10a80b0c2cc575..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExternalXdomeaProperties.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-
-import jakarta.validation.constraints.NotNull;
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-@Configuration
-@ConfigurationProperties("ozgcloud.xdomea")
-@ConditionalOnProperty(value = "ozgcloud.feature.vorgang-export", havingValue = "true")
-public class ExternalXdomeaProperties implements XdomeaProperties {
-
-	@NotNull
-	private String behoerdenschluessel;
-	@NotNull
-	private String behoerdenschluesselUri;
-	@NotNull
-	private String behoerdenschluesselVersion;
-}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XdomeaProperties.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XdomeaProperties.java
index bedb3877aeafe1401e8ca5a8e82727e2da1e963a..2d2157c690d1b1c354875b477ec6163752cc1234 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XdomeaProperties.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XdomeaProperties.java
@@ -1,10 +1,26 @@
 package de.ozgcloud.alfa.export;
 
-public interface XdomeaProperties {
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
 
-	String getBehoerdenschluessel();
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
 
-	String getBehoerdenschluesselUri();
+@Configuration
+@ConfigurationProperties("ozgcloud.xdomea")
+@Validated
+@Builder
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class XdomeaProperties {
 
-	String getBehoerdenschluesselVersion();
+	private String behoerdenschluessel;
+	private String behoerdenschluesselUri;
+	private String behoerdenschluesselVersion;
 }
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidator.java
new file mode 100644
index 0000000000000000000000000000000000000000..8cc320ecb6346fbc79bd42a2826b08bec38aaff3
--- /dev/null
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidator.java
@@ -0,0 +1,44 @@
+package de.ozgcloud.alfa.export;
+
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.validation.Errors;
+import org.springframework.validation.Validator;
+
+import de.ozgcloud.common.errorhandling.TechnicalException;
+
+public class XdomeaPropertiesValidator implements Validator {
+
+	@Override
+	public boolean supports(Class<?> clazz) {
+		return XdomeaProperties.class.isAssignableFrom(clazz);
+	}
+
+	@Override
+	public void validate(Object target, Errors errors) {
+		var properties = (XdomeaProperties) target;
+		validateBehoerdenschluesselProperties(errors, properties);
+	}
+
+	private void validateBehoerdenschluesselProperties(Errors errors, XdomeaProperties properties) {
+		if (StringUtils.isNotBlank(properties.getBehoerdenschluessel())) {
+			validateNotBlank("behoerdenschluesselUri", properties, errors);
+			validateNotBlank("behoerdenschluesselVersion", properties, errors);
+		}
+	}
+
+	private void validateNotBlank(String propertyName, XdomeaProperties properties, Errors errors) {
+		getPropertyValue(propertyName, properties);
+		if (StringUtils.isBlank(getPropertyValue(propertyName, properties))) {
+			errors.rejectValue(propertyName, String.format("ozgcloud.xdomea.%s.empty", propertyName), String.format("%s must be set", propertyName));
+		}
+	}
+
+	private static String getPropertyValue(String fieldName, XdomeaProperties properties) {
+		try {
+			return BeanUtils.getSimpleProperty(properties, fieldName);
+		} catch (Exception e) {
+			throw new TechnicalException("Property does not exist", e);
+		}
+	}
+}
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/historie/ExportHistorieService.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/historie/ExportHistorieService.java
index 827cfa4b00d8a52024ae35e562f539e54cb64f61..4f3e62cffd7e5a5e07f7dccc55a2f8ca59e092f7 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/historie/ExportHistorieService.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/historie/ExportHistorieService.java
@@ -42,17 +42,22 @@ public class ExportHistorieService {
 	}
 
 	String createValueBeforeChange(VorgangChange vorgangChange) {
-		if (vorgangChange.getOrder().equals(CommandOrder.ASSIGN_USER.name())) {
-			return appendOrganisationseinheitenID(vorgangChange.getValueBeforeChange(), vorgangChange.getOrganisationseinheitenID());
-		}
-		return vorgangChange.getValueBeforeChange();
+		return createValueChange(vorgangChange, vorgangChange.getValueBeforeChange());
 	}
 
 	String createValueAfterChange(VorgangChange vorgangChange) {
-		if (vorgangChange.getOrder().equals(CommandOrder.ASSIGN_USER.name())) {
-			return appendOrganisationseinheitenID(vorgangChange.getValueAfterChange(), vorgangChange.getOrganisationseinheitenID());
+		return createValueChange(vorgangChange, vorgangChange.getValueAfterChange());
+	}
+
+	private String createValueChange(VorgangChange vorgangChange, String valueChange) {
+		if (isAssignUserOrder(vorgangChange)) {
+			return appendOrganisationseinheitenID(valueChange, vorgangChange.getOrganisationseinheitenID());
 		}
-		return vorgangChange.getValueAfterChange();
+		return valueChange;
+	}
+
+	private boolean isAssignUserOrder(VorgangChange vorgangChange) {
+		return vorgangChange.getOrder().equals(CommandOrder.ASSIGN_USER.name());
 	}
 
 	String appendOrganisationseinheitenID(String text, String organisationseinheitenID) {
diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KopfCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KopfCreator.java
index f23b06bdff34f335838f388ca0da9e389af0eedc..5305519177c60d83ac4de118977b4fbd4c549fa2 100644
--- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KopfCreator.java
+++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/KopfCreator.java
@@ -15,6 +15,7 @@ import de.xoev.xdomea.NachrichtentypCodeType;
 import de.xoev.xdomea.NkAbgabeType;
 import de.xoev.xdomea.OrganisationseinheitType;
 import de.xoev.xdomea.SystemType;
+import io.micrometer.common.util.StringUtils;
 import lombok.RequiredArgsConstructor;
 
 @RequiredArgsConstructor
@@ -26,7 +27,7 @@ class KopfCreator {
 	static final String NACHRICHTENTYP_ABGABE_ABGABE_TYPE_CODE = "0401";
 	static final String PRODUKT_NAME = "OZG-Cloud";
 
-	private final XdomeaProperties xDomeaProperties;
+	private final XdomeaProperties xdomeaProperties;
 
 	public NkAbgabeType createKopf(VorgangWithEingang vorgang) {
 		var nkAbgabeType = new NkAbgabeType();
@@ -57,7 +58,9 @@ class KopfCreator {
 
 	KontaktType createKontaktType() {
 		var kontakt = new KontaktType();
-		kontakt.setBehoerdenkennung(createBehoerdenkennung());
+		if (StringUtils.isNotBlank(xdomeaProperties.getBehoerdenschluessel())) {
+			kontakt.setBehoerdenkennung(createBehoerdenkennung());
+		}
 		return kontakt;
 	}
 
@@ -75,9 +78,9 @@ class KopfCreator {
 
 	Code createBehoerdenschluessel() {
 		var behoerdenschluessel = new Code();
-		behoerdenschluessel.setCode(xDomeaProperties.getBehoerdenschluessel());
-		behoerdenschluessel.setListURI(xDomeaProperties.getBehoerdenschluesselUri());
-		behoerdenschluessel.setListVersionID(xDomeaProperties.getBehoerdenschluesselVersion());
+		behoerdenschluessel.setCode(xdomeaProperties.getBehoerdenschluessel());
+		behoerdenschluessel.setListURI(xdomeaProperties.getBehoerdenschluesselUri());
+		behoerdenschluessel.setListVersionID(xdomeaProperties.getBehoerdenschluesselVersion());
 		return behoerdenschluessel;
 	}
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFilenameGeneratorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFilenameGeneratorTest.java
index 1b85ad584d8f2bea60f283e6f20be763731173de..0cf25b49436886e9478b67c4e204ff824c9abed9 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFilenameGeneratorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportFilenameGeneratorTest.java
@@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.MockedStatic;
 
 import de.ozgcloud.alfa.common.ExportFilenameGenerator;
-import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.AlfaTestUtils;
 import de.ozgcloud.alfa.common.UUIDConverter;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
@@ -48,7 +48,7 @@ class ExportFilenameGeneratorTest {
 		void shouldGenerate() {
 			var filename = callGenerator();
 
-			assertThat(filename).matches(String.format("^%s_%s$", TestUtils.UUID_REGEX, ozgFile.getName()));
+			assertThat(filename).matches(String.format("^%s_%s$", AlfaTestUtils.UUID_REGEX, ozgFile.getName()));
 		}
 
 		private String callGenerator() {
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceITCase.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceITCase.java
index 4cf6d583e155be78b4d3d0020b700cf9723c6232..a55f463cb200af363bfef7d3a08e39c15066b0d2 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceITCase.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceITCase.java
@@ -1,6 +1,6 @@
 package de.ozgcloud.alfa.export;
 
-import static de.ozgcloud.alfa.common.TestUtils.*;
+import static de.ozgcloud.alfa.common.AlfaTestUtils.*;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java
index df101b3da9a0289adfc7f9322e2e30a122b62715..35bc4766a34a31b28701ce62ee9ec29a4033bf53 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java
@@ -1,6 +1,6 @@
 package de.ozgcloud.alfa.export;
 
-import static de.ozgcloud.alfa.common.TestUtils.*;
+import static de.ozgcloud.alfa.common.AlfaTestUtils.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -31,7 +31,7 @@ import de.ozgcloud.alfa.bescheid.BescheidExportDataTestFactory;
 import de.ozgcloud.alfa.bescheid.ExportBescheidService;
 import de.ozgcloud.alfa.common.ExportFilenameGenerator;
 import de.ozgcloud.alfa.common.HistorienProtokollInformationTypeTestFactory;
-import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.AlfaTestUtils;
 import de.ozgcloud.alfa.common.file.OzgFile;
 import de.ozgcloud.alfa.common.file.OzgFileTestFactory;
 import de.ozgcloud.alfa.file.ExportFileService;
@@ -397,7 +397,7 @@ class ExportServiceTest {
 		void shouldMatchPattern() {
 			var filename = service.buildXmlFilename(UUID.randomUUID().toString());
 
-			assertThat(filename).matches(TestUtils.uuidRegexWithSuffix(ExportService.EXPORT_FILENAME_SUFFIX));
+			assertThat(filename).matches(AlfaTestUtils.uuidRegexWithSuffix(ExportService.EXPORT_FILENAME_SUFFIX));
 		}
 	}
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangControllerTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangControllerTest.java
index 61ee1269d53784bb31df5c85fdc192c667cdf338..e83d251ba893e0efd9df548cdbe29846ebd4240c 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangControllerTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangControllerTest.java
@@ -21,7 +21,7 @@ import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.AlfaTestUtils;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
 
 class ExportVorgangControllerTest {
@@ -47,7 +47,7 @@ class ExportVorgangControllerTest {
 		void shouldMatchPattern() {
 			var filename = controller.buildZipFilename(UUID.randomUUID().toString());
 
-			assertThat(filename).matches(TestUtils.uuidRegexWithSuffix("_Abgabe.Abgabe.0401.xdomea"));
+			assertThat(filename).matches(AlfaTestUtils.uuidRegexWithSuffix("_Abgabe.Abgabe.0401.xdomea"));
 		}
 	}
 
@@ -74,7 +74,7 @@ class ExportVorgangControllerTest {
 			doRequest();
 
 			verify(xDomeaService).writeExport(eq(VorgangHeaderTestFactory.ID), filenameIdArgumentCaptor.capture(), any());
-			assertThat(filenameIdArgumentCaptor.getValue()).matches(TestUtils.UUID_REGEX);
+			assertThat(filenameIdArgumentCaptor.getValue()).matches(AlfaTestUtils.UUID_REGEX);
 		}
 
 		@Test
@@ -83,7 +83,7 @@ class ExportVorgangControllerTest {
 
 			verify(controller).buildZipFilename(filenameIdArgumentCaptor.capture());
 
-			assertThat(filenameIdArgumentCaptor.getValue()).matches(TestUtils.UUID_REGEX);
+			assertThat(filenameIdArgumentCaptor.getValue()).matches(AlfaTestUtils.UUID_REGEX);
 
 		}
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangProcessorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangProcessorTest.java
index 27ed62377f845026eb3265b2a23f0694188c2579..1443f94482daadc8ab02a10a9ebeaa17a3045457 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangProcessorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportVorgangProcessorTest.java
@@ -2,7 +2,6 @@ package de.ozgcloud.alfa.export;
 
 import static de.ozgcloud.alfa.common.UserProfileUrlProviderTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
-import static org.mockito.Mockito.*;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
@@ -11,11 +10,9 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.EnumSource;
 import org.mockito.InjectMocks;
-import org.mockito.Mock;
 import org.springframework.hateoas.EntityModel;
 import org.springframework.hateoas.Link;
 
-import de.ozgcloud.alfa.common.FeatureToggleProperties;
 import de.ozgcloud.alfa.common.UserProfileUrlProvider;
 import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus;
 import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
@@ -27,9 +24,6 @@ class ExportVorgangProcessorTest {
 	@InjectMocks
 	private ExportVorgangProcessor processor;
 
-	@Mock
-	private FeatureToggleProperties featureToggleProperties;
-
 	private final UserProfileUrlProvider urlProvider = new UserProfileUrlProvider();
 
 	@Nested
@@ -45,8 +39,7 @@ class ExportVorgangProcessorTest {
 			}
 
 			@Test
-			void shouldAddLinkWhenExportIsEnabledAndVorgangIsAbgeschlossen() {
-				when(featureToggleProperties.isVorgangExport()).thenReturn(true);
+			void shouldAddLinkWhenVorgangIsAbgeschlossen() {
 				var vorgang = vorgangInStatus(VorgangStatus.ABGESCHLOSSEN);
 
 				var model = processor.process(EntityModel.of(vorgang));
@@ -58,7 +51,6 @@ class ExportVorgangProcessorTest {
 			@ParameterizedTest
 			@EnumSource(mode = EnumSource.Mode.EXCLUDE, names = "ABGESCHLOSSEN")
 			void shouldNotAddLinkWhenVorgangIsNotAbgeschlossen(VorgangStatus status) {
-				when(featureToggleProperties.isVorgangExport()).thenReturn(true);
 				var vorgang = vorgangInStatus(status);
 
 				var model = processor.process(EntityModel.of(vorgang));
@@ -66,16 +58,6 @@ class ExportVorgangProcessorTest {
 				assertThat(model.getLink(ExportVorgangProcessor.REL_EXPORT)).isEmpty();
 			}
 
-			@Test
-			void shouldNotAddLinkWhenExportIsDisabled() {
-				when(featureToggleProperties.isVorgangExport()).thenReturn(false);
-				var vorgang = vorgangInStatus(VorgangStatus.ABGESCHLOSSEN);
-
-				var model = processor.process(EntityModel.of(vorgang));
-
-				assertThat(model.getLink(ExportVorgangProcessor.REL_EXPORT)).isEmpty();
-			}
-
 			private VorgangWithEingang vorgangInStatus(VorgangStatus status) {
 				return VorgangWithEingangTestFactory.createBuilder().status(status).build();
 			}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/UUIDConverterTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/UUIDConverterTest.java
index f3da0c5f65cf046199af868553c39e19c413ce03..2af0c16013bf75ec4f81c938aad8092afc884083 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/UUIDConverterTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/UUIDConverterTest.java
@@ -5,7 +5,7 @@ import static org.assertj.core.api.Assertions.*;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
-import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.AlfaTestUtils;
 import de.ozgcloud.alfa.common.UUIDConverter;
 
 class UUIDConverterTest {
@@ -17,7 +17,7 @@ class UUIDConverterTest {
 		void shouldReturnUUID() {
 			var result = UUIDConverter.fromObjectId("64a820d36285172ac02826d0");
 
-			assertThat(result).isEqualTo("64a820d3-6285-172a-c028-0000000026d0").matches(TestUtils.UUID_REGEX);
+			assertThat(result).isEqualTo("64a820d3-6285-172a-c028-0000000026d0").matches(AlfaTestUtils.UUID_REGEX);
 		}
 
 		@Test
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesTest.java
deleted file mode 100644
index e44fadad0ec3d14b3d261b45fe5b8dc30cbb7669..0000000000000000000000000000000000000000
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package de.ozgcloud.alfa.export;
-
-import static org.assertj.core.api.AssertionsForClassTypes.*;
-
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.context.TestPropertySource;
-
-public class XdomeaPropertiesTest {
-
-	@Nested
-	@SpringBootTest(properties = {"ozgcloud.feature.vorgang-export=false"})
-	class OnMissingVorgangExportFeature {
-
-		@Autowired
-		XdomeaProperties xdomeaProperties;
-
-		@Test
-		void shouldPropertiesBeOfTypeDefault(){
-			assertThat(xdomeaProperties).isInstanceOf(DefaultXdomeaProperties.class);
-		}
-
-		@Test
-		void shouldBehoerdenschluesselThrowException(){
-			assertThatThrownBy(() -> xdomeaProperties.getBehoerdenschluessel()).isInstanceOf(UnsupportedOperationException.class);
-		}
-
-		@Test
-		void shouldBehoerdenschluesselUriThrowException(){
-			assertThatThrownBy(() -> xdomeaProperties.getBehoerdenschluesselUri()).isInstanceOf(UnsupportedOperationException.class);
-		}
-
-		@Test
-		void shouldBehoerdenschluesselVersionThrowException(){
-			assertThatThrownBy(() -> xdomeaProperties.getBehoerdenschluesselVersion()).isInstanceOf(UnsupportedOperationException.class);
-		}
-	}
-
-	@Nested
-	@SpringBootTest
-	@ActiveProfiles({"itcase"})
-	class OnActiveVorgangExportFeature {
-
-		@Autowired
-		XdomeaProperties xdomeaProperties;
-
-		@Test
-		void shouldPropertiesBeOfTypeConfig(){
-			assertThat(xdomeaProperties).isInstanceOf(ExternalXdomeaProperties.class);
-		}
-
-		@Test
-		void shouldBehoerdenschluesselBeSet(){
-			assertThat(xdomeaProperties.getBehoerdenschluessel()).isEqualTo("ABC");
-		}
-
-		@Test
-		void shouldBehoerdenschluesselUriBeSet(){
-			assertThat(xdomeaProperties.getBehoerdenschluesselUri()).isEqualTo("http://meine.behoer.de");
-		}
-
-		@Test
-		void shouldBehoerdenschluesselVersionBeSet(){
-			assertThat(xdomeaProperties.getBehoerdenschluesselVersion()).isEqualTo("1.0.15b");
-		}
-	}
-}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesTestFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..78d786011aeedec05d51b6407305c2fb3769a626
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesTestFactory.java
@@ -0,0 +1,23 @@
+package de.ozgcloud.alfa.export;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.alfa.export.XdomeaProperties.XdomeaPropertiesBuilder;
+
+public class XdomeaPropertiesTestFactory {
+
+	public static final String BEHOERDENSCHLUESSEL = LoremIpsum.getInstance().getWords(1);
+	public static final String BEHOERDENSCHLUESSEL_URI = LoremIpsum.getInstance().getUrl();
+	public static final String BEHOERDENSCHLUESSEL_VERSION =  LoremIpsum.getInstance().getWords(1);
+
+	public static XdomeaProperties create() {
+		return createBuilder().build();
+	}
+
+	public static XdomeaPropertiesBuilder createBuilder() {
+		return new XdomeaPropertiesBuilder()
+				.behoerdenschluessel(BEHOERDENSCHLUESSEL)
+				.behoerdenschluesselUri(BEHOERDENSCHLUESSEL_URI)
+				.behoerdenschluesselVersion(BEHOERDENSCHLUESSEL_VERSION);
+	}
+}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidatorITCase.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidatorITCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..451d2c7c49059af03d5e26034ad45f7bc6929998
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidatorITCase.java
@@ -0,0 +1,17 @@
+package de.ozgcloud.alfa.export;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+
+import de.ozgcloud.common.test.ITCase;
+
+@ITCase
+class XdomeaPropertiesValidatorITCase {
+
+	@Test
+	void shouldExistInApplicationContext(ApplicationContext context) {
+		assertThat(context.getBean("configurationPropertiesValidator")).isNotNull().isInstanceOf(XdomeaPropertiesValidator.class);
+	}
+}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd6cf19672ab8118254ded34a4b2444d921f8f55
--- /dev/null
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/XdomeaPropertiesValidatorTest.java
@@ -0,0 +1,138 @@
+package de.ozgcloud.alfa.export;
+
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.mockito.Spy;
+import org.springframework.validation.Errors;
+
+class XdomeaPropertiesValidatorTest {
+
+	@Spy
+	private XdomeaPropertiesValidator validator;
+
+	@Nested
+	class TestSupports {
+
+		@Test
+		void shouldSupportXdomeaProperties() {
+			var supports = validator.supports(XdomeaProperties.class);
+
+			assertThat(supports).isTrue();
+		}
+	}
+
+	@Nested
+	class TestValidate {
+
+		@Test
+		void shouldBeValidIfAllBehoerdenschluesselPropertiesAreSet() {
+			var properties = XdomeaPropertiesTestFactory.create();
+
+			var errors = validate(properties);
+
+			assertThat(errors.hasErrors()).isFalse();
+		}
+
+		@ParameterizedTest
+		@NullAndEmptySource
+		void shouldBeValidIfBehoerdenschluesselIsNotSet(String behoerdenschluessel) {
+			var properties = XdomeaPropertiesTestFactory.createBuilder().behoerdenschluessel(behoerdenschluessel).build();
+
+			var errors = validate(properties);
+
+			assertThat(errors.hasErrors()).isFalse();
+		}
+
+		@Nested
+		class OnUriNotSet {
+
+			private static final String PROPERTY_NAME = "behoerdenschluesselUri";
+			public static final String PROPERTY_PATH = "ozgcloud.xdomea." + PROPERTY_NAME;
+			public static final String ERROR_CODE = PROPERTY_PATH + ".empty";
+
+			@ParameterizedTest
+			@NullAndEmptySource
+			void shouldHaveFieldErrors(String uri) {
+				var properties = withBehoerdenschluesselUri(uri);
+
+				var errors = validate(properties);
+
+				assertThat(errors.hasFieldErrors(PROPERTY_NAME)).isTrue();
+			}
+
+			@ParameterizedTest
+			@NullAndEmptySource
+			void shouldHaveMeaningfulErrorMessage(String uri) {
+				var properties = withBehoerdenschluesselUri(uri);
+
+				var errors = validate(properties);
+
+				assertThat(errors.getFieldError(PROPERTY_NAME).getDefaultMessage()).contains(PROPERTY_NAME);
+			}
+
+			@ParameterizedTest
+			@NullAndEmptySource
+			void shouldHaveErrorCode(String uri) {
+				var properties = withBehoerdenschluesselUri(uri);
+
+				var errors = validate(properties);
+
+				assertThat(errors.getFieldError(PROPERTY_NAME).getCode()).isEqualTo(ERROR_CODE);
+			}
+
+			private XdomeaProperties withBehoerdenschluesselUri(String uri) {
+				return XdomeaPropertiesTestFactory.createBuilder().behoerdenschluesselUri(uri).build();
+			}
+		}
+
+		@Nested
+		class OnVersionNotSet {
+
+			public static final String PROPERTY_NAME = "behoerdenschluesselVersion";
+			public static final String PROPERTY_PATH = "ozgcloud.xdomea." + PROPERTY_NAME;
+			public static final String ERROR_CODE = PROPERTY_PATH + ".empty";
+
+			@ParameterizedTest
+			@NullAndEmptySource
+			void shouldHaveFieldErrors(String version) {
+				var properties = withBehoerdenschluesselVersion(version);
+
+				var errors = validate(properties);
+
+				assertThat(errors.hasFieldErrors(PROPERTY_NAME)).isTrue();
+			}
+
+			@ParameterizedTest
+			@NullAndEmptySource
+			void shouldHaveMeaningfulErrorMessage(String version) {
+				var properties = withBehoerdenschluesselVersion(version);
+
+				var errors = validate(properties);
+
+				assertThat(errors.getFieldError(PROPERTY_NAME).getDefaultMessage()).contains(PROPERTY_NAME);
+			}
+
+			@ParameterizedTest
+			@NullAndEmptySource
+			void shouldHaveErrorCode(String version) {
+				var properties = withBehoerdenschluesselVersion(version);
+
+				var errors = validate(properties);
+
+				assertThat(errors.getFieldError(PROPERTY_NAME).getCode()).isEqualTo(ERROR_CODE);
+			}
+
+			private XdomeaProperties withBehoerdenschluesselVersion(String version) {
+				return XdomeaPropertiesTestFactory.createBuilder().behoerdenschluesselVersion(version).build();
+			}
+		}
+
+		private Errors validate(XdomeaProperties properties) {
+			return validator.validateObject(properties);
+		}
+	}
+}
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KopfCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KopfCreatorTest.java
index 0c72b5ad9ff5d21840af73074a8f244c3899b0ab..ad2a07d492a41a25956fe6032f940df5b82c0f9e 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KopfCreatorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/KopfCreatorTest.java
@@ -1,5 +1,6 @@
 package de.ozgcloud.alfa.vorgang;
 
+import static de.ozgcloud.alfa.export.XdomeaPropertiesTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
@@ -13,6 +14,8 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.MockedStatic;
@@ -38,9 +41,7 @@ class KopfCreatorTest {
 	private KopfCreator creator;
 
 	@Mock
-	private XdomeaProperties xDomeaProperties;
-	@Mock
-	private DateConverter dateConverter;
+	private XdomeaProperties xdomeaProperties;
 
 	@Nested
 	class TestCreateKopf {
@@ -170,9 +171,6 @@ class KopfCreatorTest {
 	@Nested
 	class TestCreateAbsender {
 
-		@Mock
-		private BehoerdenkennungType behoerdenkennungType;
-
 		@Test
 		void shouldCallCreateKontaktType() {
 			creator.createAbsender(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID);
@@ -194,15 +192,54 @@ class KopfCreatorTest {
 	@Nested
 	class TestCreateKontaktType {
 
-		@Test
-		void shouldSetBehoerdenkennungType() {
-			var expectedValue = new BehoerdenkennungType();
-			doReturn(expectedValue).when(creator).createBehoerdenkennung();
+		@Nested
+		class OnBehoerdenschluesselNotSet {
+
+			@ParameterizedTest
+			@NullAndEmptySource
+			void shouldNotCreateBehoerdenkennung(String behoerdenschluessel) {
+				when(xdomeaProperties.getBehoerdenschluessel()).thenReturn(behoerdenschluessel);
+
+				creator.createKontaktType();
+
+				verify(creator, never()).createBehoerdenkennung();
+			}
+
+			@ParameterizedTest
+			@NullAndEmptySource
+			void shouldNotSetBehoerdenkennung(String behoerdenschluessel) {
+				when(xdomeaProperties.getBehoerdenschluessel()).thenReturn(behoerdenschluessel);
+
+				var kontaktType = creator.createKontaktType();
 
-			var kontaktType = creator.createAbsender(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID);
+				assertThat(kontaktType.getBehoerdenkennung()).isNull();
+			}
+		}
+
+		@Nested
+		class OnBehoerdenschluesselSet {
+
+			private static final BehoerdenkennungType expectedValue = new BehoerdenkennungType();
+
+			@BeforeEach
+			void init() {
+				when(xdomeaProperties.getBehoerdenschluessel()).thenReturn(BEHOERDENSCHLUESSEL);
+				doReturn(expectedValue).when(creator).createBehoerdenkennung();
+			}
+
+			@Test
+			void shouldCreateBehoerdenkennung() {
+				creator.createKontaktType();
+
+				verify(creator).createBehoerdenkennung();
+			}
 
-			assertThat(kontaktType.getBehoerdenkennung()).isEqualTo(expectedValue);
+			@Test
+			void shouldSetBehoerdenkennung() {
+				var kontaktType = creator.createKontaktType();
 
+				assertThat(kontaktType.getBehoerdenkennung()).isEqualTo(expectedValue);
+			}
 		}
 	}
 
@@ -220,11 +257,22 @@ class KopfCreatorTest {
 	@Nested
 	class TestCreateBehoerdenkennung {
 
-		@Test
-		void shouldSetBehoerdenschluessel() {
-			var expectedBehoerdenschluessel = new Code();
+		private final Code expectedBehoerdenschluessel = new Code();
+
+		@BeforeEach
+		void init() {
 			doReturn(expectedBehoerdenschluessel).when(creator).createBehoerdenschluessel();
+		}
+
+		@Test
+		void shouldcreateBehoerdenschluessel() {
+			creator.createBehoerdenkennung();
+
+			verify(creator).createBehoerdenschluessel();
+		}
 
+		@Test
+		void shouldSetBehoerdenschluessel() {
 			var behoerdenkennungType = creator.createBehoerdenkennung();
 
 			assertThat(behoerdenkennungType.getBehoerdenschluessel()).isEqualTo(expectedBehoerdenschluessel);
@@ -234,34 +282,32 @@ class KopfCreatorTest {
 	@Nested
 	class TestCreateBehoerdenschlussel {
 
+		@BeforeEach
+		void init() {
+			when(xdomeaProperties.getBehoerdenschluessel()).thenReturn(BEHOERDENSCHLUESSEL);
+			when(xdomeaProperties.getBehoerdenschluesselUri()).thenReturn(BEHOERDENSCHLUESSEL_URI);
+			when(xdomeaProperties.getBehoerdenschluesselVersion()).thenReturn(BEHOERDENSCHLUESSEL_VERSION);
+		}
+
 		@Test
 		void shouldSetCode() {
-			var expectedBehoerdenschluessel = LoremIpsum.getInstance().getWords(1);
-			when(xDomeaProperties.getBehoerdenschluessel()).thenReturn(expectedBehoerdenschluessel);
-
 			var behoerdenschlussel = creator.createBehoerdenschluessel();
 
-			assertThat(behoerdenschlussel.getCode()).isEqualTo(expectedBehoerdenschluessel);
+			assertThat(behoerdenschlussel.getCode()).isEqualTo(BEHOERDENSCHLUESSEL);
 		}
 
 		@Test
 		void shouldSetListURI() {
-			var expectedBehoerdenschluesselUri = LoremIpsum.getInstance().getUrl();
-			when(xDomeaProperties.getBehoerdenschluesselUri()).thenReturn(expectedBehoerdenschluesselUri);
-
 			var behoerdenschlussel = creator.createBehoerdenschluessel();
 
-			assertThat(behoerdenschlussel.getListURI()).isEqualTo(expectedBehoerdenschluesselUri);
+			assertThat(behoerdenschlussel.getListURI()).isEqualTo(BEHOERDENSCHLUESSEL_URI);
 		}
 
 		@Test
 		void shouldSetListVersionID() {
-			var expectedBehoerdenschluesselVersion = LoremIpsum.getInstance().getWords(1);
-			when(xDomeaProperties.getBehoerdenschluesselVersion()).thenReturn(expectedBehoerdenschluesselVersion);
-
 			var behoerdenschlussel = creator.createBehoerdenschluessel();
 
-			assertThat(behoerdenschlussel.getListVersionID()).isEqualTo(expectedBehoerdenschluesselVersion);
+			assertThat(behoerdenschlussel.getListVersionID()).isEqualTo(BEHOERDENSCHLUESSEL_VERSION);
 		}
 	}
 
diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreatorTest.java
index 88dc05b51d179cc817b47252c57c3cb20ab81497..47ec3761ac84e0351a9cae1dcea008c995cb80a3 100644
--- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreatorTest.java
+++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/VorgangTypeCreatorTest.java
@@ -12,7 +12,7 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
-import de.ozgcloud.alfa.common.TestUtils;
+import de.ozgcloud.alfa.common.AlfaTestUtils;
 import de.ozgcloud.alfa.export.AllgemeineMetadatenTypeTestFactory;
 import de.ozgcloud.alfa.export.IdentifikationObjektTypeTestFactory;
 import de.xoev.xdomea.AllgemeineMetadatenType;
@@ -183,7 +183,7 @@ class VorgangTypeCreatorTest {
 		void shouldHaveId() {
 			var identifikation = creator.createIdentifikation();
 
-			assertThat(identifikation.getID()).matches(TestUtils.UUID_REGEX);
+			assertThat(identifikation.getID()).matches(AlfaTestUtils.UUID_REGEX);
 		}
 
 		@Test
diff --git a/alfa-xdomea/src/test/resources/application-itcase.yaml b/alfa-xdomea/src/test/resources/application-itcase.yaml
index 8637dea80e839d9c9b817da9756bf1e394ac958d..c6f85b1e94d61d1ee6c5992b97cbac70b7260e24 100644
--- a/alfa-xdomea/src/test/resources/application-itcase.yaml
+++ b/alfa-xdomea/src/test/resources/application-itcase.yaml
@@ -1,6 +1,4 @@
 ozgcloud:
-  feature:
-    vorgang-export: true
   xdomea:
     behoerdenschluessel: ABC
     behoerdenschluesselUri: http://meine.behoer.de
diff --git a/pom.xml b/pom.xml
index 814bc554e80a557f0b17d1e15e5f5c12df36f530..9f392394780ae740b80a1a4c48cc613ae8061467 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,7 +35,7 @@
 
 	<groupId>de.ozgcloud.alfa</groupId>
 	<artifactId>alfa</artifactId>
-	<version>2.10.0-SNAPSHOT</version>
+	<version>2.11.0-SNAPSHOT</version>
 	<name>Alfa Parent</name>
 	<packaging>pom</packaging>
 
diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
index cad88f7ba2e55da7b791497853c8ff633af6aaac..b7221ad6bd6407099a01862c2ffb85bb5199d49d 100644
--- a/src/main/helm/templates/deployment.yaml
+++ b/src/main/helm/templates/deployment.yaml
@@ -98,7 +98,7 @@ spec:
         {{- if ((.Values.ozgcloud).vorgang).bescheid}}
         {{- range $index, $bescheid := ((.Values.ozgcloud).vorgang).bescheid }}
         - name: ozgcloud_vorgang_bescheid_{{ $index }}_formId
-          value: {{ $bescheid.formId }}
+          value: {{ $bescheid.formId | quote }}
         - name: ozgcloud_vorgang_bescheid_{{ $index }}_formEngineName
           value: {{ $bescheid.formEngineName }}
         {{- end }}
diff --git a/src/test/helm/deployment_defaults_env_test.yaml b/src/test/helm/deployment_defaults_env_test.yaml
index 99d108c95f63fc674e22cf2cc369af4db57c0ae5..0bf3a7adbf32e293791d0af1a2804bf7c8c4d6df 100644
--- a/src/test/helm/deployment_defaults_env_test.yaml
+++ b/src/test/helm/deployment_defaults_env_test.yaml
@@ -92,7 +92,7 @@ tests:
             - formEngineName: AFM
               formId: form_id_1
             - formEngineName: FormSolutions
-              formId: form_id_2
+              formId: 2290
     asserts:
       - contains:
           path: spec.template.spec.containers[0].env
@@ -108,7 +108,7 @@ tests:
           path: spec.template.spec.containers[0].env
           content:
             name: ozgcloud_vorgang_bescheid_1_formId
-            value: form_id_2
+            value: "2290"
       - contains:
           path: spec.template.spec.containers[0].env
           content:
diff --git a/src/test/helm/network_policy_test.yaml b/src/test/helm/network_policy_test.yaml
index c74aa40bad0792d6da348b499eae6a22315ea6fa..af65c804e62b7fb9aebb26f65f2322b536f71550 100644
--- a/src/test/helm/network_policy_test.yaml
+++ b/src/test/helm/network_policy_test.yaml
@@ -28,21 +28,30 @@ release:
   namespace: by-helm-test
 templates:
   - templates/network_policy.yaml
-set:
-  networkPolicy:
-    dnsServerNamespace: kube-system
-    ssoPublicIp: 1.1.1.1/32
+
 tests:
   - it: should match apiVersion
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
+        ssoPublicIp: 1.1.1.1/32
     asserts:
       - isAPIVersion:
           of: networking.k8s.io/v1
 
   - it: should match kind
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
+        ssoPublicIp: 1.1.1.1/32
     asserts:
       - isKind:
           of: NetworkPolicy
   - it: validate metadata
+    set:
+      networkPolicy:
+        dnsServerNamespace: kube-system
+        ssoPublicIp: 1.1.1.1/32
     asserts:
       - equal:
           path: metadata
@@ -187,3 +196,31 @@ tests:
     asserts:
       - hasDocuments:
           count: 1
+
+  - it: test network policy dnsServerNamespace must be set message
+    set:
+      networkPolicy:
+        disabled: false
+        ssoPublicIp: 1.1.1.1/32
+    asserts:
+      - failedTemplate:
+          errorMessage: networkPolicy.dnsServerNamespace must be set
+
+
+  - it: test network policy ssoPublicIp must be set message
+    set:
+      networkPolicy:
+        disabled: false
+        dnsServerNamespace: test-dns-server-namespace
+    asserts:
+      - failedTemplate:
+          errorMessage: networkPolicy.ssoPublicIp must be set
+  
+  - it: test network policy should be enabled by default
+    set:
+      networkPolicy:
+        ssoPublicIp: 1.1.1.1
+        dnsServerNamespace: test-dns-server-namespace
+    asserts:
+      - hasDocuments:
+          count: 1
\ No newline at end of file