diff --git a/goofy-client/.gitignore b/goofy-client/.gitignore
index 4fd9280cfc1fbd0aa4b37c6d3c2c5798c3aea859..92abdb41d7fa17686e58d3ccf2fcb843520c83e7 100644
--- a/goofy-client/.gitignore
+++ b/goofy-client/.gitignore
@@ -45,3 +45,5 @@ testem.log
 # System Files
 .DS_Store
 Thumbs.db
+
+.angular
diff --git a/goofy-client/angular.json b/goofy-client/angular.json
index dc95c00d557171ac0c83278366be1a3a1463395a..faabb2288332d4d7fda6e994cf2e3450a17e6c01 100644
--- a/goofy-client/angular.json
+++ b/goofy-client/angular.json
@@ -741,6 +741,32 @@
 			},
 			"tags": []
 		},
+		"vorgang-historie": {
+			"projectType": "library",
+			"root": "libs/vorgang-historie",
+			"sourceRoot": "libs/vorgang-historie/src",
+			"prefix": "goofy-client",
+			"architect": {
+				"test": {
+					"builder": "@nrwl/jest:jest",
+					"outputs": ["coverage/libs/vorgang-historie"],
+					"options": {
+						"jestConfig": "libs/vorgang-historie/jest.config.js",
+						"passWithNoTests": true
+					}
+				},
+				"lint": {
+					"builder": "@nrwl/linter:eslint",
+					"options": {
+						"lintFilePatterns": [
+							"libs/vorgang-historie/src/**/*.ts",
+							"libs/vorgang-historie/src/**/*.html"
+						]
+					}
+				}
+			},
+			"tags": []
+		},
 		"vorgang-shared": {
 			"projectType": "library",
 			"root": "libs/vorgang-shared",
diff --git a/goofy-client/apps/goofy-e2e/cypress-ci.json b/goofy-client/apps/goofy-e2e/cypress-ci.json
index 226e3b24a4874cf11e02abb708326aa56cc6f09e..e9ae33f9b5536c4362ae095cb37566d4b2eee0b3 100644
--- a/goofy-client/apps/goofy-e2e/cypress-ci.json
+++ b/goofy-client/apps/goofy-e2e/cypress-ci.json
@@ -18,7 +18,7 @@
 	"screenshotsFolder": "./reports/screenshots",
 	"chromeWebSecurity": false,
 	"reporter": "../../node_modules/cypress-mochawesome-reporter",
-	"defaultCommandTimeout": 30000,
+	"defaultCommandTimeout": 10000,
 	"reporterOptions": {
 		"html": false,
 		"json": true,
diff --git a/goofy-client/apps/goofy-e2e/cypress.json b/goofy-client/apps/goofy-e2e/cypress.json
index e6a2f99932c1bebd99a5b710f42ed5ad0257a9fc..4122b625bd22da6b8d73513906d3bb83f608dc3e 100644
--- a/goofy-client/apps/goofy-e2e/cypress.json
+++ b/goofy-client/apps/goofy-e2e/cypress.json
@@ -19,7 +19,7 @@
 	"screenshotsFolder": "./reports/screenshots",
 	"chromeWebSecurity": false,
 	"reporter": "../../node_modules/cypress-mochawesome-reporter",
-	"defaultCommandTimeout": 30000,
+	"defaultCommandTimeout": 10000,
 	"reporterOptions": {
 		"html": false,
 		"json": true,
diff --git a/goofy-client/apps/goofy-e2e/deployment-values/goofy/ea-values.yaml b/goofy-client/apps/goofy-e2e/deployment-values/goofy/ea-values.yaml
index 186bcf470603c5e114d0646583806d9bda3cf9e8..0f0c380e7742c42c4aac7aa8b20a3bdc2912690c 100644
--- a/goofy-client/apps/goofy-e2e/deployment-values/goofy/ea-values.yaml
+++ b/goofy-client/apps/goofy-e2e/deployment-values/goofy/ea-values.yaml
@@ -1,6 +1,7 @@
 sso:
   serverUrl: 'https://sso.dev.ozg-sh.de/auth'
   role_einheitlicher_ansprechpartner: true
+  apiPassword: "Goofy1234!"
 env:
   overrideSpringProfiles: 'oc,dev,ea,e2e'
 plutoName: pluto
diff --git a/goofy-client/apps/goofy-e2e/deployment-values/goofy/values.yaml b/goofy-client/apps/goofy-e2e/deployment-values/goofy/values.yaml
index 7fc995858ebbf5ef31d5ef914a9f0b8f83a3edad..cf6d7c3b88614b1b205cd616a46dc332303752a3 100644
--- a/goofy-client/apps/goofy-e2e/deployment-values/goofy/values.yaml
+++ b/goofy-client/apps/goofy-e2e/deployment-values/goofy/values.yaml
@@ -1,5 +1,6 @@
 sso:
   serverUrl: 'https://sso.dev.ozg-sh.de/auth'
+  apiPassword: "Goofy1234!"
 env:
   overrideSpringProfiles: 'oc, dev, e2e'
 plutoName: pluto
diff --git a/goofy-client/apps/goofy-e2e/src/components/vorgang/vorgang-list.e2e.component.ts b/goofy-client/apps/goofy-e2e/src/components/vorgang/vorgang-list.e2e.component.ts
index adf241c5f3fab6967a7add75d9755ba38abf02d1..b1e2ac805a7aaba0c03dc50efc52f00ec2d8083a 100644
--- a/goofy-client/apps/goofy-e2e/src/components/vorgang/vorgang-list.e2e.component.ts
+++ b/goofy-client/apps/goofy-e2e/src/components/vorgang/vorgang-list.e2e.component.ts
@@ -6,6 +6,7 @@ export class VorgangListE2EComponent {
 	private readonly spinnerComponent: SpinnerE2EComponent = new SpinnerE2EComponent();
 
 	private readonly locatorRoot: string = 'vorgang-list';
+	private readonly locatorNoRoleMessage: string = 'user-no-role-message';
 
 	public getRoot() {
 		return cy.getTestElement(this.locatorRoot);
@@ -18,4 +19,8 @@ export class VorgangListE2EComponent {
 	public getSpinner() {
 		return this.spinnerComponent.findSpinner(this.getRoot());
 	}
+
+	public getNoRoleMessage() {
+		return cy.getTestElement(this.locatorNoRoleMessage);
+	}
 }
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/fixtures/user/user_emil.json b/goofy-client/apps/goofy-e2e/src/fixtures/user/user_emil.json
index a5e8c36bf6737e1c73a30939cd905fa0068aeb04..fdf45c69e17675488dcbb47134c0d2f941f5f74c 100644
--- a/goofy-client/apps/goofy-e2e/src/fixtures/user/user_emil.json
+++ b/goofy-client/apps/goofy-e2e/src/fixtures/user/user_emil.json
@@ -1,6 +1,6 @@
 {
 	"name": "emil",
-	"password": "Y9nk43yrQ_zzIPpfFU-I",
+	"password": "Ansprechpartner",
 	"firstName": "Emil",
 	"lastName": "Ansprechpartner",
 	"fullName": "Emil Ansprechpartner",
diff --git a/goofy-client/apps/goofy-e2e/src/fixtures/user/user_kfinder.json b/goofy-client/apps/goofy-e2e/src/fixtures/user/user_kfinder.json
index 22f78e014b70157a4d6d26ba3604e7affcf06fc9..3a7a5dcf387c718ca6e9f91ca3b0e834b8f06212 100644
--- a/goofy-client/apps/goofy-e2e/src/fixtures/user/user_kfinder.json
+++ b/goofy-client/apps/goofy-e2e/src/fixtures/user/user_kfinder.json
@@ -1,5 +1,6 @@
 {
 	"name": "kfinder",
 	"password": "Katrinfinder",
-	"groups": ["Abtl. 10.0.1 Versammlungsbehörde, Identitätsfeststellung, Fundbüro"]
+	"groups": ["Abtl. 10.0.1 Versammlungsbehörde, Identitätsfeststellung, Fundbüro"],
+	"clientRoles": ["VERWALTUNG_USER"]
 }
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/fixtures/user/user_kordner.json b/goofy-client/apps/goofy-e2e/src/fixtures/user/user_kordner.json
index f1f4ebbbea2ffe18d2118a52470cf2b17be2a6ae..79b8c6c09a07eaf851ae30f92489b3afd057f71b 100644
--- a/goofy-client/apps/goofy-e2e/src/fixtures/user/user_kordner.json
+++ b/goofy-client/apps/goofy-e2e/src/fixtures/user/user_kordner.json
@@ -1,5 +1,6 @@
 {
 	"name": "kordner",
 	"password": "Klausordner",
-	"groups": ["Abtl. 10.5.1.2 Allgemeine Gefahrenabwehr und sonstige Ordnungsrechtsangelegenheiten"]
+	"groups": ["Abtl. 10.5.1.2 Allgemeine Gefahrenabwehr und sonstige Ordnungsrechtsangelegenheiten"],
+	"clientRoles": ["VERWALTUNG_USER"]
 }
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/fixtures/user/user_richard.json b/goofy-client/apps/goofy-e2e/src/fixtures/user/user_richard.json
new file mode 100644
index 0000000000000000000000000000000000000000..c1fa331c717ea67ff70dbeb7c599b91526189c7e
--- /dev/null
+++ b/goofy-client/apps/goofy-e2e/src/fixtures/user/user_richard.json
@@ -0,0 +1,6 @@
+{
+	"name": "richard",
+	"firstName": "Richard",
+	"lastName": "Rollenlos",
+	"password": "Y9nk43yrQ_zzIPpfFU-I"
+}
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-abschliessen.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-abschliessen.e2e-spec.ts
index 06c04cf370028b782d68678eed6f5f88543020ea..7feba71dcf0ee4fa1317c3e39b019725144f5296 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-abschliessen.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-abschliessen.e2e-spec.ts
@@ -46,14 +46,11 @@ describe('Vorgang abschliessen', () => {
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbschliessen.status]);
 			})
 
-			it('should show snackBar message', () => {
+			it('should show snackBar', () => {
 				vorgangFormularButtons.clickAbschliessenByButton();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN)
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN)
 			})
 
 			it('should close snackBar', () => {
@@ -94,23 +91,23 @@ describe('Vorgang abschliessen', () => {
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbschliessenRevoke.status]);
 			})
 
-			it('should show snackBar message', () => {
+			it('should show snackBar', () => {
 				vorgangPage.getSubnavigation().clickAbschliessenByIconButton();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN);
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackBar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackBar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
-			it('should show status Beschieden', () => {
+			it('should show status Beschieden after progressbar dissapear', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-verwerfen.ea.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-verwerfen.ea.e2e-spec.ts
index b446c717078d72330f2b0bf982cbbad040e60d50..9bd90e3cb517f6d7bdf13798e5081c0ddc532293 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-verwerfen.ea.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-verwerfen.ea.e2e-spec.ts
@@ -104,23 +104,23 @@ describe('Vorgang Verwerfen', () => {
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerwerfenRevoke.status]);
 			})
 
-			it('should show snackBar message', () => {
+			it('should show snackBar', () => {
 				vorgangPage.getSubnavigation().clickVerwerfenByIconButton();
 
-				contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackbar.getCloseButton());
+				contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN);
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackbar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackbar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
-			it('should show status Neu', () => {
+			it('should show status Neu after progressbar dissapear', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-wiedereroeffnen.ea.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-wiedereroeffnen.ea.e2e-spec.ts
index 19969db1281cf3cb0698290ae52ffe031d983814..e2a47659fe3d8cd80b28689e068c517cca4824bc 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-wiedereroeffnen.ea.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-wiedereroeffnen.ea.e2e-spec.ts
@@ -96,23 +96,23 @@ describe('Vorgang wiedereroeffnen', () => {
 					haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnenRevoke.status]);
 				})
 
-				it('should show snackBar message', () => {
+				it('should show snackBar', () => {
 					vorgangPage.getSubnavigation().clickWiedereroeffnenByIconButton();
 
-					contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
-				})
-
-				it('should show snackBar close button', () => {
 					exist(snackbar.getCloseButton());
+					contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
 				})
 
-				it('should show progressbar', () => {
+				it('should close snackbar on revoke', () => {
 					snackbar.getRevokeButton().click();
 
-					exist(vorgangPage.getProgressBar());
+					notExist(snackbar.getMessage());
+					//exist(vorgangPage.getProgressBar());
 				})
 
-				it('should show status Abgeschlossen', () => {
+				it('should show status Abgeschlossen after progressbar dissapear', () => {
+					notExist(vorgangPage.getProgressBar());
+
 					haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]);
 				})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-zurueckholen.ea.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-zurueckholen.ea.e2e-spec.ts
index a8cca227ed36bc17abfa2ab8a7e675db15184700..7a1e758268f04d2fe37be61bfb5fe100dabd4bc3 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-zurueckholen.ea.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/vorgang-detail/vorgang-zurueckholen.ea.e2e-spec.ts
@@ -113,13 +113,15 @@ describe('Vorgang Zurueckholen', () => {
 				exist(snackBar.getCloseButton());
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackBar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackBar.getMessage());
 			})
 
-			it('should show status Verworfen', () => {
+			it('should show status Verworfen after progressbar dissapear', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/interceptor/interceptor-forbidden.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/interceptor/interceptor-forbidden.e2e-spec.ts
index 6f971f3dce5e52e043a092c5c36efe36b2235337..92510a18b588ab1da31fe9e98df3b45d0c051706 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/interceptor/interceptor-forbidden.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/interceptor/interceptor-forbidden.e2e-spec.ts
@@ -59,6 +59,12 @@ describe('Interceptor Forbidden', () => {
 			})
 		})
 
+		it('should close snackbar on close button', () => {
+			snackbar.getCloseButton().click()
+
+			notExist(snackbar.getMessage());
+		})
+
 		it('should navigate back on back button', () => {
 			subnavigation.clickBackButton();
 		})
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts
index 83e1ee78b3d2fdf94dc4c2ce754c059e3422841d..8f5b997336681229f082ca75e91d259aac2ff6f5 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts
@@ -1,13 +1,13 @@
 import { NavigationE2EComponent } from 'apps/goofy-e2e/src/components/navigation/navigation.e2e.component';
 import { VorgangListE2EComponent } from 'apps/goofy-e2e/src/components/vorgang/vorgang-list.e2e.component';
 import { VorgangE2E } from 'apps/goofy-e2e/src/model/vorgang';
-import { MainPage } from 'apps/goofy-e2e/src/page-objects/main.po';
+import { MainPage, waitForSpinnerToDisappear } from 'apps/goofy-e2e/src/page-objects/main.po';
 import { dropCollections } from 'apps/goofy-e2e/src/support/cypress-helper';
 import { CypressKeyboardActions, exist, notExist } from 'apps/goofy-e2e/src/support/cypress.util';
 import { getUserSabineUuid, loginAsSabine } from 'apps/goofy-e2e/src/support/user-util';
 import { buildVorgang, createVorgang, initVorgaenge, objectIds } from 'apps/goofy-e2e/src/support/vorgang-util';
 
-describe.skip('Navigation', () => {
+describe('Navigation', () => {
 	const mainPage: MainPage = new MainPage();
 	const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
 
@@ -25,6 +25,10 @@ describe.skip('Navigation', () => {
 
 		loginAsSabine();
 
+		waitForSpinnerToDisappear();
+		exist(vorgangList.getRoot());
+		navigation.getAllVorgaengeItem().click();
+		waitForSpinnerToDisappear();
 		exist(vorgangList.getRoot());
 	})
 
@@ -36,6 +40,7 @@ describe.skip('Navigation', () => {
 
 		it('should hide not to user assigned vorgaenge', () => {
 			navigation.getMyVorgaengeItem().click();
+			waitForSpinnerToDisappear();
 
 			notExist(vorgangList.getListItem(vorgang.name).getRoot());
 			notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot());
@@ -45,6 +50,7 @@ describe.skip('Navigation', () => {
 
 		it('should hide not matching vorgaenge after do search', () => {
 			doSearch(searchString);
+			waitForSpinnerToDisappear();
 
 			notExist(vorgangList.getListItem(vorgang.name).getRoot());
 			notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot());
@@ -57,6 +63,7 @@ describe.skip('Navigation', () => {
 
 		it('should show all vorgaenge', () => {
 			navigation.getAllVorgaengeItem().click();
+			waitForSpinnerToDisappear();
 
 			exist(vorgangList.getListItem(vorgang.name).getRoot());
 			exist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot());
@@ -66,6 +73,7 @@ describe.skip('Navigation', () => {
 
 		it('should hide not matching vorgaenge after do search', () => {
 			doSearch(searchString);
+			waitForSpinnerToDisappear();
 
 			notExist(vorgangList.getListItem(vorgang.name).getRoot());
 			exist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot());
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail-error.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail-error.e2e-spec.ts
index 621dabf8a158720324163270a540d882c28f3c4a..679fce67414b36e7d7e7358bf61f9bc6f0860bdc 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail-error.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail-error.e2e-spec.ts
@@ -120,6 +120,12 @@ describe('PostfachMail error', () => {
 					notExist(snackbar.getRevokeButton());
 				})
 
+				it('should close snackbar on close button', () => {
+					snackbar.getCloseButton().click();
+
+					notExist(snackbar.getMessage());
+				})
+
 				it('should show mail subject', () => {
 					contains(listItem.getSubject(), postfachMailItem.subject);
 				})
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail.e2e-spec.ts
index 63ee7d0fd571d2ae8748978b8e57b100a507fe77..c8d2c5f1b3940b4a6f934a36f25b6d94ad9c40dc 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail.e2e-spec.ts
@@ -249,6 +249,12 @@ describe('PostfachMail', () => {
 				notExist(snackbar.getRevokeButton());
 			})
 
+			it('should close snackbar on close button', () => {
+				snackbar.getCloseButton().click();
+
+				notExist(snackbar.getMessage());
+			})
+
 			it('should show postfach mail in list', () => {
 				const postfachMailItem: PostfachMailListItem = postfachMailContainer.getListItem(postfachMailToSend.subject);
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail.filtered-by-organisationseinheit.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail.filtered-by-organisationseinheit.e2e-spec.ts
index 8c388898fd9a633fe3e8a968ef7cdc970060b646..b0b322a9609135924c289cb2a5c753798b4436f9 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail.filtered-by-organisationseinheit.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/postfach-mail/postfach-mail.filtered-by-organisationseinheit.e2e-spec.ts
@@ -62,8 +62,18 @@ describe('PostfachNachrichten filtered by organisationseinheit', () => {
 			visitUrl(forbiddenUrl);
 
 			notExist(postfachMailPage.getBreadcrump());
+		})
+
+		it('should show snackbar', () => {
+			exist(snackbar.getCloseButton());
 			contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN);
-		});
+		})
+
+		it('should close snackbar on close button', () => {
+			snackbar.getCloseButton().click();
+
+			notExist(snackbar.getMessage());
+		})
 	})
 
 	describe('on user kordner', () => {
@@ -89,8 +99,18 @@ describe('PostfachNachrichten filtered by organisationseinheit', () => {
 			visitUrl(forbiddenUrl);
 
 			notExist(postfachMailPage.getBreadcrump())
+		})
+
+		it('should show snackbar', () => {
+			exist(snackbar.getCloseButton());
 			contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN);
 		})
+
+		it('should close snackbar on close button', () => {
+			snackbar.getCloseButton().click();
+
+			notExist(snackbar.getMessage());
+		})
 	})
 
 	function logInParts(toLog: string): void {
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-assign-unassign.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-assign-unassign.e2e-spec.ts
index 4ee3b74623b6c6d794867813a49552103d1a0c49..343e7e46f11cf60ae31e2f0932464b07f7402379 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-assign-unassign.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-assign-unassign.e2e-spec.ts
@@ -17,7 +17,7 @@ describe('User Profile im ausgewählten Vorgang', () => {
 	const vorgangPage: VorgangPage = new VorgangPage();
 	const userProfileContainer: UserProfileE2EComponent = vorgangPage.getVorgangDetailHeader().getUserContainer();
 
-	let vorgang: VorgangE2E = createVorgang();
+	const vorgang: VorgangE2E = createVorgang();
 	const userSabine: UserE2E = getUserSabine();
 	const userEmil: UserE2E = getUserEmil();
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-in-vorgang-error.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-in-vorgang-error.e2e-spec.ts
index 3270339a9c28435a401ac8ef8d962eb9ac436c33..9e9e5cade45cca13bb320987213380cc3717b789 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-in-vorgang-error.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-in-vorgang-error.e2e-spec.ts
@@ -20,7 +20,7 @@ describe('User profile assigned to vorgang', () => {
 	const vorgangPage: VorgangPage = new VorgangPage();
 	const userProfileContainer: UserProfileE2EComponent = vorgangPage.getVorgangDetailHeader().getUserContainer();
 
-	let vorgang: VorgangE2E = { ...createVorgang(), assignedTo: faker.datatype.uuid() };
+	const vorgang: VorgangE2E = { ...createVorgang(), assignedTo: faker.datatype.uuid() };
 
 	before(() => {
 		initVorgang(vorgang);
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-abschliessen.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-abschliessen.e2e-spec.ts
index 418c7631cfcffa90eb7157ac5dd19b4600aba17d..55ecd6385967f3649c7c336745f832b7d72e3dda 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-abschliessen.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-abschliessen.e2e-spec.ts
@@ -97,20 +97,20 @@ describe('Vorgang abschliessen(EA)', () => {
 			it('should show snackBar message', () => {
 				vorgangPage.getSubnavigation().clickAbschliessenByIconButton();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN);
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackBar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackBar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
 			it('should show status Beschieden', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-annehmen.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-annehmen.e2e-spec.ts
index 1e5c724078e13598c0f05f24941f0f19d1d14ae6..73d516905ca585046ed9348a558b7b8f4d36299b 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-annehmen.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-annehmen.e2e-spec.ts
@@ -54,14 +54,11 @@ describe('Vorgang Annehmen', () => {
 			it('should show snackBar message', () => {
 				vorgangFormularButtons.clickAnnehmenByButton();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ANGENOMMEN);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ANGENOMMEN);
 			})
 
-			it('should close snackBar', () => {
+			it('should close snackBar on close', () => {
 				snackBar.getCloseButton().click();
 
 				notExist(snackBar.getMessage());
@@ -102,20 +99,20 @@ describe('Vorgang Annehmen', () => {
 			it('should show snackBar message', () => {
 				vorgangPage.getSubnavigation().clickAnnehmenByIconButton();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ANGENOMMEN);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ANGENOMMEN);
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackBar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackBar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
 			it('should show status Neu', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-bearbeiten.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-bearbeiten.e2e-spec.ts
index f22f6ee8e24337c7a53373fc226e043a712481d9..abd022f8c6c32bcf5cc87375cbd2fa701566f2dd 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-bearbeiten.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-bearbeiten.e2e-spec.ts
@@ -46,13 +46,10 @@ describe('Vorgang bearbeiten', () => {
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBearbeiten.status]);
 			})
 
-			it('should show snackBar message', () => {
+			it('should show snackBar', () => {
 				vorgangFormularButtons.clickBearbeitenByButton();
 
 				contains(snackBar.getMessage(), VorgangMessagesE2E.BEARBEITET);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
 			})
 
@@ -104,13 +101,16 @@ describe('Vorgang bearbeiten', () => {
 				exist(snackBar.getCloseButton());
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackBar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackBar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
 			it('should show status Angenommen', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-bescheiden.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-bescheiden.e2e-spec.ts
index 828b30bcfc7c56016230710851d2ffbe24ba0332..73126c63f341322de58680441d1f6b957968db50 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-bescheiden.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-bescheiden.e2e-spec.ts
@@ -104,13 +104,16 @@ describe('Vorgang bescheiden', () => {
 				exist(snackBar.getCloseButton());
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackBar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackBar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
-			it('should show status In Bearbeitung', () => {
+			it('should show status Angenommen', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts
index cb4b967375f9dac8017e703ffd3e9c8b4826164e..a1c797d4b44ea4985d9a6e43d53b0735428457c5 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts
@@ -57,6 +57,10 @@ describe('Vorgang-detailansicht filtered by organisationseinheit', () => {
 			visitUrl(forbiddenUrl)
 
 			notExist(detailPage.getRoot());
+		})
+
+		it('should show snackbar', () => {
+			exist(snackbar.getCloseButton());
 			contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN);
 		})
 	})
@@ -82,6 +86,10 @@ describe('Vorgang-detailansicht filtered by organisationseinheit', () => {
 			visitUrl(forbiddenUrl)
 
 			notExist(detailPage.getRoot());
+		})
+
+		it('should show snackbar', () => {
+			exist(snackbar.getCloseButton());
 			contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN);
 		})
 	})
@@ -106,10 +114,25 @@ describe('Vorgang-detailansicht filtered by organisationseinheit', () => {
 				contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN);
 			})
 
+			it('should show snackbar', () => {
+				exist(snackbar.getCloseButton());
+				contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN);
+			})
+
+			it('should close snackbar on close button', () => {
+				snackbar.getCloseButton().click();
+
+				notExist(snackbar.getCloseButton());
+			})
+
 			it('should not open detailpage (for kfinder)', () => {
 				visitUrl(forbiddenUrl)
 
 				notExist(detailPage.getRoot());
+			})
+
+			it('should show snackbar', () => {
+				exist(snackbar.getCloseButton());
 				contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN);
 			})
 		})
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-verwerfen.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-verwerfen.e2e-spec.ts
index 0d15e1c5b29f7d9e1acd5d833f6e47c1b08cc3cb..2f3c88f338ad5ae015e2d2661ba41e9883cd508c 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-verwerfen.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-verwerfen.e2e-spec.ts
@@ -51,14 +51,11 @@ describe('Vorgang Verwerfen', () => {
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerwerfen.status]);
 			})
 
-			it('should show snackBar message', () => {
+			it('should show snackBar', () => {
 				vorgangFormularButtons.clickVerwerfenByButton();
 
-				contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackbar.getCloseButton());
+				contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN);
 			})
 
 			it('should close snackBar', () => {
@@ -114,13 +111,16 @@ describe('Vorgang Verwerfen', () => {
 				exist(snackbar.getCloseButton());
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackbar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackbar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
 			it('should show status Neu', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.e2e-spec.ts
index 1858838d553977c8fb374a22588823053dbdf3a2..368a69cd1aebbbeaf068dc0f8fa069e67cdf02e6 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.e2e-spec.ts
@@ -100,17 +100,14 @@ describe('Vorgang wiedereroeffnen', () => {
 				it('should show snackBar message', () => {
 					vorgangPage.getSubnavigation().clickWiedereroeffnenByIconButton();
 
-					contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
-				})
-
-				it('should show snackBar close button', () => {
 					exist(snackbar.getCloseButton());
+					contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
 				})
 
-				it('should show progressbar', () => {
+				it('should close snackbar on revoke', () => {
 					snackbar.getRevokeButton().click();
 
-					exist(vorgangPage.getProgressBar());
+					notExist(snackbar.getMessage());
 				})
 
 				it('should show status Beschieden', () => {
@@ -151,11 +148,8 @@ describe('Vorgang wiedereroeffnen', () => {
 				it('should show snackBar message', () => {
 					vorgangFormularButtons.clickWiedereroeffnenByButton();
 
-					contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
-				})
-
-				it('should show snackBar close button', () => {
 					exist(snackbar.getCloseButton());
+					contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
 				})
 
 				it('should close snackBar', () => {
@@ -196,23 +190,23 @@ describe('Vorgang wiedereroeffnen', () => {
 					haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnenRevoke.status]);
 				})
 
-				it('should show snackBar message', () => {
+				it('should show snackBar', () => {
 					vorgangPage.getSubnavigation().clickWiedereroeffnenByIconButton();
 
-					contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
-				})
-
-				it('should show snackBar close button', () => {
 					exist(snackbar.getCloseButton());
+					contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET);
 				})
 
-				it('should show progressbar', () => {
+				it('should close snackbar on revoke', () => {
 					snackbar.getRevokeButton().click();
 
-					exist(vorgangPage.getProgressBar());
+					notExist(snackbar.getMessage());
+					//exist(vorgangPage.getProgressBar());
 				})
 
 				it('should show status Abgeschlossen', () => {
+					notExist(vorgangPage.getProgressBar());
+
 					haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]);
 				})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-zurueckholen.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-zurueckholen.e2e-spec.ts
index f22c2435761230070c1ec32e386a11d41bfeb015..694a5dff596dabae5e498e73710204eb8b495960 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-zurueckholen.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-zurueckholen.e2e-spec.ts
@@ -54,11 +54,8 @@ describe('Vorgang Zurueckholen', () => {
 			it('should show snackBar message', () => {
 				vorgangFormularButtons.getZurueckholenButton().click();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT);
 			})
 
 			it('should close snackBar', () => {
@@ -103,23 +100,23 @@ describe('Vorgang Zurueckholen', () => {
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckholenRevoke.status]);
 			})
 
-			it('should show snackBar message', () => {
+			it('should show snackBar', () => {
 				vorgangPage.getSubnavigation().getZurueckholenIconButton().click();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT);
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackBar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackBar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
-			it('should show status Verworfen', () => {
+			it('should show status Abgeschlossen', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.e2e-spec.ts
index 5369892a4a69a2dba8d398761ecc0cda846f714a..8008aa1fe9b74183c1a04e579b695e5492caa19a 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.e2e-spec.ts
@@ -62,11 +62,8 @@ describe('Vorgang Zurueckstellen', () => {
 			it('should show snackBar message', () => {
 				vorgangFormularButtons.clickZurueckstellenByButton();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGESTELLT);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGESTELLT);
 			})
 
 			it('should close snackBar', () => {
@@ -110,20 +107,20 @@ describe('Vorgang Zurueckstellen', () => {
 			it('should show snackBar message', () => {
 				vorgangPage.getSubnavigation().clickZurueckstellenByIconButton();
 
-				contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGESTELLT);
-			})
-
-			it('should show snackBar close button', () => {
 				exist(snackBar.getCloseButton());
+				contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGESTELLT);
 			})
 
-			it('should show progressbar', () => {
+			it('should close snackbar on revoke', () => {
 				snackBar.getRevokeButton().click();
 
-				exist(vorgangPage.getProgressBar());
+				notExist(snackBar.getMessage());
+				//exist(vorgangPage.getProgressBar());
 			})
 
 			it('should show status In Bearbeitung', () => {
+				notExist(vorgangPage.getProgressBar());
+
 				haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]);
 			})
 
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-list.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-list.e2e-spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6be81c9f1d0c937de85b6b5a679025cf80fbbeb5
--- /dev/null
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-list.e2e-spec.ts
@@ -0,0 +1,92 @@
+import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
+import { EingangE2E, VorgangE2E } from '../../../model/vorgang';
+import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
+import { dropCollections } from '../../../support/cypress-helper';
+import { exist, notExist } from '../../../support/cypress.util';
+import { ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } from '../../../support/data.util';
+import { loginAsKfinder, loginAsKordner, loginAsRichard, loginAsZonk } from '../../../support/user-util';
+import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
+
+describe('VorgangList', () => {
+	const mainPage: MainPage = new MainPage();
+	const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
+
+	const eingangForKFinder: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER } };
+	const vorgangForKFinder: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangVisibleToKFinder'), eingangs: [eingangForKFinder] };
+
+	const eingangForKOrdner: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } };
+	const vorgangForKOrdner: VorgangE2E = { ...buildVorgang(objectIds[1], 'VorgangVisibleToKOrdner'), eingangs: [eingangForKOrdner] };
+
+	before(() => {
+		initVorgaenge([vorgangForKFinder, vorgangForKOrdner]);
+	})
+
+	after(() => {
+		dropCollections();
+	})
+
+	describe('filtered/authorized', () => {
+
+		describe('by user kfinder', () => {
+
+			before(() => {
+				loginAsKfinder();
+
+				exist(vorgangList.getRoot());
+				waitForSpinnerToDisappear();
+			})
+
+			it('should show authorized vorgaenge', () => {
+				exist(vorgangList.getListItem(vorgangForKFinder.name).getRoot());
+				notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot());
+			})
+		})
+
+		describe('by user kordner', () => {
+
+			before(() => {
+				loginAsKordner();
+
+				exist(vorgangList.getRoot());
+				waitForSpinnerToDisappear();
+			})
+
+			it('should show authorized vorgaenge', () => {
+				exist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot());
+				notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot());
+			})
+		})
+
+		describe('by user zonk', () => {
+
+			const vorgang: VorgangE2E = createVorgang();
+
+			before(() => {
+				loginAsZonk();
+
+				exist(vorgangList.getRoot());
+				waitForSpinnerToDisappear();
+			})
+
+			it('should show authorized empty vorgaenge', () => {
+				notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot());
+				notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot());
+				notExist(vorgangList.getListItem(vorgang.name).getRoot());
+			})
+		})
+
+		describe('by user richard', () => {
+
+			before(() => {
+				loginAsRichard();
+
+				waitForSpinnerToDisappear();
+			})
+
+			it('should show hint message while have no roles', () => {
+				notExist(vorgangList.getRoot());
+				exist(vorgangList.getNoRoleMessage());
+			})
+		})
+	})
+})
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-list.filtered-by-organisationseinheit.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-list.filtered-by-organisationseinheit.e2e-spec.ts
deleted file mode 100644
index a34bf37792c33edaad29827f089cda91bf558ec6..0000000000000000000000000000000000000000
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-list.filtered-by-organisationseinheit.e2e-spec.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
-import { EingangE2E, VorgangE2E } from '../../../model/vorgang';
-import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
-import { dropCollections } from '../../../support/cypress-helper';
-import { exist, notExist } from '../../../support/cypress.util';
-import { ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } from '../../../support/data.util';
-import { loginAsKfinder, loginAsKordner, loginAsZonk } from '../../../support/user-util';
-import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
-
-describe('VorgangList filtered by organisationseinheit', () => {
-	const mainPage: MainPage = new MainPage();
-	const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
-
-	const eingangForKFinder: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER } };
-	const vorgangForKFinder: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangVisibleToKFinder'), eingangs: [eingangForKFinder] };
-
-	const eingangForKOrdner: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } };
-	const vorgangForKOrdner: VorgangE2E = { ...buildVorgang(objectIds[1], 'VorgangVisibleToKOrdner'), eingangs: [eingangForKOrdner] };
-
-	before(() => {
-		initVorgaenge([vorgangForKFinder, vorgangForKOrdner]);
-	})
-
-	after(() => {
-		dropCollections();
-	})
-
-	describe('on user kfinder', () => {
-
-		before(() => {
-			loginAsKfinder();
-
-			exist(vorgangList.getRoot());
-			waitForSpinnerToDisappear();
-		})
-
-		it('should check list', () => {
-			exist(vorgangList.getListItem(vorgangForKFinder.name).getRoot());
-			notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot());
-		})
-	})
-
-	describe('on user kordner', () => {
-
-		before(() => {
-			loginAsKordner();
-
-			exist(vorgangList.getRoot());
-			waitForSpinnerToDisappear();
-		})
-
-		it('should check list', () => {
-			exist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot());
-			notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot());
-		})
-	})
-
-	describe('on user zonk', () => {
-
-		const vorgang: VorgangE2E = createVorgang();
-
-		before(() => {
-			loginAsZonk();
-
-			exist(vorgangList.getRoot());
-			waitForSpinnerToDisappear();
-		})
-
-		it('should check list', () => {
-			notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot());
-			notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot());
-			notExist(vorgangList.getListItem(vorgang.name).getRoot());
-		})
-	})
-})
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-wiedervorlage/vorgang-wiedervorlage.routing.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-wiedervorlage/vorgang-wiedervorlage.routing.e2e-spec.ts
index d50a8ae4105283a7041facd9ddc2ad1566b3ed1c..53a786504e07c4cb60d8da78955ea6f50c2209b2 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-wiedervorlage/vorgang-wiedervorlage.routing.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-wiedervorlage/vorgang-wiedervorlage.routing.e2e-spec.ts
@@ -20,7 +20,7 @@ describe('Vorgang Detailansicht Wiedervorlage routing', () => {
 	const vorgangPage: VorgangPage = new VorgangPage();
 	const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage();
 
-	let vorgang: VorgangE2E = createVorgang();
+	const vorgang: VorgangE2E = createVorgang();
 
 	before(() => {
 		initVorgang(vorgang);
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 ba33064224e38a6e59e2c85881154acd8d54170f..8332dbe37f3a8f847edb877d9e4eec23f61953e7 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
@@ -87,12 +87,17 @@ describe('Wiedervorlage attachments', () => {
 			exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot());
 		})
 
-		it('should error snackbar after upload to large file', () => {
+		it('should error snackbar after upload to large file', { defaultCommandTimeout: 30000 }, () => {
 			uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT_46MB);
 
 			exist(snackbar.getMessage());
 			contains(snackbar.getMessage(), BinaryFileSnackbarMessageE2E.ATTACHMENT_NOT_ADDED.replace('{size}', '40MB'));
+		})
+
+		it('should close snackbar on close button', () => {
 			snackbar.getCloseButton().click();
+
+			notExist(snackbar.getMessage());
 		})
 
 		it('should download attachment on click', () => {
diff --git a/goofy-client/apps/goofy-e2e/src/support/user-util.ts b/goofy-client/apps/goofy-e2e/src/support/user-util.ts
index 8c205092db57422b6353aeef62a68bb03a41e614..148d262be6246794a3a93ed8b67b489f3f20c97f 100644
--- a/goofy-client/apps/goofy-e2e/src/support/user-util.ts
+++ b/goofy-client/apps/goofy-e2e/src/support/user-util.ts
@@ -21,6 +21,7 @@ enum DatabaseUser {
 	KFINDER = 'user/user_kfinder.json',
 	KORDNER = 'user/user_kordner.json',
 	PETER = 'user/user_peter.json',
+	RICHARD = 'user/user_richard.json',
 	SABINE = 'user/user_sabine.json',
 	ZONK = 'user/user_zonk.json'
 }
@@ -41,6 +42,10 @@ export function loginAsPeter(): void {
 	login(DatabaseUser.PETER);
 }
 
+export function loginAsRichard(): void {
+	login(DatabaseUser.RICHARD);
+}
+
 export function loginAsSabine(): void {
 	login(DatabaseUser.SABINE);
 }
diff --git a/goofy-client/apps/goofy/src/styles/abstracts/_variables.scss b/goofy-client/apps/goofy/src/styles/abstracts/_variables.scss
index 89fc0e3b6c753a8f96b78f11004fe86ce9892805..25c38013e2a41900e131a44781410d0a7947294c 100644
--- a/goofy-client/apps/goofy/src/styles/abstracts/_variables.scss
+++ b/goofy-client/apps/goofy/src/styles/abstracts/_variables.scss
@@ -1,6 +1,7 @@
 @use '@angular/material' as mat;
 
 $grey: #777;
+$greyLight: rgba(0, 0, 0, 0.08);
 
 $background: #fafafa;
 $dark-background: #303030;
diff --git a/goofy-client/libs/tech-shared/src/index.ts b/goofy-client/libs/tech-shared/src/index.ts
index b607f46b67b53b24bfee67f8af75735ed9d821f2..7e0f749f00c0b9bc0c3f6c8895db70bec44535fb 100644
--- a/goofy-client/libs/tech-shared/src/index.ts
+++ b/goofy-client/libs/tech-shared/src/index.ts
@@ -11,6 +11,7 @@ export * from './lib/pipe/file-size.pipe';
 export * from './lib/pipe/format-date-with-time.pipe';
 export * from './lib/pipe/format-to-pretty-date.pipe';
 export * from './lib/pipe/has-link.pipe';
+export * from './lib/pipe/not-has-link.pipe';
 export * from './lib/pipe/to-embedded-resource.pipe';
 export * from './lib/pipe/to-resource-uri.pipe';
 export * from './lib/pipe/to-traffic-light-tooltip.pipe';
diff --git a/goofy-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.spec.ts b/goofy-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c7517c2753666e5651cbfae1fcfa477f60780b86
--- /dev/null
+++ b/goofy-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.spec.ts
@@ -0,0 +1,21 @@
+import { Resource } from '@ngxp/rest';
+import { createDummyResource } from 'libs/tech-shared/test/resource';
+import { NotHasLinkPipe } from './not-has-link.pipe';
+
+describe('NotHasLinkPipe', () => {
+	const selfLink: string = 'self';
+	const dummyLink: string = 'dummy';
+	const resource: Resource = createDummyResource([selfLink]);
+	const pipe: NotHasLinkPipe = new NotHasLinkPipe();
+
+	it('resource has link', () => {
+		const result: boolean = pipe.transform(resource, selfLink);
+
+		expect(result).toBe(false);
+	})
+	it('resource doesnt has link', () => {
+		const result: boolean = pipe.transform(resource, dummyLink);
+
+		expect(result).toBe(true);
+	})
+})
diff --git a/goofy-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts b/goofy-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d68f0417cea19776db39a12a21129d85b0f11269
--- /dev/null
+++ b/goofy-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts
@@ -0,0 +1,9 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { hasLink, Resource } from '@ngxp/rest';
+
+@Pipe({ name: 'notHasLink' })
+export class NotHasLinkPipe implements PipeTransform {
+	transform(resource: Resource, link: string) {
+		return !hasLink(resource, link);
+	}
+}
diff --git a/goofy-client/libs/tech-shared/src/lib/tech-shared.module.ts b/goofy-client/libs/tech-shared/src/lib/tech-shared.module.ts
index 2ed55173a712884078afff7af605bde8623913b7..67328c81f7d110f528ba7d4282651a251f6ddf24 100644
--- a/goofy-client/libs/tech-shared/src/lib/tech-shared.module.ts
+++ b/goofy-client/libs/tech-shared/src/lib/tech-shared.module.ts
@@ -8,6 +8,7 @@ import { FileSizePipe } from './pipe/file-size.pipe';
 import { FormatDateWithTimePipe } from './pipe/format-date-with-time.pipe';
 import { FormatToPrettyDatePipe } from './pipe/format-to-pretty-date.pipe';
 import { HasLinkPipe } from './pipe/has-link.pipe';
+import { NotHasLinkPipe } from './pipe/not-has-link.pipe';
 import { ToEmbeddedResourcesPipe } from './pipe/to-embedded-resource.pipe';
 import { ToResourceUriPipe } from './pipe/to-resource-uri.pipe';
 import { ToTrafficLightTooltipPipe } from './pipe/to-traffic-light-tooltip.pipe';
@@ -20,6 +21,7 @@ import { ToTrafficLightPipe } from './pipe/to-traffic-light.pipe';
 		EnumToLabelPipe,
 		FormatDateWithTimePipe,
 		HasLinkPipe,
+		NotHasLinkPipe,
 		ToResourceUriPipe,
 		ToTrafficLightPipe,
 		ToTrafficLightTooltipPipe,
@@ -32,6 +34,7 @@ import { ToTrafficLightPipe } from './pipe/to-traffic-light.pipe';
 		EnumToLabelPipe,
 		FormatDateWithTimePipe,
 		HasLinkPipe,
+		NotHasLinkPipe,
 		ToResourceUriPipe,
 		ToTrafficLightPipe,
 		ToTrafficLightTooltipPipe,
diff --git a/goofy-client/libs/test-utils/src/lib/helper.ts b/goofy-client/libs/test-utils/src/lib/helper.ts
index e16d3029e0f10ca2d8a5602bc54d52a835d69c9e..94887c81370ac5a428485249e842ddc34158afdd 100644
--- a/goofy-client/libs/test-utils/src/lib/helper.ts
+++ b/goofy-client/libs/test-utils/src/lib/helper.ts
@@ -10,15 +10,15 @@ function getDebugElementFromFixtureByType<T>(fixture: ComponentFixture<any>, com
 	return fixture.debugElement.query(By.directive(component));
 }
 
-export function getDebugElementFromFixtureByCss(fixture: ComponentFixture<any>, query: string): DebugElement {
-	return fixture.debugElement.query(By.css(query));
-}
-
 export function getElementFromFixture(fixture: ComponentFixture<any>, htmlElement: string): any {
 	return fixture.nativeElement.querySelector(htmlElement);
 }
 
 export function dispatchEventFromFixture(fixture: ComponentFixture<any>, elementSelector: string, event: string): void {
-	const element = fixture.debugElement.query(By.css(elementSelector));
+	const element = getDebugElementFromFixtureByCss(fixture, elementSelector)
 	element.nativeElement.dispatchEvent(new Event(event));
 }
+
+export function getDebugElementFromFixtureByCss(fixture: ComponentFixture<any>, query: string): DebugElement {
+	return fixture.debugElement.query(By.css(query));
+}
\ No newline at end of file
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.html b/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..312d42ddadb72b90bf3559e644f3f8601a9a4955
--- /dev/null
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.html
@@ -0,0 +1,3 @@
+<button mat-icon-button (click)="close.emit()" data-test-id="snackbar-close-button">
+	<mat-icon data-test-class="icon">clear</mat-icon>
+</button>
\ No newline at end of file
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.scss b/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..5e2fce20b698f7394eacec58ae3fbd517862d2ee
--- /dev/null
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.scss
@@ -0,0 +1,50 @@
+@use 'sass:map';
+@use '@angular/material' as mat;
+@import 'variables';
+
+.message {
+	white-space: pre-wrap
+}
+
+::ng-deep .mat-snack-bar-container.error {
+	min-width: 240px;
+	max-width: 90vw;
+
+	border: 3px solid mat.get-color-from-palette($warnPalette);
+	background-color: lighten(mat.get-color-from-palette($warnPalette), 38%);
+	color: rgba(#000, 0.89);
+	position: relative;
+
+	&:before {
+		position: absolute;
+		content: url("/assets/icons/error_outline_white.svg");
+		display: block;
+		background-color: mat.get-color-from-palette($warnPalette);
+		left: 0;
+		top: 0;
+		padding: 11px 9px 11px 7px;
+		color: #fff;
+		height: 100%;
+	}
+
+	> div {
+		margin-left: 44px;
+	}
+}
+
+.wrapper {
+	display: flex;
+	align-items: center;
+}
+
+.mat-button {
+	color: mat.get-color-from-palette($primaryPalette, lighter);
+}
+
+button {
+	margin: -12px -8px -12px 8px
+}
+
+::ng-deep body.dark .mat-snack-bar-container .mat-button {
+	color: mat.get-color-from-palette($primaryPalette);
+}
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4a419ae9594946ac9edc382392cddd4bc5b1f47d
--- /dev/null
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts
@@ -0,0 +1,39 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatIcon } from '@angular/material/icon';
+import { dispatchEventFromFixture, mock } from '@goofy-client/test-utils';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { EventEmitter } from 'stream';
+import { SnackbarCloseButtonComponent } from './snackbar-close-button.component';
+
+describe('SnackbarCloseButtonComponent', () => {
+	let component: SnackbarCloseButtonComponent;
+	let fixture: ComponentFixture<SnackbarCloseButtonComponent>;
+
+	const closeButton: string = getDataTestIdOf('snackbar-close-button');
+
+	beforeEach(async () => {
+		await TestBed.configureTestingModule({
+			declarations: [
+				MatIcon,
+				SnackbarCloseButtonComponent
+			]
+		}).compileComponents();
+	});
+
+	beforeEach(() => {
+		fixture = TestBed.createComponent(SnackbarCloseButtonComponent);
+		component = fixture.componentInstance;
+		component.close = { ...<any>mock(EventEmitter), emit: jest.fn() };
+		fixture.detectChanges();
+	});
+
+	it('should create', () => {
+		expect(component).toBeTruthy();
+	});
+
+	it('click should emit action', () => {
+		dispatchEventFromFixture(fixture, closeButton, 'click');
+
+		expect(component.close.emit).toHaveBeenCalled();
+	})
+});
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5c900fda5a90fde396aec8b66322c6e0fc2c28e9
--- /dev/null
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts
@@ -0,0 +1,11 @@
+import { Component, EventEmitter, Output } from '@angular/core';
+
+@Component({
+	selector: 'goofy-client-snackbar-close-button',
+	templateUrl: './snackbar-close-button.component.html',
+	styleUrls: ['./snackbar-close-button.component.scss']
+})
+export class SnackbarCloseButtonComponent {
+
+	@Output() close: EventEmitter<void> = new EventEmitter();
+}
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.html b/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.html
index c8c31801c567d84bb3da0905aaaf804bd5d15e57..1c87bdc69fac21eb254ec3b12845f862e50bb6cb 100644
--- a/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.html
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.html
@@ -1,7 +1,5 @@
 <div class="wrapper">
 	<span data-test-id="snackbar-message" class="message">{{ message }}</span>
 
-	<button mat-icon-button (click)="close()" data-test-id="snackbar-close-button">
-		<mat-icon data-test-class="icon">clear</mat-icon>
-	</button>
+	<goofy-client-snackbar-close-button (close)="close()"></goofy-client-snackbar-close-button>
 </div>
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts
index d0ead57221621e13aac4de1e9df89518b681e003..452e8208aff9c3aa5f9510af797dc2719f4b807b 100644
--- a/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts
@@ -3,6 +3,8 @@ import { MatIconModule } from '@angular/material/icon';
 import { MatSnackBarRef, MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar';
 import { mock } from '@goofy-client/test-utils';
 import { SnackBarData } from '@goofy-client/ui';
+import { MockComponent } from 'ng-mocks';
+import { SnackbarCloseButtonComponent } from '../snackbar-close-button/snackbar-close-button.component';
 import { SnackbarErrorComponent } from './snackbar-error.component';
 
 describe('SnackbarErrorComponent', () => {
@@ -18,7 +20,8 @@ describe('SnackbarErrorComponent', () => {
 				MatIconModule
 			],
 			declarations: [
-				SnackbarErrorComponent
+				SnackbarErrorComponent,
+				MockComponent(SnackbarCloseButtonComponent)
 			],
 			providers: [
 				{
@@ -42,4 +45,12 @@ describe('SnackbarErrorComponent', () => {
 	it('should create', () => {
 		expect(component).toBeTruthy();
 	});
+
+	describe('close button', () => {
+		it('should close the snackbar', () => {
+			component.close();
+
+			expect(snackBarRef.dismiss).toHaveBeenCalled();
+		})
+	})
 });
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html b/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html
index 5aefe84d96b0c8698f29084a2a58becac9a9a507..dae817d661748914e85446df69190ca1c0d3d6a2 100644
--- a/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html
@@ -7,6 +7,4 @@
 	Rückgängig
 </button>
 
-<button mat-icon-button (click)="close()" data-test-id="snackbar-close-button">
-	<mat-icon data-test-class="icon">clear</mat-icon>
-</button>
\ No newline at end of file
+<goofy-client-snackbar-close-button (close)="close()"></goofy-client-snackbar-close-button>
\ No newline at end of file
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts
index 7e295a2c20d40831dc026a57ae107af79a6af03d..cd8a3825c547c18f2ffb7f83f8efeec7754c7b65 100644
--- a/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts
@@ -4,6 +4,9 @@ import { MatSnackBarModule, MatSnackBarRef, MAT_SNACK_BAR_DATA } from '@angular/
 import { mock } from '@goofy-client/test-utils';
 import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel';
 import { createCommandResource } from 'libs/command-shared/test/command';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { MockComponent } from 'ng-mocks';
+import { SnackbarCloseButtonComponent } from '../snackbar-close-button/snackbar-close-button.component';
 import { SnackBarData } from '../snackbar.service';
 import { SnackbarInfoComponent } from './snackbar-info.component';
 
@@ -14,7 +17,7 @@ describe('SnackbarInfoComponent', () => {
 	const snackBarData: SnackBarData = { message: 'Message', commandResource: createCommandResource() };
 	const snackBarRef = { ...mock(MatSnackBarRef), dissmis: jest.fn(), dismissWithAction: jest.fn() };
 
-	const revokeButton: string = '[data-test-id="snackbar-revoke-button"]';
+	const revokeButton: string = getDataTestIdOf('snackbar-revoke-button');
 
 	beforeEach(async () => {
 		await TestBed.configureTestingModule({
@@ -22,7 +25,10 @@ describe('SnackbarInfoComponent', () => {
 				MatSnackBarModule,
 				MatIconModule
 			],
-			declarations: [SnackbarInfoComponent],
+			declarations: [
+				SnackbarInfoComponent,
+				MockComponent(SnackbarCloseButtonComponent)
+			],
 			providers: [
 				{
 					provide: MAT_SNACK_BAR_DATA,
@@ -46,7 +52,7 @@ describe('SnackbarInfoComponent', () => {
 		expect(component).toBeTruthy();
 	});
 
-	describe('clear button', () => {
+	describe('close button', () => {
 		it('should close the snackbar', () => {
 			component.close();
 
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts
index 29774c23c1fc4365593a112e30c3f871977cc930..9ae931738e196b19d43fd0158c48cc82ed5d2213 100644
--- a/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts
@@ -21,8 +21,8 @@ describe('SnackBarService', () => {
 	beforeEach(async () => {
 		await TestBed.configureTestingModule({
 			providers: [
-                { provide: MatSnackBar, useValue: mockMatSnackBar },
-            ],
+				{ provide: MatSnackBar, useValue: mockMatSnackBar },
+			],
 		}).compileComponents();
 		service = TestBed.inject(SnackBarService);
 		matSnackBar = TestBed.inject(MatSnackBar);
@@ -37,6 +37,13 @@ describe('SnackBarService', () => {
 		beforeEach(() => {
 			service.listenOnRevokeAction = jest.fn();
 			service.listenOnAfterDismissed = jest.fn();
+			service.closeSnackBarIfVisible = jest.fn();
+		})
+
+		it('should close snackbar if exists', () => {
+			service.show(commandResource, message);
+
+			expect(service.closeSnackBarIfVisible).toHaveBeenCalled();
 		})
 
 		it('should open from component', () => {
@@ -73,8 +80,16 @@ describe('SnackBarService', () => {
 
 		beforeEach(() => {
 			service.listenOnAfterDismissed = jest.fn();
+			service.closeSnackBarIfVisible = jest.fn();
 		})
 
+		it('should close snackbar if exists', () => {
+			service.showError(message);
+
+			expect(service.closeSnackBarIfVisible).toHaveBeenCalled();
+		})
+
+
 		it('should open from component', () => {
 			service.showError(message);
 
@@ -89,4 +104,27 @@ describe('SnackBarService', () => {
 			expect(service.listenOnAfterDismissed).toHaveBeenCalled();
 		})
 	})
+
+	describe('close snackbar if visible', () => {
+
+		beforeEach(() => {
+			service.closeSnackBar = jest.fn();
+		})
+
+		it('should dismiss snack bar if ref exists ', () => {
+			service.snackBarRef = <any>{};
+
+			service.closeSnackBarIfVisible();
+
+			expect(service.closeSnackBar).toHaveBeenCalled();
+		})
+
+		it('should do nothing if ref not exists ', () => {
+			service.snackBarRef = undefined;
+
+			service.closeSnackBarIfVisible();
+
+			expect(service.closeSnackBar).not.toHaveBeenCalled();
+		})
+	})
 })
diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.ts
index 6921eaba96738d7df1a2049512b7a93917ee9ee6..f91d60b7cf1522da9ab8f7a954bcb8d4f51aee76 100644
--- a/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.ts
+++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.ts
@@ -1,6 +1,7 @@
 import { Injectable } from '@angular/core';
 import { MatSnackBar, MatSnackBarRef } from '@angular/material/snack-bar';
 import { CommandResource, CommandStatus } from '@goofy-client/command-shared';
+import { isNotNil } from '@goofy-client/tech-shared';
 import { isNil } from 'lodash-es';
 import { Subscription } from 'rxjs';
 import { SnackbarErrorComponent } from './snackbar-error/snackbar-error.component';
@@ -10,12 +11,13 @@ import { SnackbarInfoComponent } from './snackbar-info/snackbar-info.component';
 export class SnackBarService {
 
 	private subscription: Subscription;
-	private snackBarRef: MatSnackBarRef<SnackbarInfoComponent | SnackbarErrorComponent>;
+	snackBarRef: MatSnackBarRef<SnackbarInfoComponent | SnackbarErrorComponent>;
 	private durationTime: number = 10000;
 
 	constructor(private snackBar: MatSnackBar) { }
 
 	public show(commandResource: CommandResource, message: string, revokeAction?: () => void): void {
+		this.closeSnackBarIfVisible();
 		if (commandResource.status === CommandStatus.ERROR) {
 			this.showError(message);
 		} else {
@@ -25,10 +27,15 @@ export class SnackBarService {
 	}
 
 	public showError(message: string): void {
+		this.closeSnackBarIfVisible();
 		this.snackBarRef = this.snackBar.openFromComponent(SnackbarErrorComponent, { data: { message }, duration: this.durationTime, panelClass: 'error' });
 		this.listenOnAfterDismissed();
 	}
 
+	closeSnackBarIfVisible() {
+		if (isNotNil(this.snackBarRef)) this.closeSnackBar();
+	}
+
 	private listenToActions(revokeAction: () => void): void {
 		this.listenOnAfterDismissed();
 		this.listenOnRevokeAction(revokeAction);
@@ -45,7 +52,7 @@ export class SnackBarService {
 		this.subscription = this.snackBarRef.afterDismissed().subscribe(() => this.closeSnackBar());
 	}
 
-	private closeSnackBar(): void {
+	closeSnackBar(): void {
 		this.snackBarRef.dismiss();
 		this.unsubscribe();
 	}
diff --git a/goofy-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html b/goofy-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html
index a55d8825a0d7c2ed79a65982b3f2ff5c4cf82981..5df4f31d06f208fdf8d4c19ba2202b046050b9ec 100644
--- a/goofy-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html
+++ b/goofy-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html
@@ -1,3 +1,3 @@
-<div class="progressbar-overlay" *ngIf="isVisible" data-test-class="progressbar-overlay">
-	<mat-progress-bar mode="indeterminate"></mat-progress-bar>
+<div *ngIf="isVisible" class="progressbar-overlay" data-test-class="progressbar-overlay">
+	<mat-progress-bar data-test-id="progress-bar" mode="indeterminate"></mat-progress-bar>
 </div>
diff --git a/goofy-client/libs/ui/src/lib/ui/ui.module.ts b/goofy-client/libs/ui/src/lib/ui/ui.module.ts
index 06404bf99418f9d86b3ce83af7c10e3d41e756f1..c482f7fc5c5248928f8c0ac3a5b03f48d66ed7fe 100644
--- a/goofy-client/libs/ui/src/lib/ui/ui.module.ts
+++ b/goofy-client/libs/ui/src/lib/ui/ui.module.ts
@@ -24,6 +24,7 @@ import { TechSharedModule } from '@goofy-client/tech-shared';
 import { de } from 'date-fns/locale';
 import { HttpConnectionTimeoutInterceptor } from '../interceptor/http-connection-timeout.interceptor';
 import { HttpErrorInterceptor } from '../interceptor/http-error.interceptor';
+import { SnackbarCloseButtonComponent } from '../snackbar/snackbar-close-button/snackbar-close-button.component';
 import { SnackbarErrorComponent } from '../snackbar/snackbar-error/snackbar-error.component';
 import { SnackbarInfoComponent } from '../snackbar/snackbar-info/snackbar-info.component';
 import { ButtonWithSpinnerComponent } from './button-with-spinner/button-with-spinner.component';
@@ -102,6 +103,7 @@ const modules = [
 		InternalServerErrorDialogComponent,
 		ConnectionTimeoutRetryDialogComponent,
 		ConnectionTimeoutRetryFailDialogComponent,
+		SnackbarCloseButtonComponent
 	],
 	imports: [
 		...modules
diff --git a/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html b/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html
index 97fc42277eea4729dd3fa51424713417da6a6027..9c2459d066398fccc76b6c80b675274ab1a1951c 100644
--- a/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html
+++ b/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html
@@ -12,17 +12,22 @@
 			</goofy-client-vorgang-detail-meta-data>
 		</mat-tab>
 		<mat-tab label="Datenrepräsentation ({{vorgangWithEingang.eingang.numberOfRepresentations}})"
-			[disabled]="!(vorgangWithEingang | hasLink:vorgangWithEingangLinkRel.REPRESENTATIONS)">
+			[disabled]="vorgangWithEingang | notHasLink:vorgangWithEingangLinkRel.REPRESENTATIONS">
 				<ng-template matTabContent>
 					<goofy-client-vorgang-detail-representation-list data-test-id="tab-representations-list" [vorgangWithEingang]="vorgangWithEingang"></goofy-client-vorgang-detail-representation-list>
 				</ng-template>
 		</mat-tab>
 		<mat-tab label="Anhänge ({{vorgangWithEingang.eingang.numberOfAttachments}})"
-			[disabled]="!(vorgangWithEingang | hasLink:vorgangWithEingangLinkRel.ATTACHMENTS)">
+			[disabled]="vorgangWithEingang | notHasLink:vorgangWithEingangLinkRel.ATTACHMENTS">
 				<ng-template matTabContent>
 					<goofy-client-vorgang-detail-attachment-list data-test-id="tab-attachments-list" [vorgangWithEingang]="vorgangWithEingang"></goofy-client-vorgang-detail-attachment-list>
 				</ng-template>
 		</mat-tab>
+		<mat-tab label="Historie" *ngIf="vorgangWithEingang | hasLink:vorgangWithEingangLinkRel.HISTORIE">
+				<ng-template matTabContent>
+					<goofy-client-vorgang-historie-container data-test-id="tab-historie-container" [vorgangWithEingang]="vorgangWithEingang"></goofy-client-vorgang-historie-container>
+				</ng-template>
+		</mat-tab>
 	</mat-tab-group>
 
 </goofy-client-expansion-panel>
diff --git a/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts b/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts
index 0511ec5727b1138a01d3327dddf91f25c386258d..a7694c5a1f8a67302f84f6cc55beb31caef24170 100644
--- a/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts
+++ b/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts
@@ -1,9 +1,10 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MatTabsModule } from '@angular/material/tabs';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { HasLinkPipe } from '@goofy-client/tech-shared';
+import { HasLinkPipe, NotHasLinkPipe } from '@goofy-client/tech-shared';
 import { getElementFromFixture } from '@goofy-client/test-utils';
 import { ExpansionPanelComponent } from '@goofy-client/ui';
+import { VorgangHistorieContainerComponent } from '@goofy-client/vorgang-historie';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@goofy-client/vorgang-shared';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
@@ -20,10 +21,12 @@ describe('VorgangDetailFormularDatenComponent', () => {
 	const tabMetaData: string = 'div[role=tab]:nth-child(2)';
 	const tabRepresentations: string = 'div[role=tab]:nth-child(3)';
 	const tabAttachments: string = 'div[role=tab]:nth-child(4)';
+	const tabHistorie: string = 'div[role=tab]:nth-child(5)';
 
 	const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource();
 	const vorgangWithAttachments: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ATTACHMENTS]);
 	const vorgangWithRepresentations: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.REPRESENTATIONS]);
+	const vorgangWithHistorie: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.HISTORIE]);
 
 	beforeEach(async () => {
 		await TestBed.configureTestingModule({
@@ -33,12 +36,14 @@ describe('VorgangDetailFormularDatenComponent', () => {
 			],
 			declarations: [
 				HasLinkPipe,
+				NotHasLinkPipe,
 				VorgangDetailFormularDatenComponent,
 				MockComponent(VorgangDetailAntragDataComponent),
 				MockComponent(VorgangDetailMetaDataComponent),
 				MockComponent(VorgangDetailAttachmentListComponent),
 				MockComponent(VorgangDetailRepresentationListComponent),
 				MockComponent(ExpansionPanelComponent),
+				MockComponent(VorgangHistorieContainerComponent),
 			]
 		}).compileComponents();
 	});
@@ -139,4 +144,24 @@ describe('VorgangDetailFormularDatenComponent', () => {
 		})
 	})
 
+	describe('Tab Historie', () => {
+		it('should be visible if Link "historie" exists', () => {
+			component.vorgangWithEingang = vorgangWithHistorie;
+
+			fixture.detectChanges();
+			const tab = getElementFromFixture(fixture, tabHistorie);
+
+			expect(tab).toBeInTheDocument();
+		})
+
+		it('should not be visible if no Link "historie"', () => {
+			component.vorgangWithEingang = vorgang;
+
+			fixture.detectChanges();
+			const tab = getElementFromFixture(fixture, tabHistorie);
+
+			expect(tab).not.toBeInTheDocument();
+		})
+	})
+
 });
diff --git a/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html b/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html
index 5e8ecaaa94dbfd9a031161240945412b77654320..d019a1ac5866afe7234426fd7c62d8f530898a10 100644
--- a/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html
+++ b/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html
@@ -11,4 +11,4 @@
 
 </ng-container>
 
-<goofy-client-progress-bar data-test-id="progress-bar" [stateResource]="revokeCommandStateResource$ | async"></goofy-client-progress-bar>
\ No newline at end of file
+<goofy-client-progress-bar [stateResource]="revokeCommandStateResource$ | async"></goofy-client-progress-bar>
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts b/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
index 4ea2a3fedfb8a38e50c2c0c1879bac72b8f830f6..fbb58cedeb0551ee16dbdaee75859f158ae3b8e6 100644
--- a/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
+++ b/goofy-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
@@ -10,6 +10,7 @@ import { TechSharedModule } from '@goofy-client/tech-shared';
 import { UiModule } from '@goofy-client/ui';
 import { UserProfileModule } from '@goofy-client/user-profile';
 import { UserProfileSharedModule } from '@goofy-client/user-profile-shared';
+import { VorgangHistorieModule } from '@goofy-client/vorgang-historie';
 import { VorgangSharedModule } from '@goofy-client/vorgang-shared';
 import { VorgangSharedUiModule } from '@goofy-client/vorgang-shared-ui';
 import { WiedervorlageModule } from '@goofy-client/wiedervorlage';
@@ -59,7 +60,8 @@ const routes: Routes = [
 		UserProfileModule,
 		UserProfileSharedModule,
 		PostfachSharedModule,
-		PostfachModule
+		PostfachModule,
+		VorgangHistorieModule
 	],
 	declarations: [
 		VorgangDetailPageComponent,
diff --git a/goofy-client/libs/vorgang-historie/.eslintrc.json b/goofy-client/libs/vorgang-historie/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..28f19b630511beab4ad3ff61ffce5a45f7430728
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/.eslintrc.json
@@ -0,0 +1,36 @@
+{
+	"extends": ["../../.eslintrc.json"],
+	"ignorePatterns": ["!**/*"],
+	"overrides": [
+		{
+			"files": ["*.ts"],
+			"extends": [
+				"plugin:@nrwl/nx/angular",
+				"plugin:@angular-eslint/template/process-inline-templates"
+			],
+			"rules": {
+				"@angular-eslint/directive-selector": [
+					"error",
+					{
+						"type": "attribute",
+						"prefix": "goofyClient",
+						"style": "camelCase"
+					}
+				],
+				"@angular-eslint/component-selector": [
+					"error",
+					{
+						"type": "element",
+						"prefix": "goofy-client",
+						"style": "kebab-case"
+					}
+				]
+			}
+		},
+		{
+			"files": ["*.html"],
+			"extends": ["plugin:@nrwl/nx/angular-template"],
+			"rules": {}
+		}
+	]
+}
diff --git a/goofy-client/libs/vorgang-historie/README.md b/goofy-client/libs/vorgang-historie/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0412a90d25be161803edbe2751e3635c48dcbc31
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/README.md
@@ -0,0 +1,7 @@
+# vorgang-historie
+
+This library was generated with [Nx](https://nx.dev).
+
+## Running unit tests
+
+Run `nx test vorgang-historie` to execute the unit tests.
diff --git a/goofy-client/libs/vorgang-historie/jest.config.js b/goofy-client/libs/vorgang-historie/jest.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..707cb488ad0a8db33a85c90c2fab768d9ecac3f5
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/jest.config.js
@@ -0,0 +1,21 @@
+module.exports = {
+	displayName: 'vorgang-historie',
+	preset: '../../jest.preset.js',
+	setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
+	globals: {
+		'ts-jest': {
+			tsconfig: '<rootDir>/tsconfig.spec.json',
+			stringifyContentPathRegex: '\\.(html|svg)$',
+		},
+	},
+	coverageDirectory: '../../coverage/libs/vorgang-historie',
+	transform: {
+		'^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular',
+	},
+	transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
+	snapshotSerializers: [
+		'jest-preset-angular/build/serializers/no-ng-attributes',
+		'jest-preset-angular/build/serializers/ng-snapshot',
+		'jest-preset-angular/build/serializers/html-comment',
+	],
+};
diff --git a/goofy-client/libs/vorgang-historie/src/index.ts b/goofy-client/libs/vorgang-historie/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..41a6b1400e8baf95216e1d8593b45b0b8faff17d
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/index.ts
@@ -0,0 +1,3 @@
+export * from './lib/vorgang-historie.module';
+
+export * from './lib/vorgang-historie-container/vorgang-historie-container.component';
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.html b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..429eccc43389cd64517c4b3bb1998f2ba7ca5037
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.html
@@ -0,0 +1 @@
+<goofy-client-vorgang-historie-list data-test-id="tab-historie-list-container" [vorgangWithEingang]="vorgangWithEingang"></goofy-client-vorgang-historie-list>
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.scss b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.spec.ts b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5fbc53485f39ab439b2bcff922b89ce61a04f872
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { VorgangHistorieContainerComponent } from './vorgang-historie-container.component';
+
+describe('VorgangHistorieContainerComponent', () => {
+	let component: VorgangHistorieContainerComponent;
+	let fixture: ComponentFixture<VorgangHistorieContainerComponent>;
+
+	beforeEach(async () => {
+		await TestBed.configureTestingModule({
+			declarations: [VorgangHistorieContainerComponent],
+		}).compileComponents();
+	});
+
+	beforeEach(() => {
+		fixture = TestBed.createComponent(VorgangHistorieContainerComponent);
+		component = fixture.componentInstance;
+		fixture.detectChanges();
+	});
+
+	it('should create', () => {
+		expect(component).toBeTruthy();
+	});
+});
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.ts b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7da65f22da2b3028a257b27b3826bfa7154d4461
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-container.component.ts
@@ -0,0 +1,13 @@
+import { Component, Input } from '@angular/core';
+import { VorgangWithEingangResource } from '@goofy-client/vorgang-shared';
+
+@Component({
+	selector: 'goofy-client-vorgang-historie-container',
+	templateUrl: './vorgang-historie-container.component.html',
+	styleUrls: ['./vorgang-historie-container.component.scss'],
+})
+export class VorgangHistorieContainerComponent {
+
+	@Input() vorgangWithEingang: VorgangWithEingangResource;
+
+}
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.html b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..4ffbccbc10733efb76f1ecaf553a57a727d43d2f
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.html
@@ -0,0 +1,3 @@
+<ul>
+	<li data-test-id="created-at">Der Vorgang wurde am {{ vorgangWithEingang.createdAt | formatDateWithTimePipe:false }} erstellt.</li>
+</ul>
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.scss b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..72a25c5cf822d4d8165725a12287832f6269080d
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.scss
@@ -0,0 +1,12 @@
+@import "variables";
+
+ul {
+	margin-top: 0;
+	padding-left: 0;
+	width: 100%;
+
+	li {
+		border-bottom: 1px solid $greyLight;
+		padding: 0.75rem 0;
+	}
+}
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.spec.ts b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1908346811cd19a353c854de26805f98f5ad4073
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.spec.ts
@@ -0,0 +1,48 @@
+import { registerLocaleData } from '@angular/common';
+import localeDe from '@angular/common/locales/de';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormatDateWithTimePipe } from '@goofy-client/tech-shared';
+import { getElementFromFixture } from '@goofy-client/test-utils';
+import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@goofy-client/vorgang-shared';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
+import { VorgangHistorieListComponent } from './vorgang-historie-list.component';
+
+registerLocaleData(localeDe);
+
+describe('VorgangHistorieListComponent', () => {
+	let component: VorgangHistorieListComponent;
+	let fixture: ComponentFixture<VorgangHistorieListComponent>;
+
+	const vorgangWithHistorie: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.HISTORIE]);
+	const createdAtElement: string = getDataTestIdOf('created-at');
+
+	beforeEach(async () => {
+		await TestBed.configureTestingModule({
+			declarations: [
+				FormatDateWithTimePipe,
+				VorgangHistorieListComponent
+			],
+		}).compileComponents();
+	});
+
+	beforeEach(() => {
+		fixture = TestBed.createComponent(VorgangHistorieListComponent);
+		component = fixture.componentInstance;
+		component.vorgangWithEingang = vorgangWithHistorie;
+		fixture.detectChanges();
+	});
+
+	it('should create', () => {
+		expect(component).toBeTruthy();
+	});
+
+	describe('on vorgang', () => {
+
+		it('should have Historie list', () => {
+			const element = getElementFromFixture(fixture, createdAtElement);
+
+			expect(element).toBeInstanceOf(HTMLLIElement);
+		});
+	});
+});
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.ts b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bd015726a6fe0a1979b9fdd5d83bff0d87d72670
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component.ts
@@ -0,0 +1,13 @@
+import { Component, Input } from '@angular/core';
+import { VorgangWithEingangResource } from '@goofy-client/vorgang-shared';
+
+@Component({
+	selector: 'goofy-client-vorgang-historie-list',
+	templateUrl: './vorgang-historie-list.component.html',
+	styleUrls: ['./vorgang-historie-list.component.scss'],
+})
+export class VorgangHistorieListComponent {
+
+	@Input() vorgangWithEingang: VorgangWithEingangResource;
+
+}
diff --git a/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie.module.ts b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..41f06719072483d05854a282803e6dc699e8f779
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/lib/vorgang-historie.module.ts
@@ -0,0 +1,20 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { TechSharedModule } from '@goofy-client/tech-shared';
+import { VorgangHistorieContainerComponent } from './vorgang-historie-container/vorgang-historie-container.component';
+import { VorgangHistorieListComponent } from './vorgang-historie-container/vorgang-historie-list/vorgang-historie-list.component';
+
+@NgModule({
+	imports: [
+		CommonModule,
+		TechSharedModule
+	],
+	declarations: [
+		VorgangHistorieContainerComponent,
+		VorgangHistorieListComponent,
+	],
+	exports: [
+		VorgangHistorieContainerComponent,
+	],
+})
+export class VorgangHistorieModule {}
diff --git a/goofy-client/libs/vorgang-historie/src/test-setup.ts b/goofy-client/libs/vorgang-historie/src/test-setup.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1100b3e8a6ed08f4b5c27a96471846d57023c320
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/src/test-setup.ts
@@ -0,0 +1 @@
+import 'jest-preset-angular/setup-jest';
diff --git a/goofy-client/libs/vorgang-historie/tsconfig.json b/goofy-client/libs/vorgang-historie/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..518abe89089dd06c8c6430da3f5f7c9105c10cd2
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/tsconfig.json
@@ -0,0 +1,13 @@
+{
+	"extends": "../../tsconfig.base.json",
+	"files": [],
+	"include": [],
+	"references": [
+		{
+			"path": "./tsconfig.lib.json"
+		},
+		{
+			"path": "./tsconfig.spec.json"
+		}
+	]
+}
diff --git a/goofy-client/libs/vorgang-historie/tsconfig.lib.json b/goofy-client/libs/vorgang-historie/tsconfig.lib.json
new file mode 100644
index 0000000000000000000000000000000000000000..a2a53880f8274e73d8c264e347047cbd8c1f1cf8
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/tsconfig.lib.json
@@ -0,0 +1,12 @@
+{
+	"extends": "./tsconfig.json",
+	"compilerOptions": {
+		"outDir": "../../dist/out-tsc",
+		"declaration": true,
+		"declarationMap": true,
+		"inlineSources": true,
+		"types": []
+	},
+	"exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts"],
+	"include": ["**/*.ts"]
+}
diff --git a/goofy-client/libs/vorgang-historie/tsconfig.spec.json b/goofy-client/libs/vorgang-historie/tsconfig.spec.json
new file mode 100644
index 0000000000000000000000000000000000000000..ff36e0edd33bbc39279480063c3c8e62e8be27ef
--- /dev/null
+++ b/goofy-client/libs/vorgang-historie/tsconfig.spec.json
@@ -0,0 +1,10 @@
+{
+	"extends": "./tsconfig.json",
+	"compilerOptions": {
+		"outDir": "../../dist/out-tsc",
+		"module": "commonjs",
+		"types": ["jest", "node"]
+	},
+	"files": ["src/test-setup.ts"],
+	"include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
+}
diff --git a/goofy-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts b/goofy-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
index aa3c06d5f237beb44245203e769956ba7a26d298..0f7f646640c7cff4edebda7b522e51b1c286e786 100644
--- a/goofy-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
+++ b/goofy-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
@@ -28,4 +28,5 @@ export enum VorgangWithEingangLinkRel {
 	PENDING_COMMANDS = 'pending-commands',
 	ASSIGN = 'assign',
 	REPRESENTATIONS = 'representations',
+	HISTORIE = 'historie',
 }
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.html b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c244b2559d54624b7c16b7a010ecbef0eddeaa41
--- /dev/null
+++ b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.html
@@ -0,0 +1 @@
+<goofy-client-vorgang-list-page [apiRootStateResource]="apiRootStateResource$ | async"></goofy-client-vorgang-list-page>
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.scss b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.spec.ts b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5151bc413161b0ac0029b4efdcb2be2eca0928b8
--- /dev/null
+++ b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.spec.ts
@@ -0,0 +1,45 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ApiRootService } from '@goofy-client/api-root-shared';
+import { mock } from '@goofy-client/test-utils';
+import { MockComponent } from 'ng-mocks';
+import { VorgangListPageComponent } from '../vorgang-list-page/vorgang-list-page.component';
+import { VorgangListPageContainerComponent } from './vorgang-list-page-container.component';
+
+describe('VorgangListPageContainerComponent', () => {
+	let component: VorgangListPageContainerComponent;
+	let fixture: ComponentFixture<VorgangListPageContainerComponent>;
+
+	const apiRootService = mock(ApiRootService);
+
+	beforeEach(async () => {
+		await TestBed.configureTestingModule({
+			declarations: [
+				VorgangListPageContainerComponent,
+				MockComponent(VorgangListPageComponent)
+			],
+			providers: [{
+				provide: ApiRootService,
+				useValue: apiRootService
+			}]
+		}).compileComponents();
+	});
+
+	beforeEach(() => {
+		fixture = TestBed.createComponent(VorgangListPageContainerComponent);
+		component = fixture.componentInstance;
+		fixture.detectChanges();
+	});
+
+	it('should create', () => {
+		expect(component).toBeTruthy();
+	});
+
+	describe('onInit', () => {
+
+		it('should call apiRootService', () => {
+			component.ngOnInit();
+
+			expect(apiRootService.getApiRoot).toHaveBeenCalled();
+		})
+	})
+});
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.ts b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ecc0ea6837efe767b36e46c08a73ee662d041fc1
--- /dev/null
+++ b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.ts
@@ -0,0 +1,20 @@
+import { Component, OnInit } from '@angular/core';
+import { ApiRootResource, ApiRootService } from '@goofy-client/api-root-shared';
+import { StateResource } from '@goofy-client/tech-shared';
+import { Observable } from 'rxjs';
+
+@Component({
+	selector: 'goofy-client-vorgang-list-page-container',
+	templateUrl: './vorgang-list-page-container.component.html',
+	styleUrls: ['./vorgang-list-page-container.component.scss'],
+})
+export class VorgangListPageContainerComponent implements OnInit {
+
+	apiRootStateResource$: Observable<StateResource<ApiRootResource>>;
+
+	constructor(private apiRootService: ApiRootService) { }
+
+	ngOnInit(): void {
+		this.apiRootStateResource$ = this.apiRootService.getApiRoot();
+	}
+}
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.html b/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.html
index 2bf1a8ddb3fa9fe14514a55299a3034ef1045f33..bafd229827f85b6d530d8b78e524e068ddfccd90 100644
--- a/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.html
+++ b/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.html
@@ -1,2 +1,6 @@
 <goofy-client-subnavigation class="mat-app-background"></goofy-client-subnavigation>
-<goofy-client-vorgang-list-container></goofy-client-vorgang-list-container>
+
+<goofy-client-vorgang-list-container *ngIf="apiRootStateResource?.resource | hasLink: apiRootLinkRel.VORGAENGE; else showNoRoleMessage" data-test-id="vorgaenge-list"></goofy-client-vorgang-list-container>
+<ng-template #showNoRoleMessage>
+	<h1 data-test-id="user-no-role-message">Die Allgemeine Fachanwendung ist wegen fehlender Rollen nicht benutzbar.</h1>
+</ng-template>
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.scss b/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.scss
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1f8ba303033ec012306500158c50e3a082bc3ab0 100644
--- a/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.scss
+++ b/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.scss
@@ -0,0 +1,13 @@
+@import "variables";
+
+h1 {
+	text-align: center;
+	margin: 0;
+	padding: 1rem;
+}
+
+:host-context(.dark) {
+	h1 {
+		background-color: $dark-background;
+	}
+}
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.spec.ts b/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.spec.ts
index 1548673e95fbf1a263d7a20160f9ff5403b8ec56..95184f30ba5b5314c55717c5969569c6bb2af316 100644
--- a/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.spec.ts
+++ b/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.spec.ts
@@ -1,18 +1,28 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { VorgangListPageComponent } from './vorgang-list-page.component';
-import { MockComponent } from 'ng-mocks';
-import { SubnavigationComponent } from 'libs/ui/src/lib/ui/subnavigation/subnavigation.component';
+import { ApiRootLinkRel } from '@goofy-client/api-root-shared';
+import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@goofy-client/tech-shared';
+import { getElementFromFixture } from '@goofy-client/test-utils';
+import { SpinnerComponent } from '@goofy-client/ui';
 import { VorgangListContainerComponent } from '@goofy-client/vorgang';
+import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { SubnavigationComponent } from 'libs/ui/src/lib/ui/subnavigation/subnavigation.component';
+import { MockComponent } from 'ng-mocks';
+import { VorgangListPageComponent } from './vorgang-list-page.component';
 
 describe('VorgangListPageComponent', () => {
 	let component: VorgangListPageComponent;
 	let fixture: ComponentFixture<VorgangListPageComponent>;
 
+	const userMessage: string = getDataTestIdOf('user-no-role-message');
+	const vorgaengeList: string = getDataTestIdOf('vorgaenge-list');
+
 	beforeEach(async () => {
 		await TestBed.configureTestingModule({
 			declarations: [
 				VorgangListPageComponent,
+				HasLinkPipe,
+				MockComponent(SpinnerComponent),
 				MockComponent(SubnavigationComponent),
 				MockComponent(VorgangListContainerComponent)
 			]
@@ -23,10 +33,32 @@ describe('VorgangListPageComponent', () => {
 	beforeEach(() => {
 		fixture = TestBed.createComponent(VorgangListPageComponent);
 		component = fixture.componentInstance;
+		component.apiRootStateResource = createEmptyStateResource();
 		fixture.detectChanges();
 	});
 
 	it('should create', () => {
 		expect(component).toBeTruthy();
 	});
+
+	describe('page', () => {
+
+		it('should show vorgaenge if link exists', () => {
+			component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.VORGAENGE]));
+			fixture.detectChanges();
+
+			const element = getElementFromFixture(fixture, vorgaengeList);
+
+			expect(element).toBeInstanceOf(HTMLElement);
+		})
+
+		it('should show hint message if link not exists', () => {
+			component.apiRootStateResource = createStateResource(createApiRootResource());
+			fixture.detectChanges();
+
+			const element = getElementFromFixture(fixture, userMessage);
+
+			expect(element).toBeInstanceOf(HTMLElement);
+		})
+	})
 });
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.ts b/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.ts
index 1f16539089f801cd3d44329020eb290556386ad0..cfe7072d4a20ee7601805bac22084ed1dd197ec2 100644
--- a/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.ts
+++ b/goofy-client/libs/vorgang/src/lib/vorgang-list-page/vorgang-list-page.component.ts
@@ -1,8 +1,16 @@
-import { Component } from '@angular/core';
+import { Component, Input } from '@angular/core';
+import { ApiRootLinkRel, ApiRootResource } from '@goofy-client/api-root-shared';
+import { StateResource } from '@goofy-client/tech-shared';
 
+//TODO unter vorgang-list-page-container schieben
 @Component({
 	selector: 'goofy-client-vorgang-list-page',
 	templateUrl: './vorgang-list-page.component.html',
 	styleUrls: ['./vorgang-list-page.component.scss']
 })
-export class VorgangListPageComponent { }
+export class VorgangListPageComponent {
+
+	@Input() apiRootStateResource: StateResource<ApiRootResource>;
+
+	readonly apiRootLinkRel = ApiRootLinkRel;
+}
\ No newline at end of file
diff --git a/goofy-client/libs/vorgang/src/lib/vorgang.module.ts b/goofy-client/libs/vorgang/src/lib/vorgang.module.ts
index c300d818a54cdef72982b58b86d7278425a3f905..b9587df7dfb040efd4e874db0a8253fa217109ac 100644
--- a/goofy-client/libs/vorgang/src/lib/vorgang.module.ts
+++ b/goofy-client/libs/vorgang/src/lib/vorgang.module.ts
@@ -13,29 +13,30 @@ import { EmptyListComponent } from './vorgang-list-container/vorgang-list/empty-
 import { VorgangListItemComponent } from './vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component';
 import { VorgangNextFristButton } from './vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component';
 import { VorgangListComponent } from './vorgang-list-container/vorgang-list/vorgang-list.component';
+import { VorgangListPageContainerComponent } from './vorgang-list-page-container/vorgang-list-page-container.component';
 import { VorgangListPageComponent } from './vorgang-list-page/vorgang-list-page.component';
 
 const routes: Routes = [
 	{
 		path: '',
-		component: VorgangListPageComponent
+		component: VorgangListPageContainerComponent,
 	},
 	{
 		path: 'search/:search',
-		component: VorgangListPageComponent
+		component: VorgangListPageContainerComponent,
 	},
 	{
 		path: 'myVorgaenge',
-		component: VorgangListPageComponent
+		component: VorgangListPageContainerComponent,
 	},
 	{
 		path: 'myVorgaenge/search/:search',
-		component: VorgangListPageComponent
+		component: VorgangListPageContainerComponent,
 	},
 	{
 		path: 'vorgang/:vorgangWithEingangUrl',
-		loadChildren: () => import('@goofy-client/vorgang-detail').then(m => m.VorgangDetailModule)
-	}
+		loadChildren: () => import('@goofy-client/vorgang-detail').then(m => m.VorgangDetailModule),
+	},
 ];
 
 @NgModule({
@@ -48,7 +49,7 @@ const routes: Routes = [
 		VorgangSharedModule,
 		WiedervorlageModule,
 		VorgangSharedUiModule,
-		UserProfileModule
+		UserProfileModule,
 	],
 	declarations: [
 		VorgangListComponent,
@@ -56,7 +57,8 @@ const routes: Routes = [
 		VorgangListContainerComponent,
 		VorgangListPageComponent,
 		EmptyListComponent,
-		VorgangNextFristButton
-	]
+		VorgangNextFristButton,
+		VorgangListPageContainerComponent
+	],
 })
 export class VorgangModule { }
diff --git a/goofy-client/tsconfig.base.json b/goofy-client/tsconfig.base.json
index b68afb258404cae674d402b8eb66078fa7beab24..b077313028be1be67cf372d6f755f0cf1e126102 100644
--- a/goofy-client/tsconfig.base.json
+++ b/goofy-client/tsconfig.base.json
@@ -54,6 +54,9 @@
 			"@goofy-client/vorgang-detail": [
 				"libs/vorgang-detail/src/index.ts"
 			],
+			"@goofy-client/vorgang-historie": [
+				"libs/vorgang-historie/src/index.ts"
+			],
 			"@goofy-client/vorgang-shared": [
 				"libs/vorgang-shared/src/index.ts"
 			],
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/JwtTokenUtil.java b/goofy-server/src/main/java/de/itvsh/goofy/JwtTokenUtil.java
index 35ff2b41ccd56e82d7f8a2875b075e34d57f9a1f..b7aa89a51b628a94be544ca6467b7976dc8e7f35 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/JwtTokenUtil.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/JwtTokenUtil.java
@@ -1,6 +1,7 @@
 package de.itvsh.goofy;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -34,6 +35,7 @@ public class JwtTokenUtil {
 	public static final String FIRSTNAME_CLAIM = "firstName";
 	public static final String LASTNAME_CLAIM = "lastName";
 	public static final String FILEID_CLAIM = "fileId";
+	public static final String ORGANSIATIONSEINHEIT_IDS_CLAIM = "organisationseinheitIds";
 
 	@Autowired
 	private DownloadTokenProperties downloadTokenProperties;
@@ -72,12 +74,25 @@ public class JwtTokenUtil {
 				.toList();
 	}
 
+	@SuppressWarnings({ "unchecked" })
+	public Collection<String> getOrganisationseinheitIdsFromToken(String token) {
+		List<String> organisationseinheitIds = new ArrayList<>();
+		getAllClaimsFromToken(token)
+				.ifPresent(claims -> {
+					if (claims.get(ORGANSIATIONSEINHEIT_IDS_CLAIM) != null) {
+						organisationseinheitIds.addAll((Collection<String>) claims.get(ORGANSIATIONSEINHEIT_IDS_CLAIM));
+					}
+				});
+		return organisationseinheitIds;
+	}
+
 	public String generateToken(FileId fileId, GoofyUser user) {
 		var claims = new HashMap<String, Object>();
 		claims.put(FIRSTNAME_CLAIM, user.getFirstName());
 		claims.put(LASTNAME_CLAIM, user.getLastName());
 		claims.put(ROLE_CLAIM, user.getAuthorities());
 		claims.put(FILEID_CLAIM, fileId.toString());
+		claims.put(ORGANSIATIONSEINHEIT_IDS_CLAIM, user.getOrganisationseinheitIds());
 
 		return doGenerateToken(claims, user.getId().toString());
 	}
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/RootController.java b/goofy-server/src/main/java/de/itvsh/goofy/RootController.java
index f931023a603f2803a7b465cfc7a6c93181f676a7..f394e86ca7234a76fca635adbb013a6558f16aed 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/RootController.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/RootController.java
@@ -18,6 +18,7 @@ import de.itvsh.goofy.common.downloadtoken.DownloadTokenController;
 import de.itvsh.goofy.common.user.CurrentUserService;
 import de.itvsh.goofy.common.user.UserId;
 import de.itvsh.goofy.common.user.UserProfileController;
+import de.itvsh.goofy.common.user.UserRole;
 import de.itvsh.goofy.vorgang.VorgangController;
 
 @RestController
@@ -39,16 +40,23 @@ public class RootController {
 	@GetMapping
 	public EntityModel<RootResource> getRootResource() {
 		return ModelBuilder.fromEntity(new RootResource())
-				.addLink(linkTo(RootController.class).withSelfRel())
-				.addLink(linkTo(VorgangController.class).withRel(REL_VORGAENGE))
-				.addLink(linkTo(methodOn(UserProfileController.class).findUsers(null)).withRel(REL_SEARCH_USER))
-				.addLink(linkTo(DownloadTokenController.class).withRel(REL_DOWNLOAD_TOKEN))
-				.addLink(buildVorgangListByPageLink(REL_SEARCH, Optional.empty()))
-				.addLink(buildVorgangListByPageLink(REL_MY_VORGAENGE, Optional.of(currentUserService.getUserId())))
-				.addLink(buildVorgangListByPageLink(REL_SEARCH_MY_VORGAENGE, Optional.of(currentUserService.getUserId())))
+				.ifMatch(this::hasRole).addLinks(
+						linkTo(RootController.class).withSelfRel(),
+						linkTo(VorgangController.class).withRel(REL_VORGAENGE),
+						linkTo(methodOn(UserProfileController.class).findUsers(null)).withRel(REL_SEARCH_USER),
+						linkTo(DownloadTokenController.class).withRel(REL_DOWNLOAD_TOKEN),
+						buildVorgangListByPageLink(REL_SEARCH, Optional.empty()),
+						buildVorgangListByPageLink(REL_MY_VORGAENGE, Optional.of(currentUserService.getUserId())),
+						buildVorgangListByPageLink(REL_SEARCH_MY_VORGAENGE, Optional.of(currentUserService.getUserId())))
 				.buildModel();
 	}
 
+	private boolean hasRole() {
+		return currentUserService.hasRole(UserRole.VERWALTUNG_USER)
+				|| currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE)
+				|| currentUserService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER);
+	}
+
 	private Link buildVorgangListByPageLink(String linkRel, Optional<UserId> assignedTo) {
 		return linkTo(methodOn(VorgangController.class).getVorgangListByPage(0, null, null, assignedTo)).withRel(linkRel);
 	}
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/callcontext/ContextService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/callcontext/ContextService.java
index b2b4e4291127c2754b88a8e120c8d190c5f90686..b80ba70fc1822726303a3e23551f91825e0758ee 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/callcontext/ContextService.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/callcontext/ContextService.java
@@ -29,7 +29,7 @@ public class ContextService {
 	static final String KEY_CLIENT_NAME = "CLIENT_NAME-bin";
 	static final String KEY_REQUEST_ID = "REQUEST_ID-bin";
 	static final String KEY_ACCESS_LIMITED_ORGAID = "ACCESS_LIMITED_TO_ORGANISATORISCHEEINHEITENID-bin";
-	static final String KEY_ORGAID_CHECK_NECESSARY = "ORGANISATION_EINHEITEN_ID_CHECK_NECESSARY-bin";
+	static final String KEY_ACCESS_LIMITED = "ACCESS_LIMITED-bin";
 
 	@Autowired
 	private ApplicationContext context;
@@ -79,14 +79,16 @@ public class ContextService {
 				.ifPresentOrElse(bytes -> metadata.put(createKeyOf(KEY_CLIENT_NAME), bytes), () -> LOG.warn("Missing value 'client name'"));
 		user.getOrganisationseinheitIds().stream().map(String::getBytes)
 				.forEach(bytes -> metadata.put(createKeyOf(KEY_ACCESS_LIMITED_ORGAID), bytes));
-		metadata.put(createKeyOf(KEY_ORGAID_CHECK_NECESSARY), isOrganisationEinheitenIdCheckNecessary());
+		metadata.put(createKeyOf(KEY_ACCESS_LIMITED), isOrganisationEinheitenIdCheckNecessary());
 
 		return metadata;
 	}
 
 	private byte[] isOrganisationEinheitenIdCheckNecessary() {
-		Boolean doOrgaIdCheck = !userService.hasRole(UserRole.VERWALTUNG_POSTSTELLE);
-		return doOrgaIdCheck.toString().getBytes();
+		var hasRoleWithNoCheckNecessary = userService.hasRole(UserRole.VERWALTUNG_POSTSTELLE)
+				|| userService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER);
+
+		return Boolean.toString(!hasRoleWithNoCheckNecessary).getBytes();
 	}
 
 	private String formatListAsCommaSeperatedString(Collection<String> organisatorischeEinheitenIds) {
diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenService.java
index dd9ac1f05e25b5cba1a7ad46ea1bfd26bc6a68fd..db648fe5fc4c96181e89351bfd6d391b9b241762 100644
--- a/goofy-server/src/main/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenService.java
+++ b/goofy-server/src/main/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenService.java
@@ -18,8 +18,8 @@ import com.auth0.jwt.exceptions.JWTVerificationException;
 
 import de.itvsh.goofy.JwtTokenUtil;
 import de.itvsh.goofy.common.binaryfile.DownloadGoofyUser;
-import de.itvsh.goofy.common.binaryfile.FileId;
 import de.itvsh.goofy.common.binaryfile.DownloadGoofyUser.DownloadGoofyUserBuilder;
+import de.itvsh.goofy.common.binaryfile.FileId;
 import de.itvsh.goofy.common.user.CurrentUserService;
 import de.itvsh.goofy.common.user.GoofyUser;
 import de.itvsh.kop.common.errorhandling.TechnicalException;
@@ -70,7 +70,8 @@ class DownloadTokenService {
 				GoofyUser.builder()
 						.firstName(claims.get(FIRSTNAME_CLAIM, String.class))
 						.lastName(claims.get(LASTNAME_CLAIM, String.class))
-						.authorities(jwtTokenUtil.getRolesFromToken(token)).build())
+						.authorities(jwtTokenUtil.getRolesFromToken(token))
+						.organisationseinheitIds(jwtTokenUtil.getOrganisationseinheitIdsFromToken(token)).build())
 				.fileId(FileId.from(claims.get(FILEID_CLAIM, String.class))));
 
 		return downloadUserBuilder.build();
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/JwtTokenUtilTest.java b/goofy-server/src/test/java/de/itvsh/goofy/JwtTokenUtilTest.java
index 61548e5b6a4d7230b09465260f68ecc7dedf5702..21872772831a98e4addae01feaf3073624b3e7d8 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/JwtTokenUtilTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/JwtTokenUtilTest.java
@@ -6,6 +6,7 @@ import static org.mockito.Mockito.*;
 
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
@@ -72,6 +73,13 @@ class JwtTokenUtilTest {
 			assertThat(expirationDate).isAfter(before).isBefore(after);
 		}
 
+		@Test
+		void organisationseinheitIds() {
+			var organisationseinheitIds = jwtTokenUtil.getOrganisationseinheitIdsFromToken(generatedToken);
+
+			assertThat(organisationseinheitIds).isEqualTo(List.of(UserTestFactory.ORGANISATORISCHE_EINHEITEN_ID));
+		}
+
 		private Claims getParsedBody() {
 			return Jwts.parser().setSigningKey(TOKEN_SECRET.getBytes()).parseClaimsJws(generatedToken).getBody();
 		}
@@ -107,6 +115,7 @@ class JwtTokenUtilTest {
 			claims.put(JwtTokenUtil.LASTNAME_CLAIM, SecurityTestFactory.USER_LASTNAME);
 			claims.put(JwtTokenUtil.ROLE_CLAIM, SecurityTestFactory.AUTHORITIES);
 			claims.put(JwtTokenUtil.FILEID_CLAIM, FileId.createNew());
+			claims.put(JwtTokenUtil.ORGANSIATIONSEINHEIT_IDS_CLAIM, SecurityTestFactory.ORGANSIATIONSEINHEIT_IDS);
 
 			return Jwts.builder()
 					.setClaims(claims)
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java
index db4a5b8c67f1dab678a0733decd25231ad7f9c8b..778e0dc261ca83baefff24df794e4e346fb7c403 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java
@@ -1,6 +1,6 @@
 package de.itvsh.goofy;
 
-import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@@ -9,6 +9,7 @@ import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
@@ -20,6 +21,8 @@ import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.ResultActions;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
+import static org.assertj.core.api.Assertions.*;
+
 import de.itvsh.goofy.common.user.CurrentUserService;
 import de.itvsh.goofy.common.user.UserTestFactory;
 
@@ -43,62 +46,90 @@ class RootControllerTest {
 		when(currentUserService.getUserId()).thenReturn(UserTestFactory.ID);
 	}
 
+	@DisplayName("Links for user")
 	@Nested
 	class TestLinks {
 
-		@Test
-		void shouldHaveSelfLink() {
-			var model = controller.getRootResource();
+		@DisplayName("with any role")
+		@Nested
+		class TestWithAnyRole {
 
-			assertThat(model.getLink(IanaLinkRelations.SELF)).isPresent();
-		}
+			@BeforeEach
+			void mockCurrentUserService() {
+				when(currentUserService.hasRole(anyString())).thenReturn(true);
+			}
 
-		@Test
-		void shouldHaveLinkToVorgangList() {
-			var model = controller.getRootResource();
+			@Test
+			void shouldHaveSelfLink() {
+				var model = controller.getRootResource();
 
-			assertThat(model.getLink(RootController.REL_VORGAENGE)).isPresent().get()
-					.extracting(Link::getHref).isEqualTo("/api/vorgangs");
-		}
+				assertThat(model.getLink(IanaLinkRelations.SELF)).isPresent();
+			}
 
-		@Test
-		void shouldHaveSearchLinkWithLimit() {
-			var model = controller.getRootResource();
+			@Test
+			void shouldHaveLinkToVorgangList() {
+				var model = controller.getRootResource();
 
-			assertThat(model.getLink(RootController.REL_SEARCH)).isPresent().get()
-					.extracting(Link::getHref).isEqualTo("/api/vorgangs?page=0{&searchBy,limit,assignedTo}");
-		}
+				assertThat(model.getLink(RootController.REL_VORGAENGE)).isPresent().get()
+						.extracting(Link::getHref).isEqualTo("/api/vorgangs");
+			}
 
-		@Test
-		void shouldHaveSearchUserLink() {
-			var model = controller.getRootResource();
+			@Test
+			void shouldHaveSearchLinkWithLimit() {
+				var model = controller.getRootResource();
 
-			assertThat(model.getLink(RootController.REL_SEARCH_USER)).isPresent().get().extracting(Link::getHref)
-					.isEqualTo("/api/userProfiles?searchBy={searchBy}");
-		}
+				assertThat(model.getLink(RootController.REL_SEARCH)).isPresent().get()
+						.extracting(Link::getHref).isEqualTo("/api/vorgangs?page=0{&searchBy,limit,assignedTo}");
+			}
 
-		@Test
-		void shoulHaveMyVorgaengeLink() {
-			var model = controller.getRootResource();
+			@Test
+			void shouldHaveSearchUserLink() {
+				var model = controller.getRootResource();
 
-			assertThat(model.getLink(RootController.REL_MY_VORGAENGE)).isPresent().get().extracting(Link::getHref)
-					.isEqualTo("/api/vorgangs?page=0&assignedTo=" + UserTestFactory.ID.toString() + "{&searchBy,limit}");
-		}
+				assertThat(model.getLink(RootController.REL_SEARCH_USER)).isPresent().get().extracting(Link::getHref)
+						.isEqualTo("/api/userProfiles?searchBy={searchBy}");
+			}
+
+			@Test
+			void shoulHaveMyVorgaengeLink() {
+				var model = controller.getRootResource();
+
+				assertThat(model.getLink(RootController.REL_MY_VORGAENGE)).isPresent().get().extracting(Link::getHref)
+						.isEqualTo("/api/vorgangs?page=0&assignedTo=" + UserTestFactory.ID.toString() + "{&searchBy,limit}");
+			}
+
+			@Test
+			void shoulHaveSearchMyVorgaengeLink() {
+				var model = controller.getRootResource();
 
-		@Test
-		void shoulHaveSearchMyVorgaengeLink() {
-			var model = controller.getRootResource();
+				assertThat(model.getLink(RootController.REL_SEARCH_MY_VORGAENGE)).isPresent().get().extracting(Link::getHref)
+						.isEqualTo("/api/vorgangs?page=0&assignedTo=" + UserTestFactory.ID.toString() + "{&searchBy,limit}");
+			}
 
-			assertThat(model.getLink(RootController.REL_SEARCH_MY_VORGAENGE)).isPresent().get().extracting(Link::getHref)
-					.isEqualTo("/api/vorgangs?page=0&assignedTo=" + UserTestFactory.ID.toString() + "{&searchBy,limit}");
+			@Test
+			void shoulHaveDownloadTokenLink() {
+				var model = controller.getRootResource();
+
+				assertThat(model.getLink(RootController.REL_DOWNLOAD_TOKEN)).isPresent().get().extracting(Link::getHref)
+						.isEqualTo("/api/downloadtoken");
+			}
 		}
 
-		@Test
-		void shoulHaveDownloadTokenLink() {
-			var model = controller.getRootResource();
+		@DisplayName("with no role")
+		@Nested
+		class TestWithNoRole {
+
+			@BeforeEach
+			void mockCurrentUserService() {
+				when(currentUserService.hasRole(anyString())).thenReturn(false);
+			}
+
+			@Test
+			void shouldHaveNoLinkAtAll() {
+				var model = controller.getRootResource();
 
-			assertThat(model.getLink(RootController.REL_DOWNLOAD_TOKEN)).isPresent().get().extracting(Link::getHref)
-					.isEqualTo("/api/downloadtoken");
+				assertThat(model.getLinks()).isEmpty();
+			}
 		}
 	}
 
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/SecurityTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/SecurityTestFactory.java
index 68298120a8b3c8725f65488b6849f024a2fe0f38..50885feffbd1c88f245154f41d16db71bafec558 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/SecurityTestFactory.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/SecurityTestFactory.java
@@ -1,6 +1,7 @@
 package de.itvsh.goofy;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
@@ -14,4 +15,5 @@ public class SecurityTestFactory {
 	static final String USER_LASTNAME = "Tester";
 	static final String ROLE = "Testrolle";
 	static final List<SimpleGrantedAuthority> AUTHORITIES = Arrays.asList(new SimpleGrantedAuthority(ROLE));
+	static final Collection<String> ORGANSIATIONSEINHEIT_IDS = List.of("812546");
 }
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/callcontext/ContextServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/callcontext/ContextServiceTest.java
index ae80e2f1ae22fdfc26ec5d288f295e65c60bda8f..6a3331f7260afc7f02743a60723632df1e8333d6 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/callcontext/ContextServiceTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/callcontext/ContextServiceTest.java
@@ -7,6 +7,7 @@ import static org.mockito.Mockito.*;
 import java.util.Collection;
 
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
@@ -22,6 +23,7 @@ import de.itvsh.goofy.RequestAttributes;
 import de.itvsh.goofy.RequestAttributesTestFactory;
 import de.itvsh.goofy.common.GrpcUtil;
 import de.itvsh.goofy.common.user.CurrentUserService;
+import de.itvsh.goofy.common.user.UserRole;
 import de.itvsh.goofy.common.user.UserTestFactory;
 import de.itvsh.ozg.pluto.grpc.command.GrpcUser;
 
@@ -45,6 +47,7 @@ class ContextServiceTest {
 		when(userService.getUser()).thenReturn(UserTestFactory.create());
 	}
 
+	@DisplayName("Get context metas")
 	@Nested
 	class TestGetContextMetas {
 
@@ -83,25 +86,36 @@ class ContextServiceTest {
 					.contains(UserTestFactory.ORGANISATORISCHE_EINHEITEN_ID, "orgaid_2");
 		}
 
+		@DisplayName("access limited")
 		@Nested
-		class CheckAccessByUserRole {
+		class TestAccessLimitedByUserRole {
 
 			@Test
-			void shouldHaveCheckIsNecessaryTrueOnRoleVerwaltungPoststelle() {
-				when(userService.hasRole(anyString())).thenReturn(Boolean.TRUE);
+			void shouldHaveTrueOnRoleVerwaltungUser() {
+				when(userService.hasRole(anyString())).thenReturn(Boolean.FALSE);
 
 				var metadata = service.buildCallContextMetadata();
 
-				assertThat(GrpcUtil.getFromHeaders(KEY_ORGAID_CHECK_NECESSARY, metadata)).isEqualTo(Boolean.FALSE.toString());
+				assertThat(GrpcUtil.getFromHeaders(KEY_ACCESS_LIMITED, metadata)).isEqualTo(Boolean.TRUE.toString());
 			}
 
 			@Test
-			void shouldHaveCheckIsNecessaryFalseOnNoRoleVerwaltungPoststelle() {
-				when(userService.hasRole(anyString())).thenReturn(Boolean.FALSE);
+			void shouldHaveFalseOnRoleVerwaltungPoststelle() {
+				when(userService.hasRole(UserRole.VERWALTUNG_POSTSTELLE)).thenReturn(Boolean.TRUE);
+
+				var metadata = service.buildCallContextMetadata();
+
+				assertThat(GrpcUtil.getFromHeaders(KEY_ACCESS_LIMITED, metadata)).isEqualTo(Boolean.FALSE.toString());
+			}
+
+			@Test
+			void shouldHaveFalseOnRoleEinheitlicherAnsprechpartner() {
+				when(userService.hasRole(UserRole.VERWALTUNG_POSTSTELLE)).thenReturn(Boolean.FALSE);
+				when(userService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER)).thenReturn(Boolean.TRUE);
 
 				var metadata = service.buildCallContextMetadata();
 
-				assertThat(GrpcUtil.getFromHeaders(KEY_ORGAID_CHECK_NECESSARY, metadata)).isEqualTo(Boolean.TRUE.toString());
+				assertThat(GrpcUtil.getFromHeaders(KEY_ACCESS_LIMITED, metadata)).isEqualTo(Boolean.FALSE.toString());
 			}
 		}
 	}
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenAuthenticationFilterITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenAuthenticationFilterITCase.java
index 260ec0db0d19212af471df04315e95f3d70adee9..479e63fb7804e00e7f792bea1c96fdcc2f77f372 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenAuthenticationFilterITCase.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenAuthenticationFilterITCase.java
@@ -45,6 +45,17 @@ class DownloadTokenAuthenticationFilterITCase {
 		verify(filter).doFilterInternal(any(), any(), any());
 	}
 
+	@Test
+	void shouldCallFilterWhenNoOrganisationseinheitIds() throws Exception {
+		String token = DownloadTokenTestFactory.createTokenBuilder(downloadTokenProperties.getSecret(), downloadTokenProperties.getValidity())
+				.setClaims(DownloadTokenTestFactory.CLAIMS_WITHOUT_ORGANSIATIONSEINHEIT_IDS).compact();
+
+		performRequest(DownloadTokenController.DOWNLOAD_TOKEN_PATH + "?" + DownloadTokenController.PARAM_TOKEN + "=" + token)
+				.andExpect(status().isOk());
+
+		verify(filter).doFilterInternal(any(), any(), any());
+	}
+
 	@Test
 	void shouldReturnUnauthorised() throws Exception {
 		String token = DownloadTokenTestFactory.createToken("badSecret", downloadTokenProperties.getValidity());
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenServiceTest.java
index d5b9f9e614f9d18d40bb37f267c7cc53928e5e56..2a3601e8a4b1991fde90fffbcaa4b644b01d79f5 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenServiceTest.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenServiceTest.java
@@ -6,6 +6,8 @@ import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
+import java.util.Collection;
+import java.util.List;
 import java.util.Optional;
 
 import javax.servlet.http.HttpServletRequest;
@@ -41,6 +43,7 @@ class DownloadTokenServiceTest {
 	private HttpServletResponse response;
 
 	private final static String FAKE_TOKEN = "xxx";
+	private final static Collection<String> ORGE_IDS = List.of("258994");
 
 	@Nested
 	class TestCreateToken {
@@ -99,10 +102,20 @@ class DownloadTokenServiceTest {
 			assertThat(user).isNotNull();
 		}
 
+		@Test
+		void shouldGetOrganisationseinheitIdsFromToken() {
+			mockClaims(FIRSTNAME_CLAIM, LASTNAME_CLAIM);
+
+			GoofyUser user = service.getUserFromToken(FAKE_TOKEN).getUser();
+
+			assertThat(user.getOrganisationseinheitIds()).isEqualTo(ORGE_IDS);
+		}
+
 		private void mockClaims(String firstnameClaim, String lastnameClaim) {
 			Claims claims = mock(Claims.class);
 			when(claims.get(FIRSTNAME_CLAIM, String.class)).thenReturn(firstnameClaim);
 			when(claims.get(LASTNAME_CLAIM, String.class)).thenReturn(lastnameClaim);
+			when(jwtTokenUtil.getOrganisationseinheitIdsFromToken(any())).thenReturn(ORGE_IDS);
 			when(jwtTokenUtil.getAllClaimsFromToken(any())).thenReturn(Optional.of(claims));
 		}
 
@@ -119,6 +132,7 @@ class DownloadTokenServiceTest {
 
 			assertThrows(TechnicalException.class, () -> handleToken());
 		}
+
 	}
 
 	void handleToken() {
diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenTestFactory.java
index 884ec1e1d43a663e2219ae17a6ae7f88242f4752..d549a1e792b12848c51aeb2fa9cb47b074a2d7c5 100644
--- a/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenTestFactory.java
+++ b/goofy-server/src/test/java/de/itvsh/goofy/common/downloadtoken/DownloadTokenTestFactory.java
@@ -2,6 +2,7 @@ package de.itvsh.goofy.common.downloadtoken;
 
 import static de.itvsh.goofy.JwtTokenUtil.*;
 
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
@@ -17,9 +18,15 @@ public class DownloadTokenTestFactory {
 	static final String SUBJECT = "subject";
 	static final String FIRSTNAME_CLAIM_VALUE = UserTestFactory.FIRSTNAME;
 	static final String LASTNAME_CLAIM_VALUE = UserTestFactory.LASTNAME;
+	final static Collection<String> ORGE_IDS = List.of("258994");
 	static final List<?> ROLE_CLAIM_VALUE = List.of();
 	static final long VALIDITY = 5000;
 	static final Map<String, Object> CLAIMS = new HashMap<>(Map.of(
+			FIRSTNAME_CLAIM, FIRSTNAME_CLAIM_VALUE,
+			LASTNAME_CLAIM, LASTNAME_CLAIM_VALUE,
+			ROLE_CLAIM, ROLE_CLAIM_VALUE,
+			ORGANSIATIONSEINHEIT_IDS_CLAIM, ORGE_IDS));
+	static final Map<String, Object> CLAIMS_WITHOUT_ORGANSIATIONSEINHEIT_IDS = new HashMap<>(Map.of(
 			FIRSTNAME_CLAIM, FIRSTNAME_CLAIM_VALUE,
 			LASTNAME_CLAIM, LASTNAME_CLAIM_VALUE,
 			ROLE_CLAIM, ROLE_CLAIM_VALUE));