diff --git a/Jenkinsfile b/Jenkinsfile
index 103c405dd347cc665296085232193cb074b33e11..b80266876dc2f1f182b1f0c2033b82fe1ca58ae2 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -13,6 +13,7 @@ pipeline {
         IMAGE_TAG = ""
         VERSION = ""
         E2E_FAILED = ""
+        HELM_CHART_VERSION = ""
     }
 
     options {
@@ -183,6 +184,28 @@ pipeline {
                 }
             }
         }
+        
+        stage('Test, build and deploy Helm Chart') {
+            steps {
+                container('k8s') {
+                    script {
+                        FAILED_GOOFY_STAGE=env.STAGE_NAME
+                        HELM_CHART_VERSION = generateHelmChartVersion()
+
+                        dir('src/main/helm') {
+                            sh "helm lint -f test-values.yaml"
+
+                            sh "helm unittest -f '../../test/helm/*.yaml' ."
+
+                            sh "helm package --version=${HELM_CHART_VERSION} ."
+
+                            deployHelmChart(HELM_CHART_VERSION)
+                        }
+                    }
+                }
+            }
+        }
+
         stage('Trigger Dev rollout') {
             when {
                 branch 'master'
@@ -214,7 +237,7 @@ pipeline {
                             def stageName = env.STAGE_NAME
                             def bezeichner = generateBezeichner(stageName)
 
-                            startEnvironment(bezeichner, stageName, IMAGE_TAG, true)
+                            startEnvironment(bezeichner, stageName, IMAGE_TAG, true, HELM_CHART_VERSION)
 
                             def testResult = runTests(stageName, bezeichner, 'einheitlicher-ansprechpartner')
 
@@ -242,7 +265,7 @@ pipeline {
                             def stageName = env.STAGE_NAME
                             def bezeichner = generateBezeichner(stageName)
 
-                            startEnvironment(bezeichner, stageName, IMAGE_TAG, false)
+                            startEnvironment(bezeichner, stageName, IMAGE_TAG, false, HELM_CHART_VERSION)
 
                             def testResult = runTests(stageName, bezeichner, 'main-tests')
 
@@ -306,6 +329,34 @@ pipeline {
     }
 }
 
+Void deployHelmChart(String helmChartVersion) {       
+    withCredentials([usernamePassword(credentialsId: 'jenkins-nexus-login', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]){
+        if (env.BRANCH_NAME == 'release') {
+            result = sh script: '''curl -u $USERNAME:$PASSWORD http://nexus.dev-tools:8081/service/rest/v1/components?repository=ozg-base-apps -F file=@goofy-'''+helmChartVersion+'''.tgz''', returnStdout: true
+        }
+        else {
+            result = sh script: '''curl -u $USERNAME:$PASSWORD http://nexus.dev-tools:8081/service/rest/v1/components?repository=ozg-base-apps-snapshot -F file=@goofy-'''+helmChartVersion+'''.tgz''', returnStdout: true
+        }
+
+        if (result != '') {
+            error(result)
+        }
+    }
+}
+
+String generateHelmChartVersion() {
+    def chartVersion = "${VERSION}"
+
+    if (env.BRANCH_NAME == 'master') {
+        chartVersion += "-${env.GIT_COMMIT.take(7)}"
+    }
+    else if (env.BRANCH_NAME != 'release') {
+        chartVersion += "-${env.BRANCH_NAME}"
+    }
+
+    return chartVersion
+}
+
 Void tagAndPushDockerImage(String newTag){
     container("docker") {
         withCredentials([usernamePassword(credentialsId: 'jenkins-docker-login', usernameVariable: 'USER', passwordVariable: 'PASSWORD')]) {
@@ -327,8 +378,8 @@ String generateImageTag() {
     return imageTag
 }
 
-Void startEnvironment(String bezeichner, String stage, String imageTag, Boolean isEa) {
-    setupAnsible(imageTag, stage, isEa)
+Void startEnvironment(String bezeichner, String stage, String imageTag, Boolean isEa, String chartVersion) {
+    setupAnsible(imageTag, stage, isEa, chartVersion)
 
     try {
         deleteKopStack(bezeichner, stage)
@@ -341,14 +392,14 @@ Void startEnvironment(String bezeichner, String stage, String imageTag, Boolean
     addKeycloakUser(bezeichner, stage)
 }
 
-Void setupAnsible(String imageTag, String stage, Boolean isEa) {
+Void setupAnsible(String imageTag, String stage, Boolean isEa, String chartVersion) {
     checkoutProvisioningRepo(stage)
 
     if (env.BRANCH_NAME == 'release') {
         copyTestEnvironmentToDev(stage)
     }
 
-    editEnvironemntVersion(stage, imageTag, isEa)
+    editEnvironemntVersion(stage, imageTag, isEa, chartVersion)
 
     if (isEa) {
         setupEaEnvironment(stage)
@@ -400,7 +451,7 @@ Void copyTestEnvironmentToDev(stage) {
     }
 }
 
-Void editEnvironemntVersion(String stage, String imageTag, Boolean isEa) {
+Void editEnvironemntVersion(String stage, String imageTag, Boolean isEa, String chartVersion) {
     dir("${stage}/provisioning") {
         def editFile = "inventories/group_vars/dev/versions"
 
@@ -416,6 +467,7 @@ Void editEnvironemntVersion(String stage, String imageTag, Boolean isEa) {
         devVersions.values.pluto.put('env', ['overrideSpringProfiles': overrideSpringProfiles])
 
         devVersions.versions.goofy.image.tag = imageTag
+        devVersions.charts.goofy.version = chartVersion
 
         writeYaml file: editFile, data: devVersions, overwrite: true
     }
@@ -743,6 +795,7 @@ Void setNewGoofyProvisioningVersion(String environment) {
         def envVersions = readYaml file: envFile
 
         envVersions.versions.goofy.image.tag = IMAGE_TAG
+        envVersions.charts.goofy.version = HELM_CHART_VERSION
 
         writeYaml file: envFile, data: envVersions, overwrite: true
     }
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/historie/historie.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/historie/historie.e2e-spec.ts
index 4bbddb7020c05495e5ff116a5e633b0411ae4c31..6beecd8570879b42760b3275126fa433c9f08890 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/historie/historie.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/historie/historie.e2e-spec.ts
@@ -128,6 +128,8 @@ describe('Historie', () => {
 		createdAt: { $date: '2020-01-01T10:08:00.000Z' }
 	};
 
+	const resendPostfachNachricht: CommandE2E = buildCommand(CommandOrderE2E.RESEND_POSTFACH_NACHRICHT, vorgang._id.$oid, vorgang._id.$oid);
+
 	const createWiedervorlageCommandBody = { ...createWiedervorlageItem('Create Wiedervorlage Betreff'), attachments: 'DummyAttachment' };
 	const createWiedervorlageCommand: CommandE2E = {
 		...buildCommand(CommandOrderE2E.CREATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid),
@@ -157,7 +159,7 @@ describe('Historie', () => {
 			assignUserCommand,
 			createKommentarCommand, editKommentarCommand,
 			forwardVorgangCommand, forwardSuccessfulCommand, forwardFailedCommand,
-			sendPostfachMailCommand, sendPostfachNachrichtCommand, receivePostfachNachrichtCommand,
+			sendPostfachMailCommand, sendPostfachNachrichtCommand, receivePostfachNachrichtCommand, resendPostfachNachricht,
 			createWiedervorlageCommand, editWiedervorlageCommand, wiedervorlageErledigenCommand, wiedervorlageWiedereroeffnenCommand
 		]);
 		initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserPeter(), getUserManagerUserEmil()]);
@@ -315,12 +317,20 @@ describe('Historie', () => {
 						contains(postfachNachtichtItem.getPostfachNachrichtSubject(), receivePostfachNachrichtCommand.bodyObject.item.subject);
 						contains(postfachNachtichtItem.getPostfachNachrichtMailBody(), receivePostfachNachrichtCommand.bodyObject.item.mailBody);
 					})
+
+					it('resend postfach nachricht', () => {
+						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(9);
+
+						exist(historieItem.getRoot());
+						contains(historieItem.getHeadline(), HistorieHeadlineE2E.RESEND_POSTFACH_NACHRICHT);
+						contains(historieItem.getUser(), userName);
+					})
 				})
 
 				describe('wiedervorlage order', () => {
 
 					it('create wiedervorlage', () => {
-						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(9);
+						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(10);
 
 						exist(historieItem.getRoot());
 						contains(historieItem.getHeadline(), HistorieHeadlineE2E.CREATE_WIEDERVORLAGE);
@@ -336,7 +346,7 @@ describe('Historie', () => {
 					})
 
 					it('edit wiedervorlage', () => {
-						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(10);
+						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(11);
 
 						exist(historieItem.getRoot());
 						contains(historieItem.getHeadline(), HistorieHeadlineE2E.EDIT_WIEDERVORLAGE);
@@ -352,7 +362,7 @@ describe('Historie', () => {
 					})
 
 					it('wiedervorlage erledigen', () => {
-						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(11);
+						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(12);
 
 						exist(historieItem.getRoot());
 						contains(historieItem.getHeadline(), HistorieHeadlineE2E.WIEDERVORLAGE_ERLEDIGEN);
@@ -361,7 +371,7 @@ describe('Historie', () => {
 					})
 
 					it('wiedervorlage wiedereroeffnen', () => {
-						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(12);
+						const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(13);
 
 						exist(historieItem.getRoot());
 						contains(historieItem.getHeadline(), HistorieHeadlineE2E.WIEDERVORLAGE_WIEDEREROEFFNEN);
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts
index 15e549333a89d12f6c5f464cce857bc163b393ab..9e0a15f6c9d0a4b65c8c80c160762e6431834167 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts
@@ -257,4 +257,34 @@ describe('Wiedervorlage attachments', () => {
 			haveLength(attachmentList.getRoot(), 1);
 		})
 	})
+
+	describe.skip('OZG-3070 delete last attachment', () => {
+
+		it('should remove on delete', () => {
+			attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDeleteButton().click();
+			waitForSpinnerToDisappear();
+
+			notExist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot());
+		})
+
+		it('should show snackbar on save', () => {
+			wiedervorlageContainer.getSpeichernButton().click();
+			waitForSpinnerToDisappear();
+
+			exist(snackbar.getMessage());
+			contains(snackbar.getMessage(), `Die Wiedervorlage "${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF}" wurde gespeichert`);
+			snackbar.getCloseButton().click();
+			waitForSpinnerToDisappear();
+		})
+
+		it('should have no attachments after save', () => {
+			const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF);
+
+			wiedervorlageComp.getExpandButton();
+			wiedervorlageComp.expandItem();
+
+			notExist(wiedervorlageComp.getAttachmentContainer().getList().getItem(TEST_FILE_WITHOUT_CONTENT).getRoot());
+			notExist(wiedervorlageComp.getAttachmentContainer().getList().getItem(TEST_FILE_WITH_CONTENT).getRoot());
+		})
+	})
 })
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.e2e-spec.ts
index 41b362b9ad2dc83f31309f5bd9dc15087eb4f346..ff413cf1d1494d95cab940af353cbde8880673c8 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.e2e-spec.ts
@@ -215,4 +215,55 @@ describe('Wiedervorlage', () => {
 			notExist(wiedervorlageInVorgang.getRoot());
 		})
 	})
+
+	describe.skip('OZG-3070 remove beschreibung from wiedervoralge', () => {
+
+		it('should open Wiedervorlage-Page by click on wiedervorlage ', () => {
+			const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage('Editierter Betreff');
+
+			wiedervorlageInVorgang.getLink().click();
+			waitForSpinnerToDisappear();
+
+			exist(wiedervorlagePage.getSubnavigation().getRoot());
+		})
+
+		it('should have beschreibung', () => {
+			haveValue(wiedervorlageCotainer.getBeschreibung(), 'Diese Wiedervorlage wurde bearbeitet');
+		})
+
+		it('should show snackbar after clear beschreibung', () => {
+			wiedervorlageCotainer.getBeschreibung().clear();
+
+			wiedervorlageCotainer.getSpeichernButton().click();
+			waitForSpinnerToDisappear();
+
+			exist(snackbar.getMessage());
+			haveText(snackbar.getMessage(), MessagesE2E.WIEDERVORLAGE_GESPEICHERT.replace('%s', 'Editierter Betreff'));
+		})
+
+		it('should close snackbar on click on close button', () => {
+			snackbar.getCloseButton().click();
+
+			notExist(snackbar.getMessage());
+		})
+
+		it('should navigate after click on "Speichern"', () => {
+			exist(vorgangPage.getVorgangDetailHeader().getRoot());
+		})
+
+		it('should navigate to formular', () => {
+			const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage(wiedervorlageBetreff);
+
+			wiedervorlageInVorgang.getLink().click();
+			waitForSpinnerToDisappear();
+
+			exist(wiedervorlagePage.getSubnavigation().getRoot());
+		})
+
+		it('should show empty beschreibung', () => {
+			wiedervorlageCotainer.getBeschreibung().clear().type('Editierter Betreff');
+
+			haveText(wiedervorlageCotainer.getBeschreibung(), '');
+		})
+	})
 });
diff --git a/goofy-client/apps/goofy-e2e/src/model/command.ts b/goofy-client/apps/goofy-e2e/src/model/command.ts
index c68548d4379883e4258cd0a357e64391fcfab542..e3a50c9e633c23e9c1f942f9c86ce3282b353b45 100644
--- a/goofy-client/apps/goofy-e2e/src/model/command.ts
+++ b/goofy-client/apps/goofy-e2e/src/model/command.ts
@@ -31,9 +31,10 @@ export enum CommandOrderE2E {
 	FORWARD_SUCCESSFUL = 'FORWARD_SUCCESSFULL', //TODO Rename Order
 	FORWARD_FAILED = 'FORWARD_FAILED',
 	PATCH_ATTACHED_ITEM = 'PATCH_ATTACHED_ITEM',
+	RECEIVE_POSTFACH_NACHRICHT = 'RECEIVE_POSTFACH_NACHRICHT',
+	RESEND_POSTFACH_NACHRICHT = 'RESEND_POSTFACH_MAIL',
 	SEND_POSTFACH_MAIL = 'SEND_POSTFACH_MAIL',
 	SEND_POSTFACH_NACHRICHT = 'SEND_POSTFACH_NACHRICHT',
-	RECEIVE_POSTFACH_NACHRICHT = 'RECEIVE_POSTFACH_NACHRICHT',
 	UPDATE_ATTACHED_ITEM = 'UPDATE_ATTACHED_ITEM'
 }
 export class CommandE2E {
diff --git a/goofy-client/apps/goofy-e2e/src/model/historie.ts b/goofy-client/apps/goofy-e2e/src/model/historie.ts
index 74729a9839e7c11a58efa12ac15a738e91b6a107..454be1a37e654ea3fe007607a585abc0c5f70a5f 100644
--- a/goofy-client/apps/goofy-e2e/src/model/historie.ts
+++ b/goofy-client/apps/goofy-e2e/src/model/historie.ts
@@ -35,6 +35,7 @@ export enum HistorieHeadlineE2E {
 	FORWARD_FAILED = 'die Weiterleitung widerrufen.',
 	SEND_POSTFACH_NACHRICHT = 'eine Nachricht geschrieben',
 	RECEIVE_POSTFACH_NACHRICHT = 'eine Nachricht des Antragstellers empfangen.',
+	RESEND_POSTFACH_NACHRICHT = 'eine Nachricht erneut versendet.',
 	WIEDERVORLAGE_ERLEDIGEN = 'eine Wiedervorlage als erledigt markiert.',
 	WIEDERVORLAGE_WIEDEREROEFFNEN = 'eine Wiedervorlage als offen markiert.',
 }
diff --git a/goofy-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts b/goofy-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts
index 8bc12ec5f0886a3ccc50b6154098f60bd975e7f3..624db23cdaa5a21fd0056c905ee91e2366f5a687 100644
--- a/goofy-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts
+++ b/goofy-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts
@@ -26,10 +26,10 @@ import { Injectable } from '@angular/core';
 import { Actions, createEffect, ofType } from '@ngrx/effects';
 import { mergeMap, switchMap, tap } from 'rxjs/operators';
 import { BinaryFileRepository } from '../binary-file.repository';
+import { DownloadBinaryFileAsPdfAction, SaveBinaryFileAsPdfAction } from './binary-file.actions';
 
 import * as saveAs from 'file-saver';
 import * as BinaryFileActions from './binary-file.actions';
-import { DownloadBinaryFileAsPdfAction, SaveBinaryFileAsPdfAction } from './binary-file.actions';
 
 @Injectable()
 export class BinaryFileEffects {
diff --git a/goofy-client/libs/command-shared/src/lib/command.model.ts b/goofy-client/libs/command-shared/src/lib/command.model.ts
index 616a7f6fd2dfc7ac327d260ea65138148af514c6..6579c4078a0cf95bf26ca1b016621ca7a851d3ac 100644
--- a/goofy-client/libs/command-shared/src/lib/command.model.ts
+++ b/goofy-client/libs/command-shared/src/lib/command.model.ts
@@ -64,6 +64,7 @@ export enum CommandOrder {
 	FORWARD_SUCCESSFULL = 'FORWARD_SUCCESSFULL',
 	SEND_POSTFACH_NACHRICHT = 'SEND_POSTFACH_NACHRICHT',
 	RECEIVE_POSTFACH_NACHRICHT = 'RECEIVE_POSTFACH_NACHRICHT',
+	RESEND_POSTFACH_NACHRICHT = 'RESEND_POSTFACH_MAIL',
 	WIEDERVORLAGE_ERLEDIGEN = 'WIEDERVORLAGE_ERLEDIGEN',
 	WIEDERVORLAGE_WIEDEREROEFFNEN = 'WIEDERVORLAGE_WIEDEREROEFFNEN',
 	VORGANG_ANNEHMEN = 'VORGANG_ANNEHMEN',
@@ -96,6 +97,7 @@ export const ORDER_TYPE_BY_COMMAND_ORDER = {
 	[CommandOrder.FORWARD_SUCCESSFULL]: CommandOrderType.FORWARDING,
 	[CommandOrder.SEND_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT,
 	[CommandOrder.RECEIVE_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT,
+	[CommandOrder.RESEND_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT,
 	[CommandOrder.WIEDERVORLAGE_ERLEDIGEN]: CommandOrderType.WIEDERVORLAGE,
 	[CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN]: CommandOrderType.WIEDERVORLAGE,
 	[CommandOrder.VORGANG_ANNEHMEN]: CommandOrderType.VORGANG,
diff --git a/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.html b/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.html
index 7db6f631f0ac80bf8d9d7ecbdfc3148ba2f7261e..2a794893ebb4b6a1cf4a50c72f598877311a749c 100644
--- a/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.html
+++ b/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.html
@@ -23,8 +23,14 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<goofy-client-expansion-panel-with-user [headline]="headline" [resource]="command" data-test-id="historie-item-wiedervorlage-user-expansion-panel">
+<goofy-client-expansion-panel-with-user *ngIf="postfachNachricht; else headlineOnly" [headline]="headline" [resource]="command" data-test-class="historie-item-postfach-nachricht-user-expansion-panel-with-body">
 	<p data-test-class="postfach-nachricht-subject" class="subject">{{postfachNachricht.subject}}</p>
 	<p data-test-class="postfach-nachricht-mail-body">{{postfachNachricht.mailBody}}</p>
-	<goofy-client-historie-item-attachment *ngIf="postfachNachricht.attachments" [attachments]="postfachNachricht.attachments" data-test-id="historie-item-postfach-nachricht-attachment"></goofy-client-historie-item-attachment>
-</goofy-client-expansion-panel-with-user>
\ No newline at end of file
+	<goofy-client-historie-item-attachment *ngIf="postfachNachricht.attachments" [attachments]="postfachNachricht.attachments" data-test-class="historie-item-postfach-nachricht-attachment"></goofy-client-historie-item-attachment>
+</goofy-client-expansion-panel-with-user>
+
+<ng-template #headlineOnly>
+	<div class="mat-expansion-panel">
+		<goofy-client-historie-item-header [resource]="command" [headline]="headline" data-test-class="historie-item-postfach-nachricht-user-expansion-panel"></goofy-client-historie-item-header>
+	</div>
+</ng-template>
\ No newline at end of file
diff --git a/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.scss b/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.scss
index 6eac44297e4cb4f6465335c57fc42b8aa6e88563..a329a524aa72eeeb5e5785155a9e6c9367bf3170 100644
--- a/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.scss
+++ b/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.scss
@@ -21,6 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+@import 'expansion-panel';
+
 .subject {
 	font-weight: bold
 }
\ No newline at end of file
diff --git a/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.spec.ts b/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.spec.ts
index 07c17114170ef1ae3cdfb4d936e1f8302578bb4a..27a196d083e21d5feaa6b9e9ee6842c2a4bf8e83 100644
--- a/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.spec.ts
+++ b/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.spec.ts
@@ -27,11 +27,12 @@ import { CommandOrder, CommandResource } from '@goofy-client/command-shared';
 import { PostfachMail } from '@goofy-client/postfach-shared';
 import { getElementFromFixture } from '@goofy-client/test-utils';
 import { createCommandResource } from 'libs/command-shared/test/command';
-import { createPostfachMail } from 'libs/postfach-shared/test/postfach';
-import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { createPostfachMail, createPostfachMailResource } from 'libs/postfach-shared/test/postfach';
+import { getDataTestClassOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { ExpansionPanelWithUserComponent } from '../expansion-panel-with-user/expansion-panel-with-user.component';
 import { HistorieItemAttachmentComponent } from '../historie-item-attachment/historie-item-attachment.component';
+import { HistorieItemHeaderComponent } from '../historie-item-header/historie-item-header.component';
 import { HistorieItemPostfachNachrichtComponent } from './historie-item-postfach-nachricht.component';
 
 describe('HistorieItemPostfachNachrichtComponent', () => {
@@ -41,14 +42,17 @@ describe('HistorieItemPostfachNachrichtComponent', () => {
 	const item: PostfachMail = createPostfachMail();
 	const postfachNachrichtCommand: CommandResource = { ...createCommandResource(), body: { item: item } };
 
-	const attachment: string = getDataTestIdOf('historie-item-postfach-nachricht-attachment');
+	const attachment: string = getDataTestClassOf('historie-item-postfach-nachricht-attachment');
+	const expansionPanel: string = getDataTestClassOf('historie-item-postfach-nachricht-user-expansion-panel');
+	const mailBody: string = getDataTestClassOf('postfach-nachricht-mail-body');
 
 	beforeEach(async () => {
 		await TestBed.configureTestingModule({
 			declarations: [
 				HistorieItemPostfachNachrichtComponent,
 				MockComponent(ExpansionPanelWithUserComponent),
-				MockComponent(HistorieItemAttachmentComponent)
+				MockComponent(HistorieItemAttachmentComponent),
+				MockComponent(HistorieItemHeaderComponent)
 			],
 		}).compileComponents();
 	});
@@ -136,4 +140,45 @@ describe('HistorieItemPostfachNachrichtComponent', () => {
 			expect(attachmentElement).toBeInstanceOf(HTMLElement);
 		})
 	})
+
+	describe('postfach nachricht body exists', () => {
+
+		beforeEach(() => {
+			component.postfachNachricht = createPostfachMailResource();
+			fixture.detectChanges();
+		})
+
+		it('should show postfach nachricht with body', () => {
+			const element = getElementFromFixture(fixture, mailBody);
+
+			expect(element).toBeInstanceOf(HTMLElement);
+		})
+
+		it('should hide postfach nachricht', () => {
+			const element = getElementFromFixture(fixture, expansionPanel);
+
+			expect(element).not.toBeInstanceOf(HTMLElement);
+		})
+	})
+
+
+	describe('postfach nachricht body not exists', () => {
+
+		beforeEach(() => {
+			component.postfachNachricht = undefined;
+			fixture.detectChanges();
+		})
+
+		it('should show postfach nachricht', () => {
+			const element = getElementFromFixture(fixture, expansionPanel);
+
+			expect(element).toBeInstanceOf(HTMLElement);
+		})
+
+		it('should hide postfach nachricht with body', () => {
+			const element = getElementFromFixture(fixture, mailBody);
+
+			expect(element).not.toBeInstanceOf(HTMLElement);
+		})
+	})
 });
diff --git a/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.ts b/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.ts
index f3382c93cd54a0fbbb4d33d89afff16a4b44c9ea..c70881f46cdcfcc7c8b899ca88faf41f24509d84 100644
--- a/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.ts
+++ b/goofy-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.ts
@@ -54,4 +54,5 @@ export class HistorieItemPostfachNachrichtComponent {
 const HISTORIE_TEXT_BY_POSTFACH_NACHRICHT_ORDER: { [order: string]: string } = {
 	[CommandOrder.SEND_POSTFACH_NACHRICHT]: 'eine Nachricht geschrieben.',
 	[CommandOrder.RECEIVE_POSTFACH_NACHRICHT]: 'eine Nachricht des Antragstellers empfangen.',
+	[CommandOrder.RESEND_POSTFACH_NACHRICHT]: 'eine Nachricht erneut versendet.'
 }
\ No newline at end of file
diff --git a/goofy-client/libs/navigation/src/lib/header-container/header/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html b/goofy-client/libs/navigation/src/lib/header-container/header/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html
index 7ebcad7ebb0909074af07c97848fc32fdc8110bc..f91c097dbbd4ca5959247439dafdcb4574d8b201 100644
--- a/goofy-client/libs/navigation/src/lib/header-container/header/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html
+++ b/goofy-client/libs/navigation/src/lib/header-container/header/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html
@@ -23,7 +23,7 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<button mat-icon-button [matMenuTriggerFor]="accountMenu" class="big-button" aria-label="Benutzerkonto" data-test-id="user-icon-button">
+<button mat-icon-button [matMenuTriggerFor]="accountMenu" class="big-button" data-test-id="user-icon-button">
 	<goofy-client-user-icon [userProfileStateResource]="currentUserResource"></goofy-client-user-icon>
 </button>
 
diff --git a/goofy-client/libs/navigation/src/lib/header-container/header/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.ts b/goofy-client/libs/navigation/src/lib/header-container/header/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.ts
index 38ea843d29cc75117d30e64b26340da1844aa962..14a0a6f108699240de11103655638bac5bc81e72 100644
--- a/goofy-client/libs/navigation/src/lib/header-container/header/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.ts
+++ b/goofy-client/libs/navigation/src/lib/header-container/header/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.ts
@@ -32,6 +32,8 @@ import { UserProfileResource } from '@goofy-client/user-profile-shared';
 	styleUrls: ['./user-profile-in-header.component.scss'],
 })
 export class UserProfileInHeaderComponent {
-	@Output() public logoutEmitter: EventEmitter<void> = new EventEmitter<void>()
+
 	@Input() public currentUserResource: StateResource<UserProfileResource>;
+
+	@Output() public logoutEmitter: EventEmitter<void> = new EventEmitter<void>()
 }
diff --git a/goofy-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts b/goofy-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts
index a119ef5e3cc1b34bc68dca2c0a55138da3a0549a..2be41d689ffe1a01bc74fba57b2ebc876d70f7a7 100644
--- a/goofy-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts
+++ b/goofy-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts
@@ -28,10 +28,10 @@ import { ApiError, ApiErrorAction, formatFullDateWithoutSeperator } from '@goofy
 import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@goofy-client/vorgang-shared';
 import { Store } from '@ngrx/store';
 import { TypedAction } from '@ngrx/store/src/models';
+import { getUrl } from '@ngxp/rest';
 import { Observable } from 'rxjs';
 
 import * as BinaryFileActions from '@goofy-client/binary-file-shared';
-import { getUrl } from '@ngxp/rest';
 import * as PostfachActions from './postfach.actions';
 import * as PostfachSelectors from './postfach.selectors';
 
diff --git a/goofy-client/libs/postfach-shared/src/lib/postfach.model.ts b/goofy-client/libs/postfach-shared/src/lib/postfach.model.ts
index 2a215910a553041d7607d5fbd2dab302a92a5c35..bfd4283af393530533621a7a2cdd37d6b537a393 100644
--- a/goofy-client/libs/postfach-shared/src/lib/postfach.model.ts
+++ b/goofy-client/libs/postfach-shared/src/lib/postfach.model.ts
@@ -61,4 +61,10 @@ export interface CreatePostfachMailCommand extends CreateCommand {
 
 export interface PostfachMailResource extends Resource, PostfachMail { }
 
-export interface PostfachMailListResource extends ListResource { }
\ No newline at end of file
+export interface PostfachMailListResource extends ListResource { }
+
+export enum PostfachNachrichtenCount {
+	NONE,
+	SINGLE,
+	MULTIPLE
+}
\ No newline at end of file
diff --git a/goofy-client/libs/postfach-shared/src/lib/postfach.util.spec.ts b/goofy-client/libs/postfach-shared/src/lib/postfach.util.spec.ts
index ba8beb83a6bcc6d9e55fcc30ca0f06e934aa4106..45933557f8c418aa2ada0769ca72cab98ef1e285 100644
--- a/goofy-client/libs/postfach-shared/src/lib/postfach.util.spec.ts
+++ b/goofy-client/libs/postfach-shared/src/lib/postfach.util.spec.ts
@@ -22,11 +22,12 @@
 /// unter der Lizenz sind dem Lizenztext zu entnehmen.
 ///
 
-import { createPostfachMail, createPostfachMailResource } from 'libs/postfach-shared/test/postfach';
-import { Direction, getMessageCodeMessage, isIncomingMail } from '..';
+import { createPostfachMail, createPostfachMailListResource, createPostfachMailResource } from 'libs/postfach-shared/test/postfach';
+import { toResource } from 'libs/tech-shared/test/resource';
+import { PostfachMailListLinkRel } from './postfach.linkrel';
 import { PostfachNachrichtMessageCode } from './postfach.message-code';
-import { CreatePostfachMailCommand, PostfachMail, PostfachOrder } from './postfach.model';
-import { createResendPostfachMailCommand, createSendPostfachMailCommand } from './postfach.util';
+import { CreatePostfachMailCommand, Direction, PostfachMail, PostfachMailListResource, PostfachMailResource, PostfachNachrichtenCount, PostfachOrder } from './postfach.model';
+import { createResendPostfachMailCommand, createSendPostfachMailCommand, getMessageCodeMessage, getPostfachNachrichtenCount, isIncomingMail } from './postfach.util';
 
 describe('PostfachUtil', () => {
 
@@ -91,4 +92,60 @@ describe('PostfachUtil', () => {
 			expect(result).toEqual('Fehlerhafte Verarbeitung: Die Nachricht wurde an das Osi-Postfach geschickt, konnte dort aber nicht richtig verarbeitet werden.');
 		})
 	})
+
+	describe('getPostfacNachrichtenCount', () => {
+
+		describe('return NONE', () => {
+
+			it('on null listResource', () => {
+				var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(null);
+
+				expect(count).toBe(PostfachNachrichtenCount.NONE);
+			})
+
+			it('on undefined listResource', () => {
+				var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(undefined);
+
+				expect(count).toBe(PostfachNachrichtenCount.NONE);
+			})
+
+			it('should return NONE on empty resource list', () => {
+				var listResource: PostfachMailListResource = createListResource([]);
+
+				var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource);
+
+				expect(count).toBe(PostfachNachrichtenCount.NONE);
+			})
+
+			it('should return NONE on non existing resources', () => {
+				var listResource: PostfachMailListResource = toResource({}, [], {});
+
+				var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource);
+
+				expect(count).toBe(PostfachNachrichtenCount.NONE);
+			})
+		})
+
+		it('should return SINGLE on one existing resources', () => {
+			var listResource: PostfachMailListResource = createListResource([createPostfachMailResource()]);
+
+			var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource);
+
+			expect(count).toBe(PostfachNachrichtenCount.SINGLE);
+		})
+
+		it('should return MULTIPLE on multiple existing resources', () => {
+			var listResource: PostfachMailListResource = createPostfachMailListResource();
+
+			var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource);
+
+			expect(count).toBe(PostfachNachrichtenCount.MULTIPLE);
+		})
+
+		function createListResource(postfachMailResources: PostfachMailResource[]): PostfachMailListResource {
+			return toResource({}, [], {
+				[PostfachMailListLinkRel.POSTFACH_MAIL_LIST]: postfachMailResources
+			});
+		}
+	})
 })
diff --git a/goofy-client/libs/postfach-shared/src/lib/postfach.util.ts b/goofy-client/libs/postfach-shared/src/lib/postfach.util.ts
index fa7f273e4cf59584637a09eb9369891bd13f4e39..a320ac47a9f3f54acd4ae3497ecb35d38636363f 100644
--- a/goofy-client/libs/postfach-shared/src/lib/postfach.util.ts
+++ b/goofy-client/libs/postfach-shared/src/lib/postfach.util.ts
@@ -22,8 +22,11 @@
 /// unter der Lizenz sind dem Lizenztext zu entnehmen.
 ///
 
+import { getEmbeddedResource } from '@ngxp/rest';
+import { isNil } from 'lodash-es';
+import { PostfachMailListLinkRel } from './postfach.linkrel';
 import { postfachNachrichtMessageCodeMessages } from './postfach.message-code';
-import { CreatePostfachMailCommand, Direction, PostfachMail, PostfachMailResource, PostfachOrder } from './postfach.model';
+import { CreatePostfachMailCommand, Direction, PostfachMail, PostfachMailListResource, PostfachMailResource, PostfachNachrichtenCount, PostfachOrder } from './postfach.model';
 
 export function createSendPostfachMailCommand(postfachMail: PostfachMail): CreatePostfachMailCommand {
 	return { order: PostfachOrder.SEND_POSTFACH_NACHRICHT, body: postfachMail };
@@ -39,4 +42,21 @@ export function isIncomingMail(postfachMail: PostfachMailResource): boolean {
 
 export function getMessageCodeMessage(postfachMail: PostfachMailResource): string {
 	return postfachNachrichtMessageCodeMessages[postfachMail.messageCode];
+}
+
+export function getPostfachNachrichtenCount(postfachMailListResource: PostfachMailListResource): PostfachNachrichtenCount {
+	if (isNil(postfachMailListResource)) {
+		return PostfachNachrichtenCount.NONE;
+	}
+
+	const resources: PostfachMailResource[] = getEmbeddedResource<PostfachMailResource[]>(postfachMailListResource, PostfachMailListLinkRel.POSTFACH_MAIL_LIST);
+	if (isNil(resources) || resources.length == 0) {
+		return PostfachNachrichtenCount.NONE;
+	}
+	if (resources.length == 1) {
+		return PostfachNachrichtenCount.SINGLE;
+	}
+	if (resources.length > 1) {
+		return PostfachNachrichtenCount.MULTIPLE;
+	}
 }
\ No newline at end of file
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.html b/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.html
index 6b583bb9b1b37111177cdb8f761f1013ad2b0763..02e6bb3a8f9c3eb1a642deeb66eb27b478f18a3b 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.html
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.html
@@ -23,15 +23,17 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<h3 class="nachrichten">Nachrichten</h3>
-
-<goofy-client-postfach-mail-pdf-button-container *ngIf="vorgang | hasLink: vorgangHeaderLinkRel.POSTFACH_MAILS" data-test-id="postfach-pdf-button"></goofy-client-postfach-mail-pdf-button-container>
+<div class="nachrichten-header">
+	<h3 class="nachrichten">Nachrichten</h3>
+	<goofy-client-postfach-mail-pdf-button-container [postfachMailListResource]="postfachMailListStateResource.resource"></goofy-client-postfach-mail-pdf-button-container>
+</div>
 
 <goofy-client-spinner [stateResource]="postfachMailListStateResource">
+
 	<goofy-client-postfach-mail *ngFor="let postfachMail of postfachMailListStateResource.resource | toEmbeddedResources: postfachMailListLinkRel.POSTFACH_MAIL_LIST"
-			class="postfach"
-			[postfachMail]="postfachMail"
-			[attr.data-test-id]="(postfachMail.subject | convertForDataTest) + '-item'">
+		class="postfach"
+		[postfachMail]="postfachMail"
+		[attr.data-test-id]="(postfachMail.subject | convertForDataTest) + '-item'">
 	</goofy-client-postfach-mail>
 </goofy-client-spinner>
 
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.scss b/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.scss
index f4a5135172ee972a0638dbf26b1c577b97428959..8eb33b8819a86ddd7bf52442dec40f771684dd5d 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.scss
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.scss
@@ -54,5 +54,12 @@ h3 {
 .nachrichten {
 	border-top: 1px solid rgba(0, 0, 0, 0.08);
 	margin-top: 16px;
-	padding-top: 16px;
 }
+
+.nachrichten-header {
+	padding-top: 16px;
+	display: flex;
+	width: 100%;
+	justify-content: space-between;
+	align-items: center;
+}
\ No newline at end of file
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.spec.ts b/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.spec.ts
index a5be3b50246f88dfebd061ea826ad2730106eecf..253c5c6ba15616607bf0ecfc05b033705366d317 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.spec.ts
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.spec.ts
@@ -27,10 +27,8 @@ import { PostfachMailListLinkRel } from '@goofy-client/postfach-shared';
 import { ConvertForDataTestPipe, createStateResource, HasLinkPipe, ToEmbeddedResourcesPipe } from '@goofy-client/tech-shared';
 import { getElementFromFixture } from '@goofy-client/test-utils';
 import { ExpansionPanelComponent, SpinnerComponent } from '@goofy-client/ui';
-import { VorgangHeaderLinkRel } from '@goofy-client/vorgang-shared';
 import { createPostfachMailListResource } from 'libs/postfach-shared/test/postfach';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
-import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { PostfachMailButtonContainerComponent } from '../../postfach-mail-button-container/postfach-mail-button-container.component';
 import { PostfachMailPdfButtonContainerComponent } from '../../postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component';
@@ -43,7 +41,6 @@ describe('PostfachMailListComponent', () => {
 
 	const postfachMailButton: string = getDataTestIdOf('postfach-mail-button-container');
 	const noPostfachText: string = getDataTestIdOf('no-postfach-text');
-	const postfachPdfButton: string = getDataTestIdOf('postfach-pdf-button');
 
 	beforeEach(async () => {
 		await TestBed.configureTestingModule({
@@ -112,25 +109,4 @@ describe('PostfachMailListComponent', () => {
 			expect(button).toBeInstanceOf(HTMLElement);
 		})
 	})
-
-	describe('postfach pdf button', () => {
-
-		it('should show if link exist', () => {
-			component.vorgang = createVorgangWithEingangResource([VorgangHeaderLinkRel.POSTFACH_MAILS]);
-			fixture.detectChanges();
-
-			var pdfButtonElement = getElementFromFixture(fixture, postfachPdfButton);
-
-			expect(pdfButtonElement).toBeInTheDocument();
-		})
-
-		it('should hide if link is missing', () => {
-			component.vorgang = createVorgangWithEingangResource();
-			fixture.detectChanges();
-
-			var pdfButtonElement = getElementFromFixture(fixture, postfachPdfButton);
-
-			expect(pdfButtonElement).not.toBeInTheDocument();
-		})
-	})
 });
\ No newline at end of file
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.html b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.html
index 9f6104e7d435cb1e36a5adf17b376101a05eeb31..d162b0bacb564258fc21dfd3de39a00aae90377c 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.html
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.html
@@ -23,10 +23,9 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<goofy-client-button-with-spinner data-test-id="send-mail-button"
-	[showSpinner]="isDownloadPdfInProgress | async"
-	text="download Pdf"
-	icon="add"
-	toolTip="Nachrichten als Pdf downloaden"
-	(clickEmitter)="downloadPdf()">
-</goofy-client-button-with-spinner>
\ No newline at end of file
+<goofy-client-postfach-mail-pdf-button
+	[isDownloadInProgress]="isDownloadPdfInProgress$ | async"
+	[postfachMailListResource]="postfachMailListResource"
+	[showButtonWithLabel]="showButtonWithLabel"
+	(downloadPdf)="downloadPdf()">
+</goofy-client-postfach-mail-pdf-button>
\ No newline at end of file
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.spec.ts b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.spec.ts
index 1ad3551a669da90238bf11e5211fae7137b5548b..63305a7125a8155ced2e16f27cb3fa36e99d486c 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.spec.ts
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.spec.ts
@@ -28,6 +28,7 @@ import { Mock, mock } from '@goofy-client/test-utils';
 import { ButtonWithSpinnerComponent } from '@goofy-client/ui';
 import { MockComponent } from 'ng-mocks';
 import { PostfachMailPdfButtonContainerComponent } from './postfach-mail-pdf-button-container.component';
+import { PostfachMailPdfButtonComponent } from './postfach-mail-pdf-button/postfach-mail-pdf-button.component';
 
 describe('PostfachMailPdfButtonContainerComponent', () => {
 	let component: PostfachMailPdfButtonContainerComponent;
@@ -39,7 +40,8 @@ describe('PostfachMailPdfButtonContainerComponent', () => {
 		await TestBed.configureTestingModule({
 			declarations: [
 				PostfachMailPdfButtonContainerComponent,
-				MockComponent(ButtonWithSpinnerComponent)
+				MockComponent(ButtonWithSpinnerComponent),
+				MockComponent(PostfachMailPdfButtonComponent)
 			],
 			providers: [
 				{
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.ts b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.ts
index 302ecaebf53ff61d1de8291da4737d99f29b4388..7880630c403d81caa057197cf2201adddcb2e891 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.ts
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.ts
@@ -22,8 +22,8 @@
 /// unter der Lizenz sind dem Lizenztext zu entnehmen.
 ///
 
-import { Component, OnInit } from '@angular/core';
-import { PostfachService } from '@goofy-client/postfach-shared';
+import { Component, Input, OnInit } from '@angular/core';
+import { PostfachMailResource, PostfachService } from '@goofy-client/postfach-shared';
 import { Observable } from 'rxjs';
 
 @Component({
@@ -33,12 +33,15 @@ import { Observable } from 'rxjs';
 })
 export class PostfachMailPdfButtonContainerComponent implements OnInit {
 
-	isDownloadPdfInProgress: Observable<boolean>;
+	@Input() postfachMailListResource: PostfachMailResource;
+	@Input() showButtonWithLabel: boolean = false
+
+	isDownloadPdfInProgress$: Observable<boolean>;
 
 	constructor(private postfachService: PostfachService) { }
 
 	ngOnInit(): void {
-		this.isDownloadPdfInProgress = this.postfachService.isDownloadPdfInProgress();
+		this.isDownloadPdfInProgress$ = this.postfachService.isDownloadPdfInProgress();
 	}
 
 	downloadPdf(): void {
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.html b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..afbdc29b6f0a120553cd44fb3dff73ec3f7fdd8c
--- /dev/null
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.html
@@ -0,0 +1,45 @@
+<!--
+
+    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.
+
+-->
+<ng-container *ngIf="postfachMailCount != postfachNachrichtenCount.NONE">
+
+	<ng-container *ngIf="showButtonWithLabel; else showButton">
+		<goofy-client-button-with-spinner data-test-id="postfach-pdf-export-button"
+			[showSpinner]="isDownloadInProgress"
+			svgIcon="pdf_export"
+			[text]="label" [toolTip]="label"
+			(clickEmitter)="downloadPdf.emit()">
+		</goofy-client-button-with-spinner>
+	</ng-container>
+	<ng-template #showButton>
+		<goofy-client-button-with-spinner data-test-id="postfach-pdf-export-label-button"
+			[showSpinner]="isDownloadInProgress"
+			svgIcon="pdf_export"
+			[toolTip]="label"
+			(clickEmitter)="downloadPdf.emit()">
+		</goofy-client-button-with-spinner>
+	</ng-template>
+
+</ng-container>
\ No newline at end of file
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.scss b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..9a08a5aabce6cc4cdbb268c4190a8d67f82f19e5
--- /dev/null
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.scss
@@ -0,0 +1,23 @@
+/**
+ * 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/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.spec.ts b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b7269460f15ccdda6d3168513c7d2d01f8fa2056
--- /dev/null
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.spec.ts
@@ -0,0 +1,169 @@
+///
+/// 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 { PostfachMailListResource, PostfachNachrichtenCount } from '@goofy-client/postfach-shared';
+import { getElementFromFixture } from '@goofy-client/test-utils';
+import { ButtonWithSpinnerComponent } from '@goofy-client/ui';
+import { createPostfachMailListResource } from 'libs/postfach-shared/test/postfach';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { MockComponent } from 'ng-mocks';
+import { PostfachMailPdfButtonComponent } from './postfach-mail-pdf-button.component';
+
+describe('PostfachMailPdfButtonComponent', () => {
+	let component: PostfachMailPdfButtonComponent;
+	let fixture: ComponentFixture<PostfachMailPdfButtonComponent>;
+
+	const pdfExportButton: string = getDataTestIdOf('postfach-pdf-export-button');
+	const pdfExportLabelButton: string = getDataTestIdOf('postfach-pdf-export-label-button');
+
+	beforeEach(async () => {
+		await TestBed.configureTestingModule({
+			declarations: [
+				PostfachMailPdfButtonComponent,
+				MockComponent(ButtonWithSpinnerComponent)
+			],
+		}).compileComponents();
+
+		fixture = TestBed.createComponent(PostfachMailPdfButtonComponent);
+		component = fixture.componentInstance;
+		fixture.detectChanges();
+	});
+
+	it('should create', () => {
+		expect(component).toBeTruthy();
+	});
+
+	describe('set postfachMailListResource', () => {
+
+		const postfachMailListResource: PostfachMailListResource = createPostfachMailListResource();
+
+		it('should set label', () => {
+			component.setLabel = jest.fn()
+
+			component.postfachMailListResource = postfachMailListResource;
+
+			expect(component.setLabel).toHaveBeenCalled();
+		})
+
+		it('should set postfachMailCount', () => {
+			component.setPostfachMailCount = jest.fn()
+
+			component.postfachMailListResource = postfachMailListResource
+
+			expect(component.setPostfachMailCount).toHaveBeenCalledWith(postfachMailListResource);
+		})
+	})
+
+	describe('setLabel', () => {
+
+		it('should not set if no mails exists', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.NONE;
+
+			component.setLabel();
+
+			expect(component.label).toBeUndefined();
+		})
+
+		it('should set for single mail exists', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.SINGLE;
+
+			component.setLabel();
+
+			expect(component.label).toBe('Nachricht exportieren');
+		})
+
+		it('should set for multiple mails exists', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.MULTIPLE;
+
+			component.setLabel();
+
+			expect(component.label).toBe('Nachrichten exportieren');
+		})
+	})
+
+	describe('export button with label', () => {
+
+		it('should show on existing emails and showButtoWithLabel true', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.SINGLE;
+			component.showButtonWithLabel = true;
+			fixture.detectChanges();
+
+			const element = getElementFromFixture(fixture, pdfExportButton);
+
+			expect(element).toBeInTheDocument();
+		})
+
+		it('should hide on non existing emails', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.NONE;
+			fixture.detectChanges();
+
+			const element = getElementFromFixture(fixture, pdfExportButton);
+
+			expect(element).not.toBeInTheDocument();
+		})
+
+		it('should hide showButtonWithLabel false', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.SINGLE;
+			component.showButtonWithLabel = false;
+			fixture.detectChanges();
+
+			const element = getElementFromFixture(fixture, pdfExportButton);
+
+			expect(element).not.toBeInTheDocument();
+		})
+	})
+
+	describe('export button', () => {
+
+		it('should show on existing emails and showButtoWithLabel false', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.SINGLE;
+			component.showButtonWithLabel = false;
+			fixture.detectChanges();
+
+			const element = getElementFromFixture(fixture, pdfExportLabelButton);
+
+			expect(element).toBeInTheDocument();
+		})
+
+		it('should hide on non existing emails', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.NONE;
+			fixture.detectChanges();
+
+			const element = getElementFromFixture(fixture, pdfExportLabelButton);
+
+			expect(element).not.toBeInTheDocument();
+		})
+
+		it('should hide showButtonWithLabel true', () => {
+			component.postfachMailCount = PostfachNachrichtenCount.SINGLE;
+			component.showButtonWithLabel = true;
+			fixture.detectChanges();
+
+			const element = getElementFromFixture(fixture, pdfExportLabelButton);
+
+			expect(element).not.toBeInTheDocument();
+		})
+	})
+});
\ No newline at end of file
diff --git a/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.ts b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a59e17d30073bd52f0e969ed75fcc722734d4ea7
--- /dev/null
+++ b/goofy-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.ts
@@ -0,0 +1,58 @@
+///
+/// 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, EventEmitter, Input, Output } from '@angular/core';
+import { getPostfachNachrichtenCount, PostfachMailListResource, PostfachNachrichtenCount } from '@goofy-client/postfach-shared';
+
+@Component({
+	selector: 'goofy-client-postfach-mail-pdf-button',
+	templateUrl: './postfach-mail-pdf-button.component.html',
+	styleUrls: ['./postfach-mail-pdf-button.component.scss'],
+})
+export class PostfachMailPdfButtonComponent {
+
+	@Input() isDownloadInProgress: boolean;
+	@Input() set postfachMailListResource(postfachMailListResource: PostfachMailListResource) {
+		this.setPostfachMailCount(postfachMailListResource);
+		this.setLabel();
+	}
+	@Input() showButtonWithLabel: boolean;
+
+	@Output() downloadPdf: EventEmitter<void> = new EventEmitter<void>();
+
+	postfachMailCount: PostfachNachrichtenCount;
+	label: string = undefined;
+
+	readonly postfachNachrichtenCount = PostfachNachrichtenCount;
+
+	setPostfachMailCount(postfachMailListResource: PostfachMailListResource): void {
+		this.postfachMailCount = getPostfachNachrichtenCount(postfachMailListResource)
+	}
+
+	setLabel(): void {
+		if (this.postfachMailCount != PostfachNachrichtenCount.NONE) {
+			this.label = this.postfachMailCount == PostfachNachrichtenCount.SINGLE ? 'Nachricht exportieren' : 'Nachrichten exportieren';
+		}
+	}
+}
\ No newline at end of file
diff --git a/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.html b/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.html
index ee84af9c74af1c9625ebfeb34e46e7b33b2066f5..1564aedfc5bd616395ab1dac38cbf8ad9fb83aec 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.html
+++ b/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.html
@@ -30,4 +30,9 @@
 		[postfachMail]="postfachMail">
 	</goofy-client-postfach-mail>
 
+	<goofy-client-postfach-mail-pdf-button-container
+		[showButtonWithLabel]="true"
+		[postfachMailListResource]="postfachMailListStateResource.resource">
+	</goofy-client-postfach-mail-pdf-button-container>
+
 </goofy-client-spinner>
diff --git a/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.spec.ts b/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.spec.ts
index af9035579e03bff6a9cb9255d4239fc2e77309bf..61ecc8de89922dd024205237125999cd836aa65a 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.spec.ts
+++ b/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.spec.ts
@@ -27,6 +27,7 @@ import { ConvertForDataTestPipe, HasLinkPipe, ToEmbeddedResourcesPipe } from '@g
 import { SpinnerComponent } from '@goofy-client/ui';
 import { MockComponent } from 'ng-mocks';
 import { PostfachMailComponent } from '../../../postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component';
+import { PostfachMailPdfButtonContainerComponent } from '../../../postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component';
 import { PostfachPageMailListComponent } from './postfach-page-mail-list.component';
 
 describe('PostfachPageMailListComponent', () => {
@@ -37,11 +38,12 @@ describe('PostfachPageMailListComponent', () => {
 		await TestBed.configureTestingModule({
 			declarations: [
 				PostfachPageMailListComponent,
-				MockComponent(PostfachMailComponent),
-				MockComponent(SpinnerComponent),
 				ToEmbeddedResourcesPipe,
 				ConvertForDataTestPipe,
 				HasLinkPipe,
+				MockComponent(PostfachMailComponent),
+				MockComponent(SpinnerComponent),
+				MockComponent(PostfachMailPdfButtonContainerComponent)
 			]
 		})
 			.compileComponents();
diff --git a/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.html b/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.html
index 34fd64ff026f71f6170f4d56d68343260866b03f..3af36ee607a92a3471a3ae9d8093589a881a84d2 100644
--- a/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.html
+++ b/goofy-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.html
@@ -24,6 +24,7 @@
 
 -->
 <goofy-client-subnavigation class="mat-app-background">
+	<!-- TODO in eigene component auslagern -->
 	<a routerLink="../" mat-icon-button data-test-id="back-button" class="back-button" aria-label="zurück zur Detailseite" matTooltip="zurück zur Detailseite">
 		<mat-icon>arrow_back</mat-icon>
 	</a>
diff --git a/goofy-client/libs/postfach/src/lib/postfach.module.ts b/goofy-client/libs/postfach/src/lib/postfach.module.ts
index 58bbde0ecdbe9d48a7bdce484adbbeee30b12f65..fc0cf3838af8d8dde536eb17fd3c72c853f394a6 100644
--- a/goofy-client/libs/postfach/src/lib/postfach.module.ts
+++ b/goofy-client/libs/postfach/src/lib/postfach.module.ts
@@ -44,6 +44,7 @@ import { PostfachMailDateComponent } from './postfach-mail-list-container/postfa
 import { PostfachMailComponent } from './postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component';
 import { PostfachNachrichtAttachmentsComponent } from './postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-nachricht-attachments/postfach-nachricht-attachments.component';
 import { PostfachMailPdfButtonContainerComponent } from './postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component';
+import { PostfachMailPdfButtonComponent } from './postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component';
 import { PostfachPageContainerComponent } from './postfach-page-container/postfach-page-container.component';
 import { PostfachPageMailListComponent } from './postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component';
 import { PostfachPageComponent } from './postfach-page-container/postfach-page/postfach-page.component';
@@ -52,8 +53,8 @@ const routes: Routes = [
 	{
 		path: 'postfach',
 		component: PostfachPageContainerComponent,
-		title: 'Nachrichten zum Vorgang | Alfa'
-	}
+		title: 'Nachrichten zum Vorgang | Alfa',
+	},
 ];
 
 @NgModule({
@@ -65,7 +66,7 @@ const routes: Routes = [
 		UserProfileModule,
 		VorgangSharedModule,
 		VorgangSharedUiModule,
-		BinaryFileModule
+		BinaryFileModule,
 	],
 	declarations: [
 		PostfachMailListContainerComponent,
@@ -83,18 +84,19 @@ const routes: Routes = [
 		OutgoingMailErrorContainerComponent,
 		PostfachNachrichtAttachmentsComponent,
 		PostfachMailButtonComponent,
-		PostfachMailPdfButtonContainerComponent
+		PostfachMailPdfButtonContainerComponent,
+		PostfachMailPdfButtonComponent,
 	],
 	exports: [
 		PostfachMailListContainerComponent,
 		PostfachMailButtonContainerComponent,
-		PostfachMailFormComponent
+		PostfachMailFormComponent,
 	],
 	providers: [
 		{
 			provide: ON_PAGE,
-			useValue: undefined
-		}
-	]
+			useValue: undefined,
+		},
+	],
 })
 export class PostfachModule { }
diff --git a/goofy-client/libs/ui/src/lib/assets/pdf_export.svg b/goofy-client/libs/ui/src/lib/assets/pdf_export.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e075a026567312695e4b8fdfe1eeeb0d75485225
--- /dev/null
+++ b/goofy-client/libs/ui/src/lib/assets/pdf_export.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7.26611 8.71924H5.63574V7.69092H7.26611C7.51807 7.69092 7.72314 7.6499 7.88135 7.56787C8.03955 7.48291 8.15527 7.36572 8.22852 7.21631C8.30176 7.06689 8.33838 6.89844 8.33838 6.71094C8.33838 6.52051 8.30176 6.34326 8.22852 6.1792C8.15527 6.01514 8.03955 5.8833 7.88135 5.78369C7.72314 5.68408 7.51807 5.63428 7.26611 5.63428H6.09277V11H4.77441V4.60156H7.26611C7.76709 4.60156 8.19629 4.69238 8.55371 4.87402C8.91406 5.05273 9.18945 5.30029 9.37988 5.6167C9.57031 5.93311 9.66553 6.29492 9.66553 6.70215C9.66553 7.11523 9.57031 7.47266 9.37988 7.77441C9.18945 8.07617 8.91406 8.30908 8.55371 8.47314C8.19629 8.63721 7.76709 8.71924 7.26611 8.71924ZM12.5396 11H11.1465L11.1553 9.97168H12.5396C12.8853 9.97168 13.1768 9.89404 13.4141 9.73877C13.6514 9.58057 13.8301 9.35059 13.9502 9.04883C14.0732 8.74707 14.1348 8.38232 14.1348 7.95459V7.64258C14.1348 7.31445 14.0996 7.02588 14.0293 6.77686C13.9619 6.52783 13.8608 6.31836 13.7261 6.14844C13.5913 5.97852 13.4258 5.85107 13.2295 5.76611C13.0332 5.67822 12.8076 5.63428 12.5527 5.63428H11.1201V4.60156H12.5527C12.9805 4.60156 13.3716 4.6748 13.7261 4.82129C14.0835 4.96484 14.3926 5.17139 14.6533 5.44092C14.9141 5.71045 15.1147 6.03271 15.2554 6.40771C15.3989 6.77979 15.4707 7.19434 15.4707 7.65137V7.95459C15.4707 8.40869 15.3989 8.82324 15.2554 9.19824C15.1147 9.57324 14.9141 9.89551 14.6533 10.165C14.3955 10.4316 14.0864 10.6382 13.7261 10.7847C13.3687 10.9282 12.9731 11 12.5396 11ZM11.8936 4.60156V11H10.5752V4.60156H11.8936ZM17.7471 4.60156V11H16.4287V4.60156H17.7471ZM20.2959 7.33496V8.36328H17.3867V7.33496H20.2959ZM20.6035 4.60156V5.63428H17.3867V4.60156H20.6035Z" fill="#1976D2"/>
+<path d="M13 19.099L15.59 16.4712L17 17.9073L12 23L7 17.9073L8.41 16.4712L11 19.099V13H13V19.099Z" fill="#1976D2"/>
+</svg>
diff --git a/goofy-client/libs/ui/src/lib/icon/icon.model.ts b/goofy-client/libs/ui/src/lib/icon/icon.model.ts
index 760724e99d00be6335c62791317817a95ff7525f..d4b01cf45cfa0917e9416b432abfa211567d8227 100644
--- a/goofy-client/libs/ui/src/lib/icon/icon.model.ts
+++ b/goofy-client/libs/ui/src/lib/icon/icon.model.ts
@@ -24,13 +24,14 @@
 
 export enum Icons {
 	INCOMING = 'incoming',
-	edit = 'edit',
-	stamp = 'stamp',
-	account_outline = 'account_outline',
-	no_reply = 'no_reply',
-	assignment_ind = 'assignment_ind',
-	az = 'az',
-	nr = 'nr',
-	mail = 'mail',
-	logo = 'logo'
+	EDIT = 'edit',
+	STAMP = 'stamp',
+	ACCOUNT_OUTLINE = 'account_outline',
+	NO_REPLY = 'no_reply',
+	ASSIGNMENT_IND = 'assignment_ind',
+	AZ = 'az',
+	NR = 'nr',
+	MAIL = 'mail',
+	LOGO = 'logo',
+	PDF_EXPORT = 'pdf_export'
 }
diff --git a/goofy-client/libs/ui/src/lib/ui/button-with-spinner/button-with-spinner.component.html b/goofy-client/libs/ui/src/lib/ui/button-with-spinner/button-with-spinner.component.html
index 502273c9988c27042f2edce7f2b8f8793d2e756a..c20937a7108fbda72f6a469c72efc74fe34b8330 100644
--- a/goofy-client/libs/ui/src/lib/ui/button-with-spinner/button-with-spinner.component.html
+++ b/goofy-client/libs/ui/src/lib/ui/button-with-spinner/button-with-spinner.component.html
@@ -23,36 +23,25 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<button mat-stroked-button
-		[color]="color"
-		[type]="type"
-		[disabled]="isDisabled"
-		[matTooltip]="toolTip"
-		(click)="clickEmitter.emit($event)"
-		[attr.data-test-id]="dataTestId"
-		data-test-class="icon-button">
-
-	<mat-icon
-			*ngIf="icon"
-			[style.visibility]="isDisabled ? 'hidden' : 'visible'"
-			data-test-class="icon">
+<button mat-stroked-button data-test-class="icon-button" [attr.data-test-id]="dataTestId"
+		[color]="color" [type]="type" [disabled]="isDisabled" [matTooltip]="toolTip"
+		(click)="clickEmitter.emit($event)">
+
+	<mat-icon *ngIf="icon" data-test-class="icon"
+			[style.visibility]="isDisabled ? 'hidden' : 'visible'">
 		{{ icon }}
 	</mat-icon>
 
-	<mat-icon
-			*ngIf="svgIcon"
+	<mat-icon *ngIf="svgIcon" data-test-class="icon"
 			[svgIcon]="svgIcon"
-			[style.visibility]="isDisabled ? 'hidden' : 'visible'"
-			data-test-class="icon">
+			[style.visibility]="isDisabled ? 'hidden' : 'visible'">
 	</mat-icon>
 
-	<span>{{ text }}</span>
+	<span *ngIf="text" data-test-class="button-with-spinner-text">{{ text }}</span>
 
 	<goofy-client-spinner
-			[diameter]="22"
-			padding="0"
-			[stateResource]="getStateResource()"
-			[show]="showSpinner">
+			[diameter]="22" padding="0"
+			[stateResource]="getStateResource()" [show]="showSpinner">
 	</goofy-client-spinner>
 
 </button>
diff --git a/goofy-client/libs/ui/src/lib/ui/button-with-spinner/button-with-spinner.component.spec.ts b/goofy-client/libs/ui/src/lib/ui/button-with-spinner/button-with-spinner.component.spec.ts
index 2ccc27e1a59e4988b26177ed82683cef9d6185e3..603fd9feb883b9a4e9364f65832d20eca85f0e3a 100644
--- a/goofy-client/libs/ui/src/lib/ui/button-with-spinner/button-with-spinner.component.spec.ts
+++ b/goofy-client/libs/ui/src/lib/ui/button-with-spinner/button-with-spinner.component.spec.ts
@@ -28,6 +28,7 @@ import { MatRipple } from '@angular/material/core';
 import { MatIcon } from '@angular/material/icon';
 import { MatTooltipModule } from '@angular/material/tooltip';
 import { createEmptyStateResource } from '@goofy-client/tech-shared';
+import { getDataTestClassOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { SpinnerComponent } from '../spinner/spinner.component';
 import { ButtonWithSpinnerComponent } from './button-with-spinner.component';
@@ -36,8 +37,9 @@ describe('ButtonWithSpinnerComponent', () => {
 	let component: ButtonWithSpinnerComponent;
 	let fixture: ComponentFixture<ButtonWithSpinnerComponent>;
 
-	const buttonSelector = '[data-test-class="icon-button"]'
-	const iconSelector = '[data-test-class="icon"]'
+	const buttonSelector: string = getDataTestClassOf('icon-button');
+	const iconSelector: string = getDataTestClassOf('icon');
+	const text: string = getDataTestClassOf('button-with-spinner-text');
 
 	beforeEach(async () => {
 		await TestBed.configureTestingModule({
@@ -57,7 +59,6 @@ describe('ButtonWithSpinnerComponent', () => {
 	beforeEach(() => {
 		fixture = TestBed.createComponent(ButtonWithSpinnerComponent);
 		component = fixture.componentInstance;
-		component.icon = 'add';
 		fixture.detectChanges();
 	});
 
@@ -66,38 +67,70 @@ describe('ButtonWithSpinnerComponent', () => {
 	});
 
 	describe('Button', () => {
+
 		it('should NOT disabled initial', () => {
-			const button = fixture.nativeElement.querySelector(buttonSelector);
 			component.stateResource = createEmptyStateResource();
 			fixture.detectChanges();
 
+			const button = fixture.nativeElement.querySelector(buttonSelector);
+
 			expect(button).not.toBeDisabled()
 		});
 
 		it('should disabled if loading', () => {
-			const button = fixture.nativeElement.querySelector(buttonSelector);
 			component.stateResource = createEmptyStateResource(true);
 			fixture.detectChanges();
 
+			const button = fixture.nativeElement.querySelector(buttonSelector);
+
 			expect(button).toBeDisabled();
 		});
 	})
 
 	describe('Icon', () => {
+
+		beforeEach(() => {
+			component.icon = 'add';
+			fixture.detectChanges();
+		})
+
 		it('should visible initial', () => {
-			const icon = fixture.nativeElement.querySelector(iconSelector);
 			component.stateResource = createEmptyStateResource();
 			fixture.detectChanges();
 
+			const icon = fixture.nativeElement.querySelector(iconSelector);
+
 			expect(icon).toBeVisible();
 		});
 
 		it('should not visible if loading', () => {
-			const icon = fixture.nativeElement.querySelector(iconSelector);
 			component.stateResource = createEmptyStateResource(true);
 			fixture.detectChanges();
 
+			const icon = fixture.nativeElement.querySelector(iconSelector);
+
 			expect(icon).not.toBeVisible();
 		});
 	})
-});
+
+	describe('Text', () => {
+
+		it('should visible if exist', () => {
+			component.text = 'Test text';
+			fixture.detectChanges();
+
+			const textElement = fixture.nativeElement.querySelector(text);
+
+			expect(textElement).toBeInTheDocument();
+		});
+
+		it('should not visible if is null', () => {
+			component.text = null;
+			fixture.detectChanges();
+
+			const textElement = fixture.nativeElement.querySelector(text);
+
+			expect(textElement).not.toBeInTheDocument();
+		});
+	})
+});
\ No newline at end of file
diff --git a/goofy-client/libs/user-profile/src/lib/user-icon/user-icon.component.html b/goofy-client/libs/user-profile/src/lib/user-icon/user-icon.component.html
index ec63189cb8ac1377ead05ce66fd6e5eed1cf5337..3495967dc6b6f6c625fb673b84e8efb6769ad507 100644
--- a/goofy-client/libs/user-profile/src/lib/user-icon/user-icon.component.html
+++ b/goofy-client/libs/user-profile/src/lib/user-icon/user-icon.component.html
@@ -26,7 +26,7 @@
 <goofy-client-spinner [stateResource]="userProfileStateResource" diameter="30" padding="3">
 	<div [matTooltipDisabled]="disableTooltip" data-test-class="user-profile-icon"
 		[class.initials]="!!userProfileStateResource.resource || userProfileStateResource.error"
-		class="user-profile" [matTooltip]="tooltip">
+		class="user-profile" [matTooltip]="tooltip" [attr.aria-label]="tooltip">
 
 	<ng-container *ngIf="userProfileStateResource.resource; else noUser">
 		<span data-test-class="user-profile-assigned">{{ initials }}</span>
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/ModelBuilder.java b/goofy-server/src/main/java/de/itvsh/goofy/common/ModelBuilder.java
index e6eecac6911538f9b12f6f01028d68e55152e129..4ba954e31ac56a14e804ef86dee5912b30182bb8 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/ModelBuilder.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/ModelBuilder.java
@@ -159,7 +159,7 @@ public class ModelBuilder<T> {
 	private List<Field> getFields(Class<? extends Annotation> annotationClass) {
 		var fields = Optional.ofNullable(ANNOTATED_FIELDS_BY_ANNOTATION.get(getEntity().getClass()))
 				.map(fieldsByAnnotation -> fieldsByAnnotation.get(annotationClass))
-				.orElseGet(() -> Collections.emptyList());
+				.orElseGet(Collections::emptyList);
 
 		if (CollectionUtils.isEmpty(fields)) {
 			fields = FieldUtils.getFieldsListWithAnnotation(getEntity().getClass(), annotationClass);
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/UserProfileUrlProvider.java b/goofy-server/src/main/java/de/itvsh/goofy/common/UserProfileUrlProvider.java
index 5e600a0c6cafcc6a1a80106a14127dd7759b9e62..c084a7c6cf3cffd11a19677e169888b675dc4c07 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/UserProfileUrlProvider.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/UserProfileUrlProvider.java
@@ -32,7 +32,10 @@ import com.google.common.base.Preconditions;
 
 @Component
 public class UserProfileUrlProvider implements ApplicationContextAware {
+	// TODO auf javax.validation umstellen
 	private static final String ERROR_MESSAGE = "Key %s missing, please add it to the application.yml";
+	// TODO applicationContext darf nicht static abgelegt werden - es sollte möglich
+	// sein, dass eine andere Konfiguration in der jvm läuft.
 	private static ApplicationContext applicationContext;
 	static final String URL_ROOT_KEY = "kop.user-manager.url";
 	static final String USER_PROFILES_TEMPLATE_KEY = "kop.user-manager.profile-template";
@@ -47,14 +50,17 @@ public class UserProfileUrlProvider implements ApplicationContextAware {
 	}
 
 	public static String getUrl(Object val) {
+		// TODO Abhängingkeit zu com.google.common ausbauen
 		Preconditions.checkNotNull(applicationContext, "ApplicationContext not initialized");
 
+		// TODO parameter lieber injezieren und validation verwenden
 		var rootUrl = applicationContext.getEnvironment().getProperty(URL_ROOT_KEY);
 		Preconditions.checkNotNull(rootUrl, ERROR_MESSAGE, URL_ROOT_KEY);
 
 		var template = applicationContext.getEnvironment().getProperty(USER_PROFILES_TEMPLATE_KEY);
 		Preconditions.checkNotNull(template, ERROR_MESSAGE, USER_PROFILES_TEMPLATE_KEY);
 
+		// TODO UriComponent Builder verwenden
 		var profilesUrl = rootUrl + template;
 		return String.format(profilesUrl, val);
 	}
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java
index f28d723d7b5ef5893f296e293772a1a000dd8ee9..2a7100860aae4eb760342af8dcd08c6b78fd7ace 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java
@@ -24,17 +24,23 @@
 package de.itvsh.goofy.wiedervorlage;
 
 import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
 
 import java.util.Collections;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.env.Environment;
 import org.springframework.hateoas.EntityModel;
 import org.springframework.hateoas.IanaLinkRelations;
 import org.springframework.hateoas.server.EntityLinks;
 
+import de.itvsh.goofy.common.UserProfileUrlProvider;
 import de.itvsh.goofy.common.file.OzgFileTestFactory;
 import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory;
 
@@ -48,6 +54,17 @@ class WiedervorlageModelAssemblerTest {
 	@Mock
 	private EntityLinks entityLinks;
 
+	private UserProfileUrlProvider urlProvider = new UserProfileUrlProvider();
+
+	@BeforeEach
+	void initTest() {
+		var context = mock(ApplicationContext.class);
+		var environment = mock(Environment.class);
+		when(environment.getProperty(anyString())).thenReturn("test/");
+		when(context.getEnvironment()).thenReturn(environment);
+		urlProvider.setApplicationContext(context);
+	}
+
 	@Nested
 	class TestLinksOnModel {
 		private static final String COMMAND_BY_WIEDERVORLAGE_PATH = WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS
diff --git a/pom.xml b/pom.xml
index 6dcf5fdde57042294fe64bbebd2f5de2802bcfcd..f51be5797b2f3f51d3e9cdedf26354ced2bc559b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,8 @@
 									<exclude>**/README</exclude>
 									<exclude>src/test/resources/**</exclude>
 									<exclude>src/main/resources/**</exclude>
+									<exclude>**/goofy-e2e/reports/videos/**</exclude>
+									<exclude>**/.angular/cache/**</exclude>
 								</excludes>
 							</licenseSet>
 						</licenseSets>
diff --git a/src/main/helm/.helmignore b/src/main/helm/.helmignore
new file mode 100644
index 0000000000000000000000000000000000000000..f48713aefc38112aeca6d64b5a57bea78aff5375
--- /dev/null
+++ b/src/main/helm/.helmignore
@@ -0,0 +1,2 @@
+unit-tests/
+tests/
\ No newline at end of file
diff --git a/src/main/helm/Chart.yaml b/src/main/helm/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..365e3e87197283fd061c56e274a7f59b47c5a51a
--- /dev/null
+++ b/src/main/helm/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v1
+appVersion: "1.1"
+description: A Helm chart for Goofy
+name: goofy
+version: 0.0.0-MANAGED-BY-JENKINS
+icon: https://simpleicons.org/icons/helm.svg
diff --git a/src/main/helm/README.md b/src/main/helm/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..06d30da3fd35dec702c4c204f85e504bbb8d3fb3
--- /dev/null
+++ b/src/main/helm/README.md
@@ -0,0 +1,24 @@
+# Helm
+## Linter
+`helm lint -f test-values.yaml`
+## Unit-Tests
+Für Unit-Tests wird das helm [helm-unittest](https://github.com/quintush/helm-unittest) plugin benötigt. Die Unit-Tests liegen im Verzeichnis src/test/helm
+
+`helm unittest -f '../../test/helm/*.yaml' .`
+## SyntaxCheck
+`helm template --debug -f test-values.yaml .`
+
+## Package
+`helm package --version=[version] .`
+
+## Versionierung
+Jenkins verwendet die Version aus der pom.xml
+
+### Master Branch
+Im master Branch werden die ersten 7 Zeichen vom git commit hash an die Version gehangen.
+
+### Release Branch
+Ist nur die Version aus der pom.xml
+
+### Feature Branch
+In einem feature Branch wird der Branchname an die Version gehangen.
\ No newline at end of file
diff --git a/src/main/helm/app-readme.md b/src/main/helm/app-readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..b357f180cf799b8de014b7870921a2d7d5f694c9
--- /dev/null
+++ b/src/main/helm/app-readme.md
@@ -0,0 +1,18 @@
+# Goofy
+
+Das helm chart zur Installation des allgemeinen Fachverfahrens - goofy.
+
+## FAQ
+
+### Benutzung beliebiger environment Werte
+
+In jedem der Projekte kann man beliebige weitere environments setzen. Dazu muss man in der jeweiligen values.yaml unter env.customList ein name value Paar setzen:
+
+```yaml
+env:
+  customList:
+    - name: Dinge
+      value: true
+    - name: ...
+      value: ...
+```
diff --git a/src/main/helm/questions.yml b/src/main/helm/questions.yml
new file mode 100644
index 0000000000000000000000000000000000000000..01532eed04b7c59b3968978876950949bb472524
--- /dev/null
+++ b/src/main/helm/questions.yml
@@ -0,0 +1,55 @@
+questions:
+  - variable: image.tag
+    default: latest
+    type: string
+    label: The deployed version tag
+    group: "Container"
+  - variable: replicaCount
+    group: "Container"
+    type: string
+    default: "2"
+    label: "Deployment Replica count"
+  - variable: env.overrideSpringProfiles
+    type: string
+    label: "Override Spring boot profile"
+    group: "Container"
+  - variable: kop.bundesland
+    group: "KOP"
+    label: Bundesland
+    type: string
+    required: true
+  - variable: kop.bezeichner
+    group: "KOP"
+    label: "Bezeichner"
+    type: string
+    required: true
+  - variable: kop.environment
+    group: "KOP"
+    label: "Environment"
+    type: string
+    required: true
+  - variable: plutoName
+    group: "Other"
+    type: string
+    default: "pluto"
+    label: "Name of the pluto deployment in the namespace"
+  - variable: sso.role_einheitlicher_ansprechpartner
+    group: "Other"
+    type: boolean
+    default: false
+    label: "Add role for EA"
+  - variable: sso.displayName
+    group: "Other"
+    type: string
+    default: ""
+    label: "The custom display name to write on top of the login page. Defaults to 'Realm für <app.name>', Works on initial Install only."
+  - variable: sso.apiPassword
+    group: "Other"
+    type: string
+    default: " "
+    label: "SSO API User Password"
+  - variable: useKeycloakNamespace
+    group: "Other"
+    type: boolean
+    default: false
+    label: "Use keycloak namespace for keycloak templates"
\ No newline at end of file
diff --git a/src/main/helm/templates/NOTES.txt b/src/main/helm/templates/NOTES.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/main/helm/templates/_helpers.tpl b/src/main/helm/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..8000fc888b34569c25046bd8c653401a913cd144
--- /dev/null
+++ b/src/main/helm/templates/_helpers.tpl
@@ -0,0 +1,153 @@
+{{/* vim: set filetype=mustache: */}}
+
+{{/* Truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec) */}}
+{{/* Name */}}
+{{- define "app.name" -}}
+{{- default .Release.Name | toString | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/* Namespace */}}
+{{- define "app.namespace" -}}
+{{- default .Release.Namespace | toString | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/* Version */}}
+{{- define "app.version" -}}
+{{- default .Chart.Version | toString | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/* Chart: Name + Version */}}
+{{- define "app.chart" -}}
+{{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end -}}
+
+{{/* Managed-by -> On Helm, this value is always Helm */}}
+{{- define "app.managedBy" -}}
+{{- default .Release.Service | toString | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/* Default Labels: Helm recommended best-practice labels https://helm.sh/docs/chart_best_practices/labels/ */}}
+{{- define "app.defaultLabels" }}
+app.kubernetes.io/instance: goofy
+app.kubernetes.io/managed-by: {{ include "app.managedBy" . }}
+app.kubernetes.io/name: {{ include "app.name" . }}
+app.kubernetes.io/part-of: kop
+app.kubernetes.io/version: {{ include "app.version" . }}
+app.kubernetes.io/namespace: {{ include "app.namespace" . }}
+helm.sh/chart: {{ include "app.chart" . }}
+{{- end -}}
+
+{{- define "app.matchLabels" }}
+app.kubernetes.io/name: {{ include "app.name" . }}
+app.kubernetes.io/namespace: {{ include "app.namespace" . }}
+{{- end -}}
+
+{{- define "app.envSpringProfiles" }}
+{{- if (.Values.env).overrideSpringProfiles -}}
+{{ printf "%s" (.Values.env).overrideSpringProfiles }}
+{{- else -}}
+{{ printf "oc, %s" (include "app.kopEnvironment" . ) }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.grpc_client_pluto_address" -}}
+{{ printf "%s.%s:9090" ( coalesce .Values.plutoName "pluto" ) .Release.Namespace | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end -}}
+
+{{- define "app.kop_user-manager_url" -}}
+{{- if eq (include "app.kopEnvironment" . ) "prod" -}}
+{{ printf "https://%s-%s.ozg-sh.de" (include "app.kopBezeichner" .) .Values.usermanagerName }}
+{{- else -}}
+{{ printf "https://%s-%s.%s.ozg-sh.de" (include "app.kopBezeichner" .) .Values.usermanagerName (include "app.kopEnvironment" . ) }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.kop_user-manager_internalurl" -}}
+{{ printf "http://%s.%s:8080" .Values.usermanagerName (include "app.namespace" . )}}
+{{- end -}}
+
+{{- define "app.imagePullSecret" }}
+{{- with .Values.imageCredentials }}
+{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }}
+{{- end }}
+{{- end }}
+
+{{/* --- region keycoak --- */}} 
+{{/* namespace sh-kiel-dev means <bundesland>-<name>-<level> */}}
+{{/* depending on level the server url is sso.dev.ozg-sh.de or sso.ozg-sh.de  */}}
+{{/* values can be overwritten */}}
+
+{{- define "app.kopBundesland" -}}
+{{- required "Bundesland muss angegeben sein" (.Values.kop).bundesland }}
+{{- end -}}
+
+{{- define "app.kopBezeichner" -}}
+{{ $length := len (.Values.kop).bezeichner }}
+{{- if ge 27 $length -}}
+{{- required "Bezeichner muss angegeben sein" (.Values.kop).bezeichner -}}
+{{- else -}}
+{{ required (printf "Bezichner %s ist zu lang (max. 27 Zeichen)" (.Values.kop).bezeichner) nil }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.kopEnvironment" -}}
+{{- required "Environment muss angegeben sein" (.Values.kop).environment -}}
+{{- end -}}
+
+{{- define "app.ssoRealm" -}}
+{{ printf "%s-%s-%s" (include "app.kopBundesland" .) ( include "app.kopBezeichner" . ) ( include "app.kopEnvironment" . ) | trunc 63 | trimSuffix "-" }}
+{{- end -}}
+
+{{- define "app.ssoRealmDisplayName" -}}
+{{- if (.Values.sso).displayName -}}
+{{ printf "%s" (.Values.sso).displayName }}
+{{- else if eq (include "app.kopEnvironment" . ) "prod" -}}
+{{ printf "Realm für %s" (include "app.kopBezeichner" . | title ) }}
+{{- else -}}
+{{ printf "Realm für %s (%s)" (include "app.kopBezeichner" . | title ) (include "app.kopEnvironment" .) }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.ssoServerUrl" -}}
+{{- if (.Values.sso).serverUrl -}}
+{{- printf "%s" .Values.sso.serverUrl -}}
+{{- else if eq (include "app.kopEnvironment" . ) "dev" -}} 
+{{ printf "https://sso.dev.ozg-sh.de" }}
+{{- else if eq (include "app.kopEnvironment" . ) "test" -}}
+{{ printf "https://sso.test.ozg-sh.de" }}
+{{- else -}}
+{{ printf "https://sso.ozg-sh.de" }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.baseUrl" -}}
+{{- if .Values.host -}}
+{{- printf "%s" .Values.host -}}
+{{- else if eq (include "app.kopEnvironment" . ) "prod" -}}
+{{ printf "https://%s.ozg-sh.de" (include "app.kopBezeichner" .) }}
+{{- else -}}
+{{ printf "https://%s.%s.ozg-sh.de" (include "app.kopBezeichner" .) (include "app.kopEnvironment" . ) }}
+{{- end -}}
+{{- end -}}
+
+{{- define "app.keycloakClientId" -}}
+{{ printf "%s-%s-%s-%s" (include "app.kopBundesland" .) ( include "app.kopBezeichner" . ) ( include "app.kopEnvironment" . ) ( include "app.name" . ) | trunc 63 | trimSuffix "-" }}
+{{- end -}}
+
+{{- define "app.resources" }}
+{{- if eq (include "app.kopEnvironment" . ) "prod" }}
+  limits:
+    cpu: "500m"
+    memory: "1000Mi"
+  requests:
+    cpu: "50m"
+    memory: "250Mi"
+{{- else }}
+  limits:
+    cpu: "500m"
+    memory: "1000Mi"
+  requests:
+    cpu: "50m"
+    memory: "250Mi"
+{{- end }}
+{{- end -}}
diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5ad917e35132470396ecd9a89f813f1f1af1bcd1
--- /dev/null
+++ b/src/main/helm/templates/deployment.yaml
@@ -0,0 +1,110 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "app.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: goofy
+    spec:
+      topologySpreadConstraints:
+      - maxSkew: 1
+        topologyKey: kubernetes.io/hostname
+        whenUnsatisfiable: ScheduleAnyway
+        labelSelector:
+          matchLabels:
+            app.kubernetes.io/name: {{ include "app.name" . }}
+      affinity:
+        nodeAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            nodeSelectorTerms:
+            - matchExpressions:
+              - key: goofyable
+                operator: NotIn
+                values:
+                - "false"
+      containers:
+      - env:
+        - name: grpc_client_pluto_address
+          value: {{ include "app.grpc_client_pluto_address" . }}
+        - name: spring_profiles_active
+          value: {{ include "app.envSpringProfiles" . }}
+        - name: keycloak_realm
+          value: {{ include "app.ssoRealm" . }}
+        - name: keycloak_resource
+          value: {{ include "app.keycloakClientId" . }}
+        - name: keycloak_auth-server-url
+          value: {{ include "app.ssoServerUrl" . }}
+        - name: goofy_keycloak_api_password
+          value: {{ required "A sso apiPassword is required!" (.Values.sso).apiPassword }}
+        - name: kop_user-manager_url
+          value: {{ include "app.kop_user-manager_url" . }}
+        - name: kop_user-manager_internalurl
+          value: {{ include "app.kop_user-manager_internalurl" . }}
+        {{- with (.Values.env).customList }}
+{{ toYaml . | indent 8 }}
+        {{- end }}
+        image: "{{ .Values.image.repo }}/{{ .Values.image.name }}:{{ coalesce (.Values.image).tag "latest" }}"
+        imagePullPolicy: Always
+        name: goofy
+        ports:
+        - containerPort: 8080
+          name: 8080tcp1
+          protocol: TCP
+        - containerPort: 8081
+          name: metrics
+          protocol: TCP
+        readinessProbe:
+          failureThreshold: 3
+          httpGet:
+            path: /actuator/health/readiness
+            port: 8081
+            scheme: HTTP
+          periodSeconds: 10
+          successThreshold: 1
+          timeoutSeconds: 3
+        startupProbe:
+          failureThreshold: 10
+          httpGet:
+            path: /actuator/health/readiness
+            port: 8081
+            scheme: HTTP
+          initialDelaySeconds: 30
+          periodSeconds: 5
+          successThreshold: 1
+          timeoutSeconds: 5
+        resources:
+          {{- include "app.resources" . | indent 8 }}
+        securityContext:
+          allowPrivilegeEscalation: false
+          privileged: false
+          readOnlyRootFilesystem: false
+          runAsNonRoot: false
+        stdin: true
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+        tty: true
+      dnsConfig: {}
+      dnsPolicy: ClusterFirst
+      imagePullSecrets:
+      - name: goofy-image-pull-secret
+      restartPolicy: Always
+      schedulerName: default-scheduler
+      securityContext: {}
+      terminationGracePeriodSeconds: 30
diff --git a/src/main/helm/templates/image-pull-secret.yaml b/src/main/helm/templates/image-pull-secret.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d302111913d0d9dead7188ec83ebfb158dc6c8c3
--- /dev/null
+++ b/src/main/helm/templates/image-pull-secret.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: goofy-image-pull-secret
+  namespace: {{ include "app.namespace" . }}
+type: kubernetes.io/dockerconfigjson
+data:
+  .dockerconfigjson: {{ include "app.imagePullSecret" . }}
\ No newline at end of file
diff --git a/src/main/helm/templates/ingress.yaml b/src/main/helm/templates/ingress.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9512154b91be62b4fdb87c0c7e4e3ebe025520b3
--- /dev/null
+++ b/src/main/helm/templates/ingress.yaml
@@ -0,0 +1,23 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  {{- with .Values.ingressAnnotations }}
+  annotations: {{- toYaml . | nindent 4 }}
+  {{- end }}
+  name: {{ include "app.name" . }}
+  namespace: {{ include "app.namespace" . }}
+spec:
+  rules:
+    - http:
+        paths:
+          - backend:
+              service:
+                port:
+                  number: 8080
+                name: {{ include "app.name" . }}
+            path: ''
+            pathType: ImplementationSpecific
+      host: {{ trimPrefix "https://" ( include "app.baseUrl" . ) }}
+  tls:
+    - hosts:
+      - {{ trimPrefix "https://" ( include "app.baseUrl" . ) }}
\ No newline at end of file
diff --git a/src/main/helm/templates/service.yaml b/src/main/helm/templates/service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..08f730e44f5646bdcd8e7fa16a0f0a8a5aa5045e
--- /dev/null
+++ b/src/main/helm/templates/service.yaml
@@ -0,0 +1,21 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "app.name" . }}
+  namespace: {{ include "app.namespace" . }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+    component: goofy-service
+spec:
+  type: ClusterIP
+  ports:
+    - name: http
+      port: 8080
+      protocol: TCP
+      targetPort: 8080
+    - name: metrics
+      port: 8081
+      protocol: TCP
+  selector:
+    {{- include "app.matchLabels" . | indent 4 }}
+    component: goofy
\ No newline at end of file
diff --git a/src/main/helm/templates/service_monitor.yaml b/src/main/helm/templates/service_monitor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..23a84b8e0302eb664766e703c2a6e3f9903e9794
--- /dev/null
+++ b/src/main/helm/templates/service_monitor.yaml
@@ -0,0 +1,19 @@
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+metadata:
+  name: {{ include "app.name" . }}
+  namespace: {{ include "app.namespace" . }}
+  labels:
+    {{- include "app.defaultLabels" . | indent 4 }}
+    component: goofy-service-monitor
+spec:
+  endpoints:
+  - port: metrics
+    path: /actuator/prometheus
+  namespaceSelector:
+    matchNames:
+    - {{ include "app.namespace" . }}
+  selector:
+    matchLabels:
+      {{- include "app.matchLabels" . | indent 6 }}
+      component: goofy-service
\ No newline at end of file
diff --git a/src/main/helm/templates/tests/test-ingress-connection.yaml b/src/main/helm/templates/tests/test-ingress-connection.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..acde6bdd62afb06c1de9f78e41cd8cd3a0be7031
--- /dev/null
+++ b/src/main/helm/templates/tests/test-ingress-connection.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: "{{ include "app.name" . }}-test-ingress"
+  labels:
+    {{- include "app.matchLabels" . | nindent 4 }}
+  annotations:
+    "helm.sh/hook": test
+spec:
+  containers:
+    - name: wget
+      image: busybox
+      command: ['wget']
+      args: 
+        - {{ include "app.baseUrl" . }}
+  restartPolicy: Never
diff --git a/src/main/helm/templates/tests/test-service-connection.yaml b/src/main/helm/templates/tests/test-service-connection.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a2024a8bc89891f9efb94629d8bfcdc94ad7528d
--- /dev/null
+++ b/src/main/helm/templates/tests/test-service-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: "{{ include "app.name" . }}-test-connection"
+  labels:
+    {{- include "app.matchLabels" . | nindent 4 }}
+  annotations:
+    "helm.sh/hook": test
+spec:
+  containers:
+    - name: wget
+      image: busybox
+      command: ['wget']
+      args: ['{{ include "app.name" . }}:8080']
+  restartPolicy: Never
diff --git a/src/main/helm/test-values.yaml b/src/main/helm/test-values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a87a415fc8ed01c0b27cc7b9715a8dea592b59c0
--- /dev/null
+++ b/src/main/helm/test-values.yaml
@@ -0,0 +1,7 @@
+kop:
+  bundesland: sh
+  bezeichner: helm
+  environment: test
+
+sso:
+  apiPassword: test1234
diff --git a/src/main/helm/values.yaml b/src/main/helm/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..510d062f849cf2a0fb3ede101153e4e7eeda06d6
--- /dev/null
+++ b/src/main/helm/values.yaml
@@ -0,0 +1,48 @@
+imageCredentials:
+  registry: docker.ozg-sh.de
+  username: kop
+  password:  
+  email: webmaster@ozg-sh.de
+
+image:
+  repo: docker.ozg-sh.de
+  name: goofy
+  tag: latest # [default: latest]
+
+replicaCount: 2 # [default: 2]
+
+ingressAnnotations:
+  kubernetes.io/ingress.class: traefik
+  traefik.ingress.kubernetes.io/router.entrypoints: websecure
+  traefik.ingress.kubernetes.io/router.tls: "true"
+
+usermanagerName: user-manager
+
+# env:
+#   overrideSpringProfiles: "oc,prod"
+#   customList: # add name value pair for additional environments
+#     - name: Dinge
+#       value: true
+
+# host: # [default: https://<name>.<level>.ozg-sh.de, if level == "prod" https://<name>.ozg-sh.de] optional, host override value. Be aware that XXX.dev.ozg-sh.de can be used in the dev cluster only.
+
+# resources:
+#   limits:
+#     cpu: 1
+#     memory: 1000Mi
+#   requests:
+#     cpu: 50m
+#     memory: 500Mi
+
+# plutoName: pluto # [default: pluto]
+# sso: # Most values are set according to namespace name (<bundesland>-<name>-<level>) and are optional
+  # serverUrl: https://sso.ozg-sh.de # [default: https://sso.dev.ozg-sh.de, if level == "stage|prod" https://sso.ozg-sh.de]
+  # apiPassword:   # Required value
+  # role_einheitlicher_ansprechpartner: false # [default: false]
+  # displayName: "Hüttener Berge" [default: "Realm für <sso.name> (<sso.level>"] The custom display name to write on top of the login page.
+
+
+# kop:
+#   bundesland: sh
+#   bezeichner: kiel
+#   environment: dev
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_affinity_test.yaml b/src/test/helm/deployment_defaults_affinity_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d12e99027345cb0bf82c22280f9297c8273ce604
--- /dev/null
+++ b/src/test/helm/deployment_defaults_affinity_test.yaml
@@ -0,0 +1,25 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should work
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key
+          value: goofyable
+      - equal:
+          path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator
+          value: NotIn
+      - equal:
+          path: spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].values[0]
+          value: "false"
diff --git a/src/test/helm/deployment_defaults_annotaion_test.yaml b/src/test/helm/deployment_defaults_annotaion_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f339eaea438f903c6f1f3aa1d3bfec8e1bcf2f6f
--- /dev/null
+++ b/src/test/helm/deployment_defaults_annotaion_test.yaml
@@ -0,0 +1,24 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/ingress.yaml
+tests:
+  - it: check ingress annotaions if traefik v2
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+    asserts:
+      - isKind:
+          of: Ingress
+      - equal:
+          path: metadata.annotations.[kubernetes.io/ingress.class]
+          value: traefik
+      - equal:
+          path: metadata.annotations.[traefik.ingress.kubernetes.io/router.entrypoints]
+          value: websecure
+      - equal:
+          path: metadata.annotations.[traefik.ingress.kubernetes.io/router.tls]
+          value: "true"
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_env_test.yaml b/src/test/helm/deployment_defaults_env_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..02c38fad69008a0604b9e12cd99c5afa5383ac60
--- /dev/null
+++ b/src/test/helm/deployment_defaults_env_test.yaml
@@ -0,0 +1,46 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-prod
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: check default values
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: prod
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_pluto_address
+            value: pluto.sh-helm-prod:9090
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc, prod
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_realm
+            value: sh-helm-prod
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_resource
+            value: sh-helm-prod-goofy      
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_auth-server-url
+            value: https://sso.ozg-sh.de
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: goofy_keycloak_api_password
+            value: test1234
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_labels_test.yaml b/src/test/helm/deployment_defaults_labels_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..435293b114807acfa54360af3acfa5c071f7e077
--- /dev/null
+++ b/src/test/helm/deployment_defaults_labels_test.yaml
@@ -0,0 +1,28 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+  - templates/service_monitor.yaml
+  - templates/service.yaml
+tests:
+  - it: check default labels
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - equal:
+          path: metadata.labels.[app.kubernetes.io/instance]
+          value: goofy
+      - equal:
+          path: metadata.labels.[app.kubernetes.io/name]
+          value: goofy
+      - equal:
+          path: metadata.labels.[app.kubernetes.io/part-of]
+          value: kop
+      - equal:
+          path: metadata.labels.[app.kubernetes.io/namespace]
+          value: sh-helm-test
diff --git a/src/test/helm/deployment_defaults_spec_containers_health_test.yaml b/src/test/helm/deployment_defaults_spec_containers_health_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ff3abe23ee3e77eabfce97c0c60aac3742eb91d7
--- /dev/null
+++ b/src/test/helm/deployment_defaults_spec_containers_health_test.yaml
@@ -0,0 +1,62 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should work
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.failureThreshold
+          value: 3
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.httpGet.path
+          value: /actuator/health/readiness
+      - equal:
+          path: spec.template.spec.containers[0].readinessProbe.httpGet.port
+          value: 8081
+      - 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  
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.failureThreshold
+          value: 10
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.httpGet.path
+          value: /actuator/health/readiness
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.httpGet.port
+          value: 8081
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.httpGet.scheme
+          value: HTTP
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.initialDelaySeconds
+          value: 30
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.periodSeconds
+          value: 5
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.successThreshold
+          value: 1
+      - equal:
+          path: spec.template.spec.containers[0].startupProbe.timeoutSeconds
+          value: 5
+      
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_spec_containers_securityContext_test.yaml b/src/test/helm/deployment_defaults_spec_containers_securityContext_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9b495037644a61bbbaff0504a8f4516960d48910
--- /dev/null
+++ b/src/test/helm/deployment_defaults_spec_containers_securityContext_test.yaml
@@ -0,0 +1,28 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should work
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.privileged
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
+          value: false
+      - equal:
+          path: spec.template.spec.containers[0].securityContext.runAsNonRoot
+          value: false
diff --git a/src/test/helm/deployment_defaults_spec_containers_test.yaml b/src/test/helm/deployment_defaults_spec_containers_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..34a37263a8df719d4958933366d26c4076c3b87e
--- /dev/null
+++ b/src/test/helm/deployment_defaults_spec_containers_test.yaml
@@ -0,0 +1,77 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: check for some standard values
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.containers[0].image
+          value: "docker.ozg-sh.de/goofy:latest"
+      - equal:
+          path: spec.template.spec.containers[0].imagePullPolicy
+          value: Always
+      - equal:
+          path: spec.template.spec.containers[0].name
+          value: goofy
+      - equal:
+          path: spec.template.spec.containers[0].ports[0].containerPort
+          value: 8080
+      - equal:
+          path: spec.template.spec.containers[0].ports[0].name
+          value: 8080tcp1
+      - equal:
+          path: spec.template.spec.containers[0].ports[0].protocol
+          value: TCP
+      - 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: should add the port for metrics when scrapeMetrics is enabled
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: kiel
+      kop.environment: dev
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.containers[0].ports[1].containerPort
+          value: 8081
+      - equal:
+          path: spec.template.spec.containers[0].ports[1].name
+          value: metrics
+      - equal:
+          path: spec.template.spec.containers[0].ports[1].protocol
+          value: TCP
+  - it: should not add the port for metrics when scrapeMetrics is disabled
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: kiel
+      kop.environment: dev
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - notContains:
+          path: spec.template.spec.containers[0].ports
+          content:
+            name: metrics
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_spec_test.yaml b/src/test/helm/deployment_defaults_spec_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a36146dc77fb2889353f2f1685d0fc09a8eb7690
--- /dev/null
+++ b/src/test/helm/deployment_defaults_spec_test.yaml
@@ -0,0 +1,55 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should work
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.progressDeadlineSeconds
+          value: 600
+      - equal:
+          path: spec.replicas
+          value: 2
+      - equal:
+          path: spec.revisionHistoryLimit
+          value: 10
+      - equal:
+          path: spec.selector.matchLabels.[app.kubernetes.io/name]
+          value: goofy
+      - equal:
+          path: spec.selector.matchLabels.[app.kubernetes.io/namespace]
+          value: sh-helm-test
+      - equal:
+          path: spec.strategy.rollingUpdate.maxSurge
+          value: 1
+      - equal:
+          path: spec.strategy.rollingUpdate.maxUnavailable
+          value: 0
+      - equal:
+          path: spec.strategy.type
+          value: RollingUpdate
+      - equal:
+          path: spec.template.spec.dnsPolicy
+          value: ClusterFirst
+      - equal:
+          path: spec.template.spec.imagePullSecrets[0].name
+          value: goofy-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.terminationGracePeriodSeconds
+          value: 30
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_sso_test.yaml b/src/test/helm/deployment_defaults_sso_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a2f1e9ed10fbad3be0387d0fc2b14153d92ef35e
--- /dev/null
+++ b/src/test/helm/deployment_defaults_sso_test.yaml
@@ -0,0 +1,74 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-prod
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: check default values
+    set:
+      sso.apiPassword: SicherheitGehtVor!!1!
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: prod
+    asserts:
+      - isKind:
+          of: Deployment
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_realm
+            value: sh-helm-prod
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_resource
+            value: sh-helm-prod-goofy      
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_auth-server-url
+            value: https://sso.ozg-sh.de
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: goofy_keycloak_api_password
+            value: SicherheitGehtVor!!1!
+  - it: check sso serverUrl for dev environment
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: name
+      kop.environment: dev
+      sso.apiPassword: test1234
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_auth-server-url
+            value: https://sso.dev.ozg-sh.de
+  - it: check sso serverUrl for test environment
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: name
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_auth-server-url
+            value: https://sso.test.ozg-sh.de
+  - it: check realm with long namespace
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: eins-zwei
+      kop.environment: prod
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: keycloak_realm
+            value: sh-eins-zwei-prod
\ No newline at end of file
diff --git a/src/test/helm/deployment_defaults_topologySpreadConstraints_test.yaml b/src/test/helm/deployment_defaults_topologySpreadConstraints_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..c670af4be87ba4893fe272920c17736eae057975
--- /dev/null
+++ b/src/test/helm/deployment_defaults_topologySpreadConstraints_test.yaml
@@ -0,0 +1,28 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: check default values
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - 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: goofy
\ No newline at end of file
diff --git a/src/test/helm/deployment_env_test.yaml b/src/test/helm/deployment_env_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..52702ef3a707850e29f1e783f5e98b090e5aa009
--- /dev/null
+++ b/src/test/helm/deployment_env_test.yaml
@@ -0,0 +1,33 @@
+suite: test environments
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: check customList
+    template: deployment.yaml
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+      env.customList:
+        - name: my_test_environment_name
+          value: "A test value"
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
+  - it: check customList test value is not set by default
+    template: deployment.yaml
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - notContains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: my_test_environment_name
+            value: "A test value"
diff --git a/src/test/helm/deployment_imageTag_test.yaml b/src/test/helm/deployment_imageTag_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..166e053201afe61eda3ef188c06309b7781d2619
--- /dev/null
+++ b/src/test/helm/deployment_imageTag_test.yaml
@@ -0,0 +1,20 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should set the snapshot latest imageTag
+    set:
+      image.tag: snapshot-latest
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.template.spec.containers[0].image
+          value: docker.ozg-sh.de/goofy:snapshot-latest
\ No newline at end of file
diff --git a/src/test/helm/deployment_pluto_address_test.yaml b/src/test/helm/deployment_pluto_address_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..67e8f5d052e8019e8c7d07b8f965bc2bfa4946d6
--- /dev/null
+++ b/src/test/helm/deployment_pluto_address_test.yaml
@@ -0,0 +1,20 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should set the pluto name
+    set:
+      plutoName: my-test-pluto-name
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: grpc_client_pluto_address
+            value: my-test-pluto-name.sh-helm-test:9090
diff --git a/src/test/helm/deployment_replicas_test.yaml b/src/test/helm/deployment_replicas_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6fe277c36d6939474d9827dc85211c3c44129113
--- /dev/null
+++ b/src/test/helm/deployment_replicas_test.yaml
@@ -0,0 +1,20 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should set the replica count
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+      replicaCount: 5
+    asserts:
+      - isKind:
+          of: Deployment
+      - equal:
+          path: spec.replicas
+          value: 5
\ No newline at end of file
diff --git a/src/test/helm/deployment_resources_test.yaml b/src/test/helm/deployment_resources_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..131ec3d99c1e0e81cdc2cb99ebf4871b9635131d
--- /dev/null
+++ b/src/test/helm/deployment_resources_test.yaml
@@ -0,0 +1,45 @@
+suite: test deployment
+release:
+  name: goofy
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: test resources for prod environment
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: name
+      kop.environment: prod
+      sso.apiPassword: test1234
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.cpu
+          value: 500m
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.memory
+          value: 1000Mi
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.cpu
+          value: 50m
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.memory
+          value: 250Mi
+  - it: test default resources
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: name
+      kop.environment: dev
+      sso.apiPassword: test1234
+    asserts:
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.cpu
+          value: 500m
+      - equal:
+          path: spec.template.spec.containers[0].resources.limits.memory
+          value: 1000Mi
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.cpu
+          value: 50m
+      - equal:
+          path: spec.template.spec.containers[0].resources.requests.memory
+          value: 250Mi
+
diff --git a/src/test/helm/deployment_springProfile_test.yaml b/src/test/helm/deployment_springProfile_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..55bb7b804a940211217a0829f86db4664e434e7e
--- /dev/null
+++ b/src/test/helm/deployment_springProfile_test.yaml
@@ -0,0 +1,36 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should override the spring profiles
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+      env.overrideSpringProfiles: oc,stage,ea
+    asserts:
+      - isKind:
+          of: Deployment
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc,stage,ea
+  - it: should generate the spring profiles
+    set:
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: spring_profiles_active
+            value: oc, test
\ No newline at end of file
diff --git a/src/test/helm/deployment_usermanager_address_test.yaml b/src/test/helm/deployment_usermanager_address_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..3519d0cf3c2181ddd34f1af92213626e9d79bf8f
--- /dev/null
+++ b/src/test/helm/deployment_usermanager_address_test.yaml
@@ -0,0 +1,37 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should set the usermanager url for test environment
+    set:
+      usermanagerName: my-test-usermanager-name
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: kop_user-manager_url
+            value: https://helm-my-test-usermanager-name.test.ozg-sh.de
+  - it: should set the usermanager url for prod environment
+    set:
+      usermanagerName: my-test-usermanager-name
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: prod
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: kop_user-manager_url
+            value: https://helm-my-test-usermanager-name.ozg-sh.de
diff --git a/src/test/helm/deployment_usermanager_internal_address_test.yaml b/src/test/helm/deployment_usermanager_internal_address_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a3ed9a555b5a4246fb6f75b5b16f5e6271e9789c
--- /dev/null
+++ b/src/test/helm/deployment_usermanager_internal_address_test.yaml
@@ -0,0 +1,22 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/deployment.yaml
+tests:
+  - it: should set the internal usermanager url
+    set:
+      usermanagerName: my-test-usermanager-name
+      kop.bundesland: sh
+      kop.bezeichner: helm
+      kop.environment: test
+      sso.apiPassword: test1234
+    asserts:
+      - isKind:
+          of: Deployment
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: kop_user-manager_internalurl
+            value: http://my-test-usermanager-name.sh-helm-test:8080
\ No newline at end of file
diff --git a/src/test/helm/service_monitor_test.yaml b/src/test/helm/service_monitor_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5bf1addd1e47ce39a323f7e0a4baedf3d6eb351b
--- /dev/null
+++ b/src/test/helm/service_monitor_test.yaml
@@ -0,0 +1,52 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: sh-helm-test
+templates:
+  - templates/service_monitor.yaml
+tests:
+  - it: should have the label component with value goofy-service-monitor attached
+    asserts:
+      - isKind:
+          of: ServiceMonitor
+      - equal:
+          path: metadata.labels.[component]
+          value: goofy-service-monitor
+  - it: should have the metrics endpoint configured by default
+    set:
+      env.springProfiles: oc,stage
+    asserts:
+      - isKind:
+          of: ServiceMonitor
+      - contains:
+          path: spec.endpoints
+          content:
+            port: metrics
+            path: /actuator/prometheus
+  - it: should be able to enable the endpoint
+    asserts:
+      - isKind:
+          of: ServiceMonitor
+      - contains:
+          path: spec.endpoints
+          content:
+            port: metrics
+            path: /actuator/prometheus
+  - it: namespace selector should contain the namespace
+    asserts:
+      - contains:
+          path: spec.namespaceSelector.matchNames
+          content: sh-helm-test
+  - it: selector should contain the component label with the value goofy-service
+    asserts:
+      - equal:
+          path: spec.selector.matchLabels.[component]
+          value: goofy-service
+  - it: selector should contain helm recommended labels name and namespace
+    asserts:
+      - equal:
+          path: spec.selector.matchLabels.[app.kubernetes.io/name]
+          value: goofy
+      - equal:
+          path: spec.selector.matchLabels.[app.kubernetes.io/namespace]
+          value: sh-helm-test
diff --git a/src/test/helm/service_test.yaml b/src/test/helm/service_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e1fde5e1f6402a6356e8217d5a3f231d737d1c90
--- /dev/null
+++ b/src/test/helm/service_test.yaml
@@ -0,0 +1,54 @@
+suite: test deployment
+release:
+  name: goofy
+  namespace: helm-test
+templates:
+  - templates/service.yaml
+tests:
+  - it: should have the label component with value goofy-service attached
+    asserts:
+      - isKind:
+          of: Service
+      - equal:
+          path: metadata.labels.[component]
+          value: goofy-service
+  - it: should be of type ClusterIP
+    asserts:
+      - equal:
+          path: spec.type
+          value: ClusterIP
+  - it: ports should contain the 8080 default http port
+    asserts:
+      - contains:
+          path: spec.ports
+          content:
+            name: http
+            port: 8080
+            protocol: TCP
+            targetPort: 8080
+        count: 1
+        any: true
+  - it: ports should contain the metrics port
+    asserts:
+      - contains:
+          path: spec.ports
+          content:
+            name: metrics
+            port: 8081
+            protocol: TCP
+        count: 1
+        any: true
+  - it: selector should contain the component label with the value goofy
+    asserts:
+      - equal:
+          path: spec.selector.[component]
+          value: goofy
+  - it: selector should contain helm recommended labels name and namespace
+    asserts:
+      - equal:
+          path: spec.selector.[app.kubernetes.io/name]
+          value: goofy
+      - equal:
+          path: spec.selector.[app.kubernetes.io/namespace]
+          value: helm-test
+  
\ No newline at end of file