diff --git a/alfa-client/apps/admin-e2e/src/components/benutzer/benutzer.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/benutzer/benutzer.e2e.component.ts
index 018f353c5f8cfca304adf2b0bd15a6f0792482c9..0af0f39b14cfd07cdd0ad868b8c780c1bbbea19f 100644
--- a/alfa-client/apps/admin-e2e/src/components/benutzer/benutzer.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/benutzer/benutzer.e2e.component.ts
@@ -22,35 +22,71 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import 'cypress-real-events';
+import { AdminUserE2E } from '../../model/util';
 import { exist } from '../../support/cypress.util';
 
 export class BenutzerE2EComponent {
-  private readonly benutzerHinzufuegenButton: string = 'Add-user-button';
-  private readonly userEntry: string = 'User-entry-';
+  private readonly benutzerHinzufuegenButton: string = 'add-user-button';
+  private readonly userEntry: string = 'user-entry-';
   private readonly userVorname: string = 'Vorname-text-input';
   private readonly userNachname: string = 'Nachname-text-input';
   private readonly userBenutzername: string = 'Benutzername-text-input';
   private readonly userMail: string = 'E-Mail-text-input';
-  private readonly addOEButton: string = 'Add-organisationseinheit-button';
   private readonly adminCheckbox: string = 'Admin-checkbox-editor';
   private readonly loeschenCheckbox: string = 'Loschen-checkbox-editor';
   private readonly userCheckbox: string = 'User-checkbox-editor';
   private readonly postCheckbox: string = 'Poststelle-checkbox-editor';
   private readonly saveButton: string = 'save-button';
+  private readonly organisationsEinheitCheckbox: string = '-checkbox-editor';
 
   public getHinzufuegenButton(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.benutzerHinzufuegenButton);
   }
 
-  public addUser(): void {
+  public hinzufuegenButtonIsVisible(): void {
+    exist(this.getHinzufuegenButton());
+  }
+
+  public clickAddUser(): void {
     this.getHinzufuegenButton().click();
   }
 
+  public addUser(user: AdminUserE2E): void {
+    this.enterVorname(user.vorname);
+    this.enterNachname(user.nachname);
+    this.enterBenutzername(user.benutzername);
+    this.enterMail(user.email);
+
+    if (user.isAdmin) {
+      this.clickAdminCheckbox();
+    }
+    if (user.isUser) {
+      this.clickUserCheckbox();
+    }
+    if (user.isLoeschen) {
+      this.clickLoeschenCheckbox();
+    }
+    if (user.isPoststelle) {
+      this.clickPostCheckbox();
+    }
+
+    if (user.organisationseinheiten) {
+      for (const einheit of user.organisationseinheiten) {
+        this.clickOrganisationsEinheitCheckbox(einheit);
+      }
+    }
+    this.saveUser();
+  }
+
   public getUserEntry(user: string): Cypress.Chainable<Element> {
     user = this.userEntry + user;
     return cy.getTestElement(user);
   }
 
+  public clickUserEntry(user: string): void {
+    this.getUserEntry(user).click();
+  }
+
   public stringExistsInUserEntry(phrase: string, user: string): void {
     this.getUserEntry(user).within(() => {
       exist(cy.contains(phrase));
@@ -89,14 +125,6 @@ export class BenutzerE2EComponent {
     this.getMailInput().type(mail);
   }
 
-  public getOEButton(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.addOEButton);
-  }
-
-  public addOrganisationseinheit(): void {
-    this.getOEButton().click();
-  }
-
   public getAdminCheckbox(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.adminCheckbox);
   }
@@ -136,4 +164,12 @@ export class BenutzerE2EComponent {
   public saveUser(): void {
     this.getSaveButton().click();
   }
+
+  public getOrganisationsEinheitCheckbox(einheit: string): Cypress.Chainable<Element> {
+    return cy.getTestElement(einheit + this.organisationsEinheitCheckbox);
+  }
+
+  public clickOrganisationsEinheitCheckbox(einheit: string): void {
+    this.getOrganisationsEinheitCheckbox(einheit).click();
+  }
 }
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-anlegen.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-anlegen.cy.ts
index 08b27109920f0cc6a67779bfb8d3d262b63bd7bb..0b9aad6ab869bad69f47e7c59cbf0b85e39abe61 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-anlegen.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-anlegen.cy.ts
@@ -5,7 +5,8 @@ import { beChecked, beEnabled, contains, exist, notBeChecked, notBeEnabled } fro
 import { AlfaRollen, AlfaUsers, loginAsAriane } from '../../../support/user-util';
 import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component';
 import { SnackbarMessagesE2E } from '../../../model/util';
-import { wait, waitOfInterceptor } from 'apps/admin-e2e/src/support/cypress-helper';
+import { getCypressEnv, interceptWithResponse, wait, waitOfInterceptor } from 'apps/admin-e2e/src/support/cypress-helper';
+import { AdminUserE2E, HttpMethodE2E } from '../../../model/util';
 
 const mainPage: MainPage = new MainPage();
 const benutzerPage: BenutzerE2EComponent = new BenutzerE2EComponent();
@@ -16,34 +17,36 @@ const nachname: string = 'Testuser';
 const benutzername: string = 'testtheo';
 const emailAddress: string = 'theo.test@ozg-sh.de';
 
+const newUser: AdminUserE2E = {
+  vorname: 'Theo',
+  nachname: 'Testuser',
+  benutzername: 'testtheo',
+  email: 'theo.test@ozg-sh.de',
+  isAdmin: true,
+  isUser: true,
+}
+
 describe('Benutzer anlegen', () => {
   before(() => {
     loginAsAriane();
   });
 
   it('should open Benutzer tab and show Hinzufuegen button', () => {
-    mainPage.clickBenutzerTab();
+    mainPage.clickBenutzerNavigationItem();
 
     exist(benutzerPage.getHinzufuegenButton());
   });
 
-  it.skip('should not do anything after click on save with missing data', () => {
-    benutzerPage.addUser();
-    benutzerPage.saveUser();
-    
-    //TODO: Fehlermeldungen hinzufügen
-  });
-
   it('should show snackbar message on error', () => {
     const interceptor: string = 'postUser';
-    const url: string = 'https://sso.dev.by.ozg-cloud.de/admin/realms/by-e2e-tests-local-dev/users'
+    const url: string = getCypressEnv('keycloakUrl') + '/admin/realms/' + getCypressEnv('keycloakRealm') + '/users'
     const errorCode: number = 500;
     const errorBody: string = 'Internal Server Error';
 
-    cy.intercept('POST', url, {statusCode: errorCode, body: errorBody}).as(interceptor);
+    interceptWithResponse(HttpMethodE2E.POST, url, { errorCode, errorBody }).as(interceptor);
 
-    benutzerPage.addUser();
-    benutzerPage.saveUser();
+    benutzerPage.clickAddUser();
+    benutzerPage.addUser(newUser); 
 
     waitOfInterceptor(interceptor).then(() => {
       contains(snackBar.getMessage(), SnackbarMessagesE2E.NUTZER_FEHLGESCHLAGEN);
@@ -52,13 +55,6 @@ describe('Benutzer anlegen', () => {
 
   it('should show snackbar message on saving user', () => {
     snackBar.getCloseButton().click();
-  
-    benutzerPage.enterVorname(vorname);
-    benutzerPage.enterNachname(nachname);
-    benutzerPage.enterBenutzername(benutzername);
-    benutzerPage.enterMail(emailAddress);
-    benutzerPage.clickAdminCheckbox();
-    benutzerPage.clickUserCheckbox();
 
     benutzerPage.saveUser();
     contains(snackBar.getMessage(), SnackbarMessagesE2E.NUTZER_ANGELEGT);
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-zu-oe-hinzufuegen.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-zu-oe-hinzufuegen.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3735e511e5eb33b45987bbf61fb4aa757d02025c
--- /dev/null
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer-zu-oe-hinzufuegen.cy.ts
@@ -0,0 +1,110 @@
+import { OrganisationsEinheitenE2EComponent } from 'apps/admin-e2e/src/components/organisationseinheiten/organisationseinheiten.e2e.component';
+import { ZustaendigeStelleDialogE2EComponent } from 'apps/admin-e2e/src/components/zustaendige-stelle/zustaendige-stelle-dialog.e2e.component';
+import { AdminUserE2E } from 'apps/admin-e2e/src/model/util';
+import { MainPage } from 'apps/admin-e2e/src/page-objects/main.po';
+import { BenutzerE2EComponent } from '../../../components/benutzer/benutzer.e2e.component';
+import { beChecked, exist, notBeChecked } from '../../../support/cypress.util';
+import { loginAsAriane } from '../../../support/user-util';
+
+describe('Organisationseinheit zu Benutzer hinzufügen', () => {
+  const mainPage: MainPage = new MainPage();
+  const benutzerPage: BenutzerE2EComponent = new BenutzerE2EComponent();
+  const organisationsEinheitenComponent: OrganisationsEinheitenE2EComponent = new OrganisationsEinheitenE2EComponent();
+  const zustaendigeStelleSearchComponent: ZustaendigeStelleDialogE2EComponent = new ZustaendigeStelleDialogE2EComponent();
+  const organistationsEinheitOrdnungsamt: string = 'Ordnungsamt';
+  const organisationsEinheitDenkmalpflege: string = 'Denkmalpflege';
+  const organisationsEinheitWentorf: string = 'grundschule wentorf';
+  const organisationsEinheitNone: string = 'keine zuständige Stelle zugewiesen';
+  const vorname: string = 'Theo';
+  const nachname: string = 'Testuser';
+  const now1 = new Date();
+  const benutzername1: string = 'testtheo' + now1.getSeconds().toString() + now1.getMilliseconds().toString();
+  const emailAddress1: string = 'theo' + now1.getSeconds().toString() + now1.getMilliseconds().toString() + '@ozg-sh.de';
+  const now2 = new Date(now1.getTime() + 1000);
+  const benutzername2: string = 'testtheo' + now2.getSeconds().toString() + now2.getMilliseconds().toString();
+  const emailAddress2: string = 'theo' + now2.getSeconds().toString() + now2.getMilliseconds().toString() + '@ozg-sh.de';
+
+  const newUser1: AdminUserE2E = {
+    vorname: vorname,
+    nachname: nachname,
+    benutzername: benutzername1,
+    email: emailAddress1,
+    isUser: true,
+  };
+
+  const newUser2: AdminUserE2E = {
+    vorname: vorname,
+    nachname: nachname,
+    benutzername: benutzername2,
+    email: emailAddress2,
+    isUser: true,
+    organisationseinheiten: ['Denkmalpflege'],
+  };
+
+  before(() => {
+    loginAsAriane();
+  });
+
+  it('should click Hinzufügen button and show Organisationseinheiten in Benutzer page', () => {
+    mainPage.benutzerNavigationItemIsVisible();
+    mainPage.clickBenutzerNavigationItem();
+    benutzerPage.hinzufuegenButtonIsVisible();
+
+    benutzerPage.clickAddUser();
+    exist(benutzerPage.getOrganisationsEinheitCheckbox(organisationsEinheitDenkmalpflege));
+    exist(benutzerPage.getOrganisationsEinheitCheckbox(organistationsEinheitOrdnungsamt));
+  });
+
+  it('should add no Organisationseinheit to new user without selection and saving', () => {
+    benutzerPage.addUser(newUser1);
+
+    benutzerPage.stringExistsInUserEntry(organisationsEinheitNone, benutzername1);
+  });
+
+  it('should add Organisationseinheit to new user after selection and saving', () => {
+    benutzerPage.clickAddUser();
+    benutzerPage.addUser(newUser2);
+
+    benutzerPage.stringExistsInUserEntry(organisationsEinheitDenkmalpflege, benutzername2);
+  });
+
+  it('should remove Organisationseinheit from existing user on deselection and save', () => {
+    benutzerPage.clickUserEntry(benutzername2);
+    beChecked(benutzerPage.getOrganisationsEinheitCheckbox(organisationsEinheitDenkmalpflege));
+
+    benutzerPage.clickOrganisationsEinheitCheckbox(organisationsEinheitDenkmalpflege);
+    benutzerPage.saveUser();
+
+    benutzerPage.stringExistsInUserEntry(organisationsEinheitNone, benutzername2);
+  });
+
+  it('should add Organisationseinheit to existing user on selection and save', () => {
+    benutzerPage.clickUserEntry(benutzername2);
+    notBeChecked(benutzerPage.getOrganisationsEinheitCheckbox(organistationsEinheitOrdnungsamt));
+
+    benutzerPage.clickOrganisationsEinheitCheckbox(organistationsEinheitOrdnungsamt);
+    benutzerPage.saveUser();
+
+    benutzerPage.stringExistsInUserEntry(organistationsEinheitOrdnungsamt, benutzername2);
+  });
+
+  it('should enable new Organisationseinheit for users after adding it', () => {
+    mainPage.clickOrganisationsEinheitenNavigationItem();
+    organisationsEinheitenComponent.clickHinzufuegen();
+    zustaendigeStelleSearchComponent.enterSearchTerm(organisationsEinheitWentorf);
+    zustaendigeStelleSearchComponent.getZustaendigeStelleTitle(0).then((title: string) => {
+      zustaendigeStelleSearchComponent.clickFoundItem(0);
+    });
+
+    mainPage.clickBenutzerNavigationItem();
+    benutzerPage.clickUserEntry(benutzername2);
+
+    exist(benutzerPage.getOrganisationsEinheitCheckbox(organisationsEinheitWentorf));
+  });
+
+  it('should add new Organisationseinheit to existing user', () => {
+    benutzerPage.clickOrganisationsEinheitCheckbox(organistationsEinheitOrdnungsamt);
+    benutzerPage.saveUser();
+    benutzerPage.stringExistsInUserEntry(organisationsEinheitWentorf, benutzername2);
+  });
+});
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts
index 367507640ad23ba24fa778b1ba0f3afb9bb76e94..9514df893c043a400aa61ec1e517a6007846eb68 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts
@@ -28,7 +28,7 @@ import { AlfaRollen, AlfaUsers, loginAsAriane } from '../../../support/user-util
 
 const mainPage: MainPage = new MainPage();
 const benutzerPage: BenutzerE2EComponent = new BenutzerE2EComponent();
-const organistationsEinheitOrdnungsamt: string = 'Ordnungsamt';
+const organisationsEinheitOrdnungsamt: string = 'Ordnungsamt';
 const organisationsEinheitDenkmalpflege: string = 'Denkmalpflege';
 const organisationsEinheitWirtschaftsfoerderung: string = 'Wirtschaftsförderung';
 const organisationsEinheitNone: string = 'keine zuständige Stelle zugewiesen';
@@ -40,7 +40,7 @@ describe('Benutzer und Rollen', () => {
   });
 
   it('should open Benutzer tab and show Hinzufuegen button', () => {
-    mainPage.clickBenutzerTab();
+    mainPage.clickBenutzerNavigationItem();
 
     exist(benutzerPage.getHinzufuegenButton());
   });
@@ -48,7 +48,7 @@ describe('Benutzer und Rollen', () => {
   it('should show users and attributes in table', () => {
     exist(benutzerPage.getUserEntry('ariane'));
     benutzerPage.stringExistsInUserEntry(AlfaRollen.USER, AlfaUsers.DOROTHEA);
-    benutzerPage.stringExistsInUserEntry(organistationsEinheitOrdnungsamt, AlfaUsers.LUDWIG);
+    benutzerPage.stringExistsInUserEntry(organisationsEinheitOrdnungsamt, AlfaUsers.LUDWIG);
     benutzerPage.stringExistsInUserEntry(AlfaRollen.USER, AlfaUsers.ZELDA);
     benutzerPage.stringExistsInUserEntry(AlfaRollen.LOESCHEN, AlfaUsers.LUDWIG);
     benutzerPage.stringExistsInUserEntry(organisationsEinheitDenkmalpflege, AlfaUsers.ZELDA);
@@ -59,7 +59,7 @@ describe('Benutzer und Rollen', () => {
   });
 
   it('should show single user screen on click', () => {
-    benutzerPage.addUser();
+    benutzerPage.clickAddUser();
 
     exist(benutzerPage.getVornameInput());
     exist(benutzerPage.getNachnameInput());
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/ariane.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/ariane.cy.ts
index 10be61e410d4b9332e05ce3efdd12e65bfd6dc4b..80987765996348c4f24f3105abc2328713ef4371 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/ariane.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/ariane.cy.ts
@@ -13,15 +13,15 @@ describe('Navigation', () => {
     });
 
     it('should show benutzer navigation item', () => {
-      exist(mainPage.getBenutzerTab());
+      exist(mainPage.getBenutzerNavigationItem());
     });
 
     it('should show postfach navigation item', () => {
       exist(mainPage.getPostfachNavigationItem());
     });
 
-    it('should hide organisationseinheiten navigation item', () => {
-      notExist(mainPage.getOrganisationEinheitNavigationItem());
+    it('should show organisationseinheiten navigation item', () => {
+      exist(mainPage.getOrganisationEinheitNavigationItem());
     });
 
     it('should hide statistik navigation item', () => {
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/daria.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/daria.cy.ts
index 3f4d7d82697d1ad4c5e97c57a24113dd14b67a39..57867568976e5deb0675a0ccd3fc52f9e5e19d79 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/daria.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/daria.cy.ts
@@ -16,7 +16,7 @@ describe('Navigation', () => {
     });
 
     it('should hide other navigation item', () => {
-      notExist(mainPage.getBenutzerTab());
+      notExist(mainPage.getBenutzerNavigationItem());
     });
 
     it('should hide postfach navigation item', () => {
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/safira.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/safira.cy.ts
index f1bb7d1184a08fe52a254d3e031de705e7d912f4..6f76dafdfc3161646383b34465056c2e751fa33c 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/safira.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/safira.cy.ts
@@ -16,7 +16,7 @@ describe('Navigation', () => {
     });
 
     it('should show benutzer navigation item', () => {
-      exist(mainPage.getBenutzerTab());
+      exist(mainPage.getBenutzerNavigationItem());
     });
 
     it('should show postfach navigation item', () => {
@@ -34,7 +34,7 @@ describe('Navigation', () => {
 
       describe('on selection', () => {
         before(() => {
-          mainPage.openStatistik();
+          mainPage.clickStatistikNavigationItem();
         });
 
         it('should show page on selection', () => {
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/organisationseinheiten/organisationseinheiten-hinzufuegen.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/organisationseinheiten/organisationseinheiten-hinzufuegen.cy.ts
index 1479f2ad7be1d3153cfb1a75dd435e824b0450f8..ecdc072a69ee0a81f41aa786ccb0a23eacc4f450 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/organisationseinheiten/organisationseinheiten-hinzufuegen.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/organisationseinheiten/organisationseinheiten-hinzufuegen.cy.ts
@@ -17,7 +17,7 @@ describe('Organisationseinheiten', () => {
 
   it('should show table with Organisationseinheiten', () => {
     waitForSpinnerToDisappear();
-    mainPage.openOrganisationsEinheiten();
+    mainPage.clickOrganisationsEinheitenNavigationItem();
 
     exist(organisationsEinheitenComponent.getOrganisationsEinheitHinzufuegenButton());
   });
diff --git a/alfa-client/apps/admin-e2e/src/model/util.ts b/alfa-client/apps/admin-e2e/src/model/util.ts
index efd196d5bb608c2f48ef32ec1f46524847da91fd..a6e185610f221306000e326517a8906ecb1c1f6f 100644
--- a/alfa-client/apps/admin-e2e/src/model/util.ts
+++ b/alfa-client/apps/admin-e2e/src/model/util.ts
@@ -26,6 +26,26 @@ export class ObjectIdE2E {
 }
 
 export enum SnackbarMessagesE2E {
-  NUTZER_ANGELEGT = 'Der Benutzer wurde hinzugefügt.',
-  NUTZER_FEHLGESCHLAGEN = 'Der Benutzer konnte nicht hinzugefügt werden.'
+  NUTZER_ANGELEGT = 'Der Benutzer wurde angelegt.',
+  NUTZER_FEHLGESCHLAGEN = 'Der Benutzer konnte nicht angelegt werden.',
+}
+
+export enum HttpMethodE2E {
+  POST = 'POST',
+  PUT = 'PUT',
+  PATCH = 'PATCH',
+  DELETE = 'DELETE',
+  GET = 'GET',
+}
+
+export interface AdminUserE2E {
+  vorname: string;
+  nachname: string;
+  benutzername: string;
+  email: string;
+  isAdmin?: boolean;
+  isUser?: boolean;
+  isLoeschen?: boolean;
+  isPoststelle?: boolean;
+  organisationseinheiten?: string[];
 }
diff --git a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
index 360f51ce884d2e15ec285c10d7b7c2d8eb66856e..338c98286a6f1fc02e97d52381b99de0dbfc3db6 100644
--- a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
+++ b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
@@ -22,19 +22,16 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BuildInfoE2EComponent } from '../components/buildinfo/buildinfo.e2e.component';
-import { containClass } from '../support/cypress.util';
+import { containClass, exist } from '../support/cypress.util';
 import { HeaderE2EComponent } from './header.po';
 
 export class MainPage {
   private readonly buildInfo: BuildInfoE2EComponent = new BuildInfoE2EComponent();
   private readonly header: HeaderE2EComponent = new HeaderE2EComponent();
 
-  private readonly benutzerTab: string = 'caption-Benutzer__Rollen';
-  private readonly postfachTab: string = 'caption-Postfach';
-  private readonly organisationsEinheitenTab: string = 'caption-Organisationseinheiten';
-
+  private readonly benutzerNavigationItem: string = 'caption-Benutzer__Rollen';
   private readonly postfachNavigationItem: string = 'postfach-navigation';
-  private readonly organisationEinheitNavigation: string = 'organisations-einheiten-navigation';
+  private readonly organisationEinheitNavigationItem: string = 'organisations-einheiten-navigation';
   private readonly statistikNavigationItem: string = 'statistik-navigation';
 
   public getBuildInfo(): BuildInfoE2EComponent {
@@ -45,40 +42,44 @@ export class MainPage {
     return this.header;
   }
 
-  public getBenutzerTab(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.benutzerTab);
+  public getBenutzerNavigationItem(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.benutzerNavigationItem);
+  }
+
+  public clickBenutzerNavigationItem(): void {
+    this.getBenutzerNavigationItem().click();
   }
 
-  public clickBenutzerTab(): void {
-    this.getBenutzerTab().click();
+  public benutzerNavigationItemIsVisible(): void {
+    exist(this.getBenutzerNavigationItem());
   }
 
   public getPostfachNavigationItem(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.postfachNavigationItem);
   }
 
-  public getOrganisationEinheitNavigationItem(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.organisationEinheitNavigation);
+  public clickPostfachNavigationItem(): void {
+    this.getPostfachNavigationItem().click();
   }
 
-  public getOrganisationsEinheitenMenu(): Cypress.Chainable<Element> {
-    return cy.getTestElement(this.organisationsEinheitenTab);
+  public getOrganisationEinheitNavigationItem(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.organisationEinheitNavigationItem);
   }
 
-  public openOrganisationsEinheiten(): void {
-    this.getOrganisationsEinheitenMenu().click();
+  public clickOrganisationsEinheitenNavigationItem(): void {
+    this.getOrganisationEinheitNavigationItem().click();
   }
 
   public getStatistikNavigationItem(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.statistikNavigationItem);
   }
 
-  public isStatistikNavigationItemSelected(): void {
-    containClass(this.getStatistikNavigationItem().get('a'), 'border-selected');
+  public clickStatistikNavigationItem(): void {
+    this.getStatistikNavigationItem().click();
   }
 
-  public openStatistik(): void {
-    this.getStatistikNavigationItem().click();
+  public isStatistikNavigationItemSelected(): void {
+    containClass(this.getStatistikNavigationItem().get('a'), 'border-selected');
   }
 }
 
diff --git a/alfa-client/apps/admin/package.json b/alfa-client/apps/admin/package.json
index d5971b6d301de0a793d62252d8633de0bdc5d13b..924f232583709ebf8224d6a8301cd00d84cb1307 100644
--- a/alfa-client/apps/admin/package.json
+++ b/alfa-client/apps/admin/package.json
@@ -1,4 +1,4 @@
 {
   "name": "admin",
-  "version": "1.5.0-SNAPSHOT"
+  "version": "1.6.0-SNAPSHOT"
 }
diff --git a/alfa-client/apps/admin/src/app/app.component.html b/alfa-client/apps/admin/src/app/app.component.html
index 2bec4bfa7e7bdac55e21d1a7ab5a645ece953f28..8302d53018783e91ffb01539a627b9e5ee7730ff 100644
--- a/alfa-client/apps/admin/src/app/app.component.html
+++ b/alfa-client/apps/admin/src/app/app.component.html
@@ -41,7 +41,7 @@
   <div class="flex h-screen w-full justify-center overflow-y-auto">
     <ods-navbar data-test-id="navigation">
       @if (apiRoot | hasLink: apiRootLinkRel.USERS) {
-        <ods-nav-item data-test-id="users-roles-navigation" caption="Benutzer & Rollen" [path]="routes.BENUTZER_UND_ROLLEN">
+        <ods-nav-item data-test-id="users-roles-navigation" caption="Benutzer & Rollen" [path]="routes.BENUTZER">
           <ods-users-icon class="stroke-text" icon />
         </ods-nav-item>
       }
diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts
index c9fc4300b0ad4d7d7355e475f7693ebde70e5090..34bd937efea886d40f3dc6f77df5eb1b3d68bce5 100644
--- a/alfa-client/apps/admin/src/app/app.component.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.component.spec.ts
@@ -27,11 +27,24 @@ import { KeycloakTokenService } from '@admin/keycloak-shared';
 import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
 import { BuildInfoComponent } from '@alfa-client/common';
 import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@alfa-client/tech-shared';
-import { existsAsHtmlElement, getElementComponentFromFixtureByCss, Mock, mock, notExistsAsHtmlElement, } from '@alfa-client/test-utils';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  Mock,
+  mock,
+  notExistsAsHtmlElement,
+} from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
 import { AuthenticationService } from '@authentication';
-import { AdminLogoIconComponent, MailboxIconComponent, NavbarComponent, NavItemComponent, OrgaUnitIconComponent, UsersIconComponent, } from '@ods/system';
+import {
+  AdminLogoIconComponent,
+  MailboxIconComponent,
+  NavbarComponent,
+  NavItemComponent,
+  OrgaUnitIconComponent,
+  UsersIconComponent,
+} from '@ods/system';
 import { createConfigurationResource } from 'libs/admin/configuration-shared/test/configuration';
 import { MenuContainerComponent } from 'libs/admin/configuration/src/lib/menu-container/menu-container.component';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
@@ -292,13 +305,13 @@ describe('AppComponent', () => {
 
         component.navigateByApiRoot(apiRootResource);
 
-        expect(router.navigate).toHaveBeenCalledWith(['/benutzer_und_rollen']);
+        expect(router.navigate).toHaveBeenCalledWith([`/${ROUTES.BENUTZER}`]);
       });
 
       it('should navigate to unavailable page if no link exists', () => {
         component.navigateByApiRoot(createApiRootResource());
 
-        expect(router.navigate).toHaveBeenCalledWith(['/unavailable']);
+        expect(router.navigate).toHaveBeenCalledWith([`/${ROUTES.UNAVAILABLE}`]);
       });
 
       it('should call unsubscribe', () => {
@@ -385,7 +398,7 @@ describe('AppComponent', () => {
             usersRolesNavigationSelector,
           );
 
-          expect(naviItemComponent.path).toEqual(ROUTES.BENUTZER_UND_ROLLEN);
+          expect(naviItemComponent.path).toEqual(ROUTES.BENUTZER);
         });
 
         it('should show if users link is present', () => {
diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts
index 3a5d98dce6cdf1dc185a64765f03da9514a8f86e..fe6c276c6df933b4df3e29605271a7cf31380042 100644
--- a/alfa-client/apps/admin/src/app/app.component.ts
+++ b/alfa-client/apps/admin/src/app/app.component.ts
@@ -120,7 +120,7 @@ export class AppComponent implements OnInit {
 
   navigateByApiRoot(apiRootResource: ApiRootResource): void {
     if (hasLink(apiRootResource, ApiRootLinkRel.USERS)) {
-      this.navigate(ROUTES.BENUTZER_UND_ROLLEN);
+      this.navigate(ROUTES.BENUTZER);
     } else {
       this.navigate(ROUTES.UNAVAILABLE);
     }
diff --git a/alfa-client/apps/admin/src/app/app.routes.ts b/alfa-client/apps/admin/src/app/app.routes.ts
index b006ee1903203d2ed355ae75ed3a15a4c3c13dc3..279141277b1bbd700ca663d7009e886b89453429 100644
--- a/alfa-client/apps/admin/src/app/app.routes.ts
+++ b/alfa-client/apps/admin/src/app/app.routes.ts
@@ -23,6 +23,7 @@
  */
 import { ConfigurationLinkRel } from '@admin-client/configuration-shared';
 import { ROUTES } from '@admin-client/shared';
+import { UserFormComponent } from '@admin-client/user';
 import { ApiRootLinkRel } from '@alfa-client/api-root-shared';
 import { Route } from '@angular/router';
 import { OrganisationsEinheitPageComponent } from '../pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component';
@@ -30,8 +31,8 @@ import { PostfachPageComponent } from '../pages/postfach/postfach-page/postfach-
 import { StatistikFieldsFormPageComponent } from '../pages/statistik/statistik-fields-form-page/statistik-fields-form-page.component';
 import { StatistikPageComponent } from '../pages/statistik/statistik-page/statistik-page.component';
 import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component';
-import { UserAddPageComponent } from '../pages/users-roles/user-add-page/user-add-page.component';
-import { UserRolesPageComponent } from '../pages/users-roles/user-roles-page/user-roles-page.component';
+import { UserFormPageComponent } from '../pages/user/user-form-page/user-form-page.component';
+import { UserListPageComponent } from '../pages/user/user-list-page/user-list-page.component';
 import { apiRootGuard, configurationGuard } from './app.guard';
 
 export interface GuardData {
@@ -47,19 +48,26 @@ export const appRoutes: Route[] = [
     data: <GuardData>{ linkRelName: ConfigurationLinkRel.SETTING },
   },
   {
-    path: ROUTES.BENUTZER_UND_ROLLEN,
-    component: UserRolesPageComponent,
-    title: 'Admin | Benutzer & Rollen',
+    path: ROUTES.BENUTZER,
+    component: UserListPageComponent,
+    title: 'Admin | Benutzer',
     canActivate: [apiRootGuard],
     data: <GuardData>{ linkRelName: ApiRootLinkRel.USERS },
   },
   {
-    path: ROUTES.BENUTZER_UND_ROLLEN_NEU,
-    component: UserAddPageComponent,
+    path: ROUTES.BENUTZER_NEU,
+    component: UserFormPageComponent,
     title: 'Admin | Benutzer anlegen',
     canActivate: [apiRootGuard],
     data: <GuardData>{ linkRelName: ApiRootLinkRel.USERS },
   },
+  {
+    path: ROUTES.BENUTZER_ID,
+    component: UserFormComponent,
+    title: 'Admin | Benutzer bearbeiten',
+    canActivate: [apiRootGuard],
+    data: <GuardData>{ linkRelName: ApiRootLinkRel.USERS },
+  },
   {
     path: ROUTES.ORGANISATIONSEINHEITEN,
     component: OrganisationsEinheitPageComponent,
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.html b/alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.html
similarity index 95%
rename from alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.html
rename to alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.html
index b4f2c21ecb76e734d0a91b08d61db3e332ab3acb..b8ea84f0bce2a28ed4c1eb19cce3ab7edea16be7 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.html
+++ b/alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.html
@@ -23,4 +23,4 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<admin-users-roles data-test-id="users-roles" />
+<admin-user-form data-test-id="user-form" />
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.spec.ts b/alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.spec.ts
similarity index 76%
rename from alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.spec.ts
rename to alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.spec.ts
index 6c13973fa0b634e253c29ee4354b48da911efc3b..f81d9ea99433e30ecf4ffba51a37ab33d48b0a8c 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.spec.ts
@@ -21,21 +21,21 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { UserAddFormComponent } from '@admin-client/user';
+import { UserFormComponent } from '@admin-client/user';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
-import { UserAddPageComponent } from './user-add-page.component';
+import { UserFormPageComponent } from './user-form-page.component';
 
-describe('UserAddPageComponent', () => {
-  let component: UserAddPageComponent;
-  let fixture: ComponentFixture<UserAddPageComponent>;
+describe('UserPageComponent', () => {
+  let component: UserFormPageComponent;
+  let fixture: ComponentFixture<UserFormPageComponent>;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [UserAddPageComponent, MockComponent(UserAddFormComponent)],
+      declarations: [UserFormPageComponent, MockComponent(UserFormComponent)],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(UserAddPageComponent);
+    fixture = TestBed.createComponent(UserFormPageComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.ts b/alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.ts
similarity index 83%
rename from alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.ts
rename to alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.ts
index 0df47d3f99a92af7ba262020ec16b2ad9466a8e6..998ca19ed9140ec58ccec2abf89b43d8e794530a 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/user/user-form-page/user-form-page.component.ts
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { UserAddFormComponent } from '@admin-client/user';
+import { UserFormComponent } from '@admin-client/user';
 import { Component } from '@angular/core';
 
 @Component({
-  selector: 'user-add-page',
-  templateUrl: './user-add-page.component.html',
+  selector: 'user-form-page',
+  templateUrl: './user-form-page.component.html',
   standalone: true,
-  imports: [UserAddFormComponent],
+  imports: [UserFormComponent],
 })
-export class UserAddPageComponent {}
+export class UserFormPageComponent {}
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.html b/alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.html
similarity index 94%
rename from alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.html
rename to alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.html
index e8bcd63d2f35daea2cb655013ad7a28de1679d77..f8e490cb38d1effa9ca1577c37b3398040af81dc 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-add-page/user-add-page.component.html
+++ b/alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.html
@@ -23,4 +23,4 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<admin-user-add-form data-test-id="user-add-form" />
+<admin-user-list-container data-test-id="users-roles" />
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.spec.ts b/alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.spec.ts
similarity index 77%
rename from alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.spec.ts
rename to alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.spec.ts
index dcff9ea1f54b16ed94d2bf2f37957d37749c34b7..014117b59b7cfaea1ebc68e69be6abf80ef854a2 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.spec.ts
+++ b/alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.spec.ts
@@ -21,22 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { UsersRolesComponent } from '@admin-client/user';
+import { UserListContainerComponent } from '@admin-client/user';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { MockComponent } from 'ng-mocks';
-import { UserRolesPageComponent } from './user-roles-page.component';
+import { UserListPageComponent } from './user-list-page.component';
 
 describe('UserRolesPageComponent', () => {
-  let component: UserRolesPageComponent;
-  let fixture: ComponentFixture<UserRolesPageComponent>;
+  let component: UserListPageComponent;
+  let fixture: ComponentFixture<UserListPageComponent>;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [UserRolesPageComponent],
-      imports: [MockComponent(UsersRolesComponent)],
+      declarations: [UserListPageComponent],
+      imports: [MockComponent(UserListContainerComponent)],
     }).compileComponents();
 
-    fixture = TestBed.createComponent(UserRolesPageComponent);
+    fixture = TestBed.createComponent(UserListPageComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
diff --git a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.ts b/alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.ts
similarity index 82%
rename from alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.ts
rename to alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.ts
index 2d2cf9efdf2de388854a19148634c734b5587297..d30dd38209c8002f6a84f9a0cd1f24d777bc1180 100644
--- a/alfa-client/apps/admin/src/pages/users-roles/user-roles-page/user-roles-page.component.ts
+++ b/alfa-client/apps/admin/src/pages/user/user-list-page/user-list-page.component.ts
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { UsersRolesComponent } from '@admin-client/user';
+import { UserListContainerComponent } from '@admin-client/user';
 import { Component } from '@angular/core';
 
 @Component({
-  selector: 'app-user-roles-page',
-  templateUrl: './user-roles-page.component.html',
+  selector: 'app-user-list-page',
+  templateUrl: './user-list-page.component.html',
   standalone: true,
-  imports: [UsersRolesComponent],
+  imports: [UserListContainerComponent],
 })
-export class UserRolesPageComponent {}
+export class UserListPageComponent {}
diff --git a/alfa-client/apps/alfa-e2e/docker-compose.yml b/alfa-client/apps/alfa-e2e/docker-compose.yml
index 4437108a00c7c9d20850ae18afe70e8eb8101f8f..efbb27de9070db53e35dc0e0c7c3d41ed9015966 100644
--- a/alfa-client/apps/alfa-e2e/docker-compose.yml
+++ b/alfa-client/apps/alfa-e2e/docker-compose.yml
@@ -123,6 +123,7 @@ services:
       - OZGCLOUD_VORGANG_BESCHEID_0_FORM_ID=KFAS_STAGE_KI_10_Haltverbot_LANDESHACKATHON
       - OZGCLOUD_FEATURE_COLLABORATION_ENABLED=true
       - OZGCLOUD_BARRIEREFREIHEIT_URL=https://static.dev.sh.ozg-cloud.de/barrierefreiheit
+      - OZGCLOUD_IMPRESSUM_URL=https://static.dev.sh.ozg-cloud.de/impressum
     ports:
       - 8080:8080
       - 5000:5000
diff --git a/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts
index 04851d1ee40caab11dc5aec3fb28a84363ef1e5e..6900b4f81bba5213341add0864bec162856037fb 100644
--- a/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts
@@ -1,3 +1,5 @@
+import { shouldHaveAttribute } from "../../support/cypress.util";
+
 /*
  * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
@@ -26,6 +28,7 @@ export class HelpMenuE2EComponent {
   private readonly button: string = 'help-menu-button';
   private readonly dropdownButton: string ='dropdown-button';
   private readonly openDocumentationButton: string = 'open-documentation-button';
+  private readonly openImpressumButton: string = 'impressum';
 
   public getRoot() {
     return cy.getTestElementWithOid(this.root);
@@ -42,4 +45,12 @@ export class HelpMenuE2EComponent {
   public getOpenDocumentationButton() {
     return this.getRoot().getTestElementWithOid(this.openDocumentationButton);
   }
+
+  public getImpressumButton(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.openImpressumButton)
+  }
+
+  public impressumLinkIs(link: string): void {
+    shouldHaveAttribute(this.getImpressumButton().find('a'),'href', link)
+  }
 }
diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components.ts
index 76cc3eafbe00d3a6f7cd3f249a1e38ecf0a60d4a..b91293c81d9c0bc662f2ba91cbc1a14a03b9b548 100644
--- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components.ts
+++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components.ts
@@ -25,10 +25,10 @@ export class VorgangFormularButtonsE2EComponent {
   private readonly abschliessenButton: string = 'abschliessen-button';
   private readonly annehmenButton: string = 'annehmen-button';
   private readonly bearbeitenButton: string = 'bearbeiten-button';
+  private readonly forwardButton: string = 'forward-by-ozgcloud-button';
   private readonly bescheidenButton: string = 'bescheiden-button';
   private readonly endgueltigLoeschenButton: string = 'endgueltig-loeschen-button';
-  private readonly loeschAnforderungZuruecknehmenButton: string =
-    'loesch-anforderung-zuruecknehmen-button';
+  private readonly loeschAnforderungZuruecknehmenButton: string = 'loesch-anforderung-zuruecknehmen-button';
   private readonly loeschenAnfordernButton: string = 'loeschen-anfordern-button';
   private readonly verwerfenButton: string = 'verwerfen-button';
   private readonly wiedereroeffnenButton: string = 'wiedereroeffnen-button';
@@ -47,6 +47,10 @@ export class VorgangFormularButtonsE2EComponent {
     return cy.getTestElement(this.bearbeitenButton);
   }
 
+  public getForwardButton() {
+    return cy.getTestElement(this.forwardButton);
+  }
+
   public getBescheidenButton() {
     return cy.getTestElement(this.bescheidenButton);
   }
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward-by-ozgcloud.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward-by-ozgcloud.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8b346e0d75ba810435adc064d63adf36e2ef0991
--- /dev/null
+++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward-by-ozgcloud.cy.ts
@@ -0,0 +1,46 @@
+import { registerLocaleData } from '@angular/common';
+import localeDe from '@angular/common/locales/de';
+import localeDeExtra from '@angular/common/locales/extra/de';
+import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
+import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
+import { VorgangE2E } from '../../../model/vorgang';
+import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
+import { VorgangPage } from '../../../page-objects/vorgang.po';
+import { dropCollections } from '../../../support/cypress-helper';
+import { exist, notExist } from '../../../support/cypress.util';
+import { loginAsEmil } from '../../../support/user-util';
+import { createVorgang, initVorgaenge } from '../../../support/vorgang-util';
+
+registerLocaleData(localeDe, 'de', localeDeExtra);
+
+describe('Vorgang weiterleiten innerhalb der OzgCloud', () => {
+  const mainPage: MainPage = new MainPage();
+  const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
+
+  const vorgangPage: VorgangPage = new VorgangPage();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
+
+  const vorgangWeiterleiten: VorgangE2E = { ...createVorgang(), name: 'Weiterleitung' };
+
+  before(() => {
+    initVorgaenge([vorgangWeiterleiten]);
+
+    loginAsEmil();
+
+    waitForSpinnerToDisappear();
+    exist(vorgangList.getRoot());
+  });
+
+  after(() => {
+    dropCollections();
+  });
+
+  describe('Weiterleiten', () => {
+    it('should display Weiterleiten button in Status Neu', () => {
+      vorgangList.getListItem(vorgangWeiterleiten.name).getRoot().click();
+      waitForSpinnerToDisappear();
+
+      notExist(vorgangFormularButtons.getForwardButton());
+    });
+  });
+});
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts
index b0d1fade8eabd902c3fe3e34b9c6f5763a3a66c2..4cc001a7f49f79190e8e1f53ef1242c36378d238 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts
@@ -25,7 +25,7 @@ import { HelpMenuE2EComponent } from 'apps/alfa-e2e/src/components/user-assistan
 import { HeaderE2EComponent } from 'apps/alfa-e2e/src/page-objects/header.po';
 import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-objects/main.po';
 import { dropCollections } from 'apps/alfa-e2e/src/support/cypress-helper';
-import { exist } from 'apps/alfa-e2e/src/support/cypress.util';
+import { contains, exist, shouldHaveAttribute } from 'apps/alfa-e2e/src/support/cypress.util';
 import { loginAsSabine } from 'apps/alfa-e2e/src/support/user-util';
 
 describe('Help Menu', () => {
@@ -33,6 +33,8 @@ describe('Help Menu', () => {
   const header: HeaderE2EComponent = mainPage.getHeader();
   const helpMenu: HelpMenuE2EComponent = header.getHelpMenu();
 
+  const impressumLink: string = 'https://static.dev.sh.ozg-cloud.de/impressum'
+
   before(() => {
     loginAsSabine();
 
@@ -44,14 +46,19 @@ describe('Help Menu', () => {
     dropCollections();
   });
 
-  describe('open documentation', () => {
-    it('should show "open documentation" button', () => {
+  describe('open help menu', () => {
+    it('should show "open documentation"', () => {
       helpMenu.getRoot().click();
 
       exist(helpMenu.getOpenDocumentationButton());
     });
 
-    it('should open file', () => {
+    it('should show Impressum button and find link', () => {
+      exist(helpMenu.getImpressumButton());
+      helpMenu.impressumLinkIs(impressumLink);
+    });
+
+    it('should open documentation', () => {
       helpMenu
         .getOpenDocumentationButton()
         .find('a')
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/vorgang-anhang-herunterladen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/vorgang-anhang-herunterladen.cy.ts
index f2dd9e0c5d7154ae951368e83bbc4011fd94003f..66ed9474b72739851ea9c6f0eb4845b761d91377 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/vorgang-anhang-herunterladen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/vorgang-anhang-herunterladen.cy.ts
@@ -139,7 +139,7 @@ describe('Vorgang Anhänge', () => {
       exist(readFileFromDownloads(`${vorgangAnhangVorhanden.nummer}_Anhaenge.zip`));
     });
 
-    it('should unzip attachment file', () => {
+    it.skip('UNSTABLE: should unzip attachment file', () => {
       getDownloadFiles().then((files) => {
         unzipDownloadFile(files[0]).then(() => {
           countDownloadFiles().then((count) => {
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts
index aba91c4f37aaf8692d02663f6c6161929804bdbc..81bbd0cdfbe44f1480fcd852caa3f0ae3657e701 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts
@@ -138,7 +138,7 @@ describe('Vorgang abschliessen', () => {
         notExist(snackBar.getMessage());
       });
 
-      it('should show status Beschieden', () => {
+      it.skip('UNSTABLE: should show status Beschieden', () => {
         notExist(vorgangPage.getProgressBar());
 
         haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]);
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-annehmen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-annehmen.cy.ts
index e9c5f5ee33a413f617edd86f0f51a70aaacecce3..b08442086509488f44ece379cccec5186b4a0a03 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-annehmen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-annehmen.cy.ts
@@ -27,23 +27,13 @@ import localeDeExtra from '@angular/common/locales/extra/de';
 import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
 import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component';
 import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
-import {
-  VorgangE2E,
-  VorgangMessagesE2E,
-  VorgangStatusE2E,
-  vorgangStatusLabelE2E,
-} from '../../../model/vorgang';
+import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
 import { dropCollections } from '../../../support/cypress-helper';
 import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
 import { loginAsSabine } from '../../../support/user-util';
-import {
-  buildVorgang,
-  createVorgang,
-  initVorgaenge,
-  objectIds,
-} from '../../../support/vorgang-util';
+import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
 
 registerLocaleData(localeDe, 'de', localeDeExtra);
 
@@ -53,8 +43,7 @@ describe('Vorgang Annehmen', () => {
   const snackBar: SnackBarE2EComponent = mainPage.getSnackBar();
 
   const vorgangPage: VorgangPage = new VorgangPage();
-  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent =
-    vorgangPage.getFormularButtons();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
 
   const vorgangAnnehmen: VorgangE2E = { ...createVorgang(), name: 'DoAnnehmen' };
   const vorgangAnnehmenRevoke: VorgangE2E = buildVorgang(objectIds[0], 'DoRevokeAnnehmen');
@@ -82,10 +71,7 @@ describe('Vorgang Annehmen', () => {
 
     describe('by button', () => {
       it('should have status Neu', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[vorgangAnnehmen.status],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAnnehmen.status]);
       });
 
       it('should show snackBar message', () => {
@@ -103,10 +89,8 @@ describe('Vorgang Annehmen', () => {
       });
 
       it('should have status Angenommen', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN],
-        );
+        waitForSpinnerToDisappear();
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]);
       });
 
       it('back to vorgang list', () => {
@@ -117,10 +101,7 @@ describe('Vorgang Annehmen', () => {
       });
 
       it('should have status Angenommen', () => {
-        haveText(
-          vorgangList.getListItem(vorgangAnnehmen.name).getStatus(),
-          vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN],
-        );
+        haveText(vorgangList.getListItem(vorgangAnnehmen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]);
       });
     });
   });
@@ -135,10 +116,7 @@ describe('Vorgang Annehmen', () => {
 
     describe('by icon-button', () => {
       it('should have status Neu', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[vorgangAnnehmenRevoke.status],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAnnehmenRevoke.status]);
       });
 
       it('should show snackBar message', () => {
@@ -158,10 +136,7 @@ describe('Vorgang Annehmen', () => {
       it('should show status Neu', () => {
         notExist(vorgangPage.getProgressBar());
 
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[VorgangStatusE2E.NEU],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]);
       });
 
       it('back to vorgang list', () => {
@@ -172,10 +147,7 @@ describe('Vorgang Annehmen', () => {
       });
 
       it('should have status Neu', () => {
-        haveText(
-          vorgangList.getListItem(vorgangAnnehmenRevoke.name).getStatus(),
-          vorgangStatusLabelE2E[VorgangStatusE2E.NEU],
-        );
+        haveText(vorgangList.getListItem(vorgangAnnehmenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]);
       });
     });
   });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bearbeiten.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bearbeiten.cy.ts
index c5c0e5306d22ca86da042384ca926c7a3b93b0d3..f178c0f5159cd4b91714ec75f658f12e6b336321 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bearbeiten.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bearbeiten.cy.ts
@@ -24,23 +24,13 @@
 import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
 import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component';
 import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
-import {
-  VorgangE2E,
-  VorgangMessagesE2E,
-  VorgangStatusE2E,
-  vorgangStatusLabelE2E,
-} from '../../../model/vorgang';
+import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
 import { dropCollections } from '../../../support/cypress-helper';
 import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
 import { loginAsSabine } from '../../../support/user-util';
-import {
-  buildVorgang,
-  createVorgang,
-  initVorgaenge,
-  objectIds,
-} from '../../../support/vorgang-util';
+import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
 
 describe('Vorgang bearbeiten', () => {
   const mainPage: MainPage = new MainPage();
@@ -48,8 +38,7 @@ describe('Vorgang bearbeiten', () => {
   const snackBar: SnackBarE2EComponent = mainPage.getSnackBar();
 
   const vorgangPage: VorgangPage = new VorgangPage();
-  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent =
-    vorgangPage.getFormularButtons();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
 
   const vorgangBearbeiten: VorgangE2E = {
     ...createVorgang(),
@@ -84,10 +73,7 @@ describe('Vorgang bearbeiten', () => {
 
     describe('by button', () => {
       it('should have status Angenommen', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[vorgangBearbeiten.status],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBearbeiten.status]);
       });
 
       it('should show snackBar', () => {
@@ -105,10 +91,7 @@ describe('Vorgang bearbeiten', () => {
       });
 
       it('should have status In Bearbeitung', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]);
       });
 
       it('back to vorgang list', () => {
@@ -137,10 +120,7 @@ describe('Vorgang bearbeiten', () => {
 
     describe('by icon-button', () => {
       it('should have status Angenommen', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[vorgangBearbeitenRevoke.status],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBearbeitenRevoke.status]);
       });
 
       it('should show snackBar', () => {
@@ -160,11 +140,9 @@ describe('Vorgang bearbeiten', () => {
 
       it('should show status Angenommen', () => {
         notExist(vorgangPage.getProgressBar());
+        waitForSpinnerToDisappear();
 
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]);
       });
 
       it('back to vorgang list', () => {
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-forward-by-ozgcloud.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-forward-by-ozgcloud.cy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d4661c6d5f536cda3e4286f4064b157cd5e56cf0
--- /dev/null
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-forward-by-ozgcloud.cy.ts
@@ -0,0 +1,78 @@
+import { registerLocaleData } from '@angular/common';
+import localeDe from '@angular/common/locales/de';
+import localeDeExtra from '@angular/common/locales/extra/de';
+import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components';
+import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
+import { VorgangE2E } from '../../../model/vorgang';
+import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
+import { VorgangPage } from '../../../page-objects/vorgang.po';
+import { dropCollections } from '../../../support/cypress-helper';
+import { exist, notExist } from '../../../support/cypress.util';
+import { loginAsPeter, loginAsSabine } from '../../../support/user-util';
+import { createVorgang, initVorgaenge } from '../../../support/vorgang-util';
+
+registerLocaleData(localeDe, 'de', localeDeExtra);
+
+describe('Vorgang weiterleiten innerhalb der OzgCloud', () => {
+  const mainPage: MainPage = new MainPage();
+  const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList();
+
+  const vorgangPage: VorgangPage = new VorgangPage();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
+
+  const vorgangWeiterleiten: VorgangE2E = { ...createVorgang(), name: 'Weiterleitung' };
+
+  after(() => {
+    dropCollections();
+  });
+
+  describe('For Sabine', () => {
+    before(() => {
+      initVorgaenge([vorgangWeiterleiten]);
+
+      loginAsSabine();
+
+      waitForSpinnerToDisappear();
+      exist(vorgangList.getRoot());
+    });
+
+    it('should display Weiterleiten button in Status Neu', () => {
+      vorgangList.getListItem(vorgangWeiterleiten.name).getRoot().click();
+      waitForSpinnerToDisappear();
+
+      exist(vorgangFormularButtons.getForwardButton());
+    });
+
+    it('should not display Weiterleiten button in Status Angenommen', () => {
+      vorgangFormularButtons.getAnnehmenButton().click();
+      waitForSpinnerToDisappear();
+
+      notExist(vorgangFormularButtons.getForwardButton());
+    });
+
+    it('should not display Weiterleiten button in Status In Bearbeitung', () => {
+      vorgangFormularButtons.getBearbeitenButton().click();
+      waitForSpinnerToDisappear();
+
+      notExist(vorgangFormularButtons.getForwardButton());
+    });
+  });
+
+  describe('For Peter', () => {
+    before(() => {
+      initVorgaenge([vorgangWeiterleiten]);
+
+      loginAsPeter();
+
+      waitForSpinnerToDisappear();
+      exist(vorgangList.getRoot());
+    });
+
+    it('should not display Weiterleiten button in Status In Neu', () => {
+      vorgangList.getListItem(vorgangWeiterleiten.name).getRoot().click();
+      waitForSpinnerToDisappear();
+
+      notExist(vorgangFormularButtons.getForwardButton());
+    });
+  });
+});
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts
index 4564daa0997b2d79aa459947ac142ee0f85fdb42..c86efc5d90992c7d5eb14b126554bc3b1872cac1 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts
@@ -161,7 +161,7 @@ describe('Vorgang wiedereroeffnen', () => {
         });
 
         it('should show status Beschieden', () => {
-          wait(500);
+          waitForSpinnerToDisappear();
 
           haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]);
         });
diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.cy.ts
index 9913480cc7a5a8d9f415e6fbbfbdc4103b46a121..59cf821edeb879a7d68283a6644b96c65b513c9f 100644
--- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.cy.ts
+++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.cy.ts
@@ -28,23 +28,13 @@ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components
 import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component';
 import { UserProfileE2EComponent } from '../../../components/user-profile/user-profile.component.e2e';
 import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component';
-import {
-  VorgangE2E,
-  VorgangMessagesE2E,
-  VorgangStatusE2E,
-  vorgangStatusLabelE2E,
-} from '../../../model/vorgang';
+import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang';
 import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po';
 import { VorgangPage } from '../../../page-objects/vorgang.po';
 import { dropCollections } from '../../../support/cypress-helper';
 import { contains, exist, haveText, notExist } from '../../../support/cypress.util';
 import { getUserSabineId, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util';
-import {
-  buildVorgang,
-  createVorgang,
-  initVorgaenge,
-  objectIds,
-} from '../../../support/vorgang-util';
+import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util';
 
 registerLocaleData(localeDe, 'de', localeDeExtra);
 
@@ -54,11 +44,8 @@ describe('Vorgang Zurueckstellen', () => {
   const snackBar: SnackBarE2EComponent = mainPage.getSnackBar();
 
   const vorgangPage: VorgangPage = new VorgangPage();
-  const userContainer: UserProfileE2EComponent = vorgangPage
-    .getVorgangDetailHeader()
-    .getUserContainer();
-  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent =
-    vorgangPage.getFormularButtons();
+  const userContainer: UserProfileE2EComponent = vorgangPage.getVorgangDetailHeader().getUserContainer();
+  const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons();
 
   const vorgangZurueckstellen: VorgangE2E = {
     ...createVorgang(),
@@ -95,10 +82,7 @@ describe('Vorgang Zurueckstellen', () => {
 
     describe('by button', () => {
       it('should have status In Bearbeitung', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[vorgangZurueckstellen.status],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckstellen.status]);
       });
 
       it('should have assigned user(Bearbeiter)', () => {
@@ -121,10 +105,8 @@ describe('Vorgang Zurueckstellen', () => {
       });
 
       it('should have status Angenommen', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN],
-        );
+        waitForSpinnerToDisappear();
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]);
       });
 
       it('back to vorgang list', () => {
@@ -153,10 +135,7 @@ describe('Vorgang Zurueckstellen', () => {
 
     describe('by icon-button', () => {
       it('should have status In Bearbeitung', () => {
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[vorgangZurueckstellenRevoke.status],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckstellenRevoke.status]);
       });
 
       it('should show snackBar message', () => {
@@ -177,10 +156,7 @@ describe('Vorgang Zurueckstellen', () => {
       it('should show status In Bearbeitung', () => {
         notExist(vorgangPage.getProgressBar());
 
-        haveText(
-          vorgangPage.getVorgangDetailHeader().getStatus(),
-          vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG],
-        );
+        haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]);
       });
 
       it('back to vorgang list', () => {
diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml
index 6e358cdd43eed1c5dfd790f9e50f66e0a6e5cfd0..302524d843ae5058af38787a567cde11e5ef04e8 100644
--- a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml
+++ b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml
@@ -46,6 +46,7 @@ alfa:
       documentation:
         url: /assets/benutzerleitfaden/benutzerleitfaden.pdf
     barrierefreiheitUrl: https://static.dev.sh.ozg-cloud.de/barrierefreiheit
+    impressumUrl: https://static.dev.sh.ozg-cloud.de/impressum
     vorgang:
       bescheid:
         - formEngineName: FormSolutions
diff --git a/alfa-client/apps/alfa/package.json b/alfa-client/apps/alfa/package.json
index 5bec6446d53077a3ab1a8def94090810804c5e64..c5322d141c5350c1a5a192513595e4a25eb170f9 100644
--- a/alfa-client/apps/alfa/package.json
+++ b/alfa-client/apps/alfa/package.json
@@ -1,4 +1,4 @@
 {
   "name": "alfa",
-  "version": "2.20.0-SNAPSHOT"
+  "version": "2.21.0-SNAPSHOT"
 }
diff --git a/alfa-client/apps/demo/src/app/app.component.html b/alfa-client/apps/demo/src/app/app.component.html
index 4bec8efda85154a651118d34581a1f7861b0398c..226972864701eedbc6a7b16461f51f85130a88aa 100644
--- a/alfa-client/apps/demo/src/app/app.component.html
+++ b/alfa-client/apps/demo/src/app/app.component.html
@@ -36,6 +36,26 @@
       <nav>NAV</nav>
     </div>
     <main class="flex-auto bg-background-50 p-6">
+      <div class="my-12">
+        <h1 class="mb-6 text-2xl font-semibold text-text">Buttons</h1>
+        <ods-button text="Organisationseinheit hinzufügen" />
+        <br />
+        <ods-button disabled="true" text="Organisationseinheit hinzufügen" />
+
+        <br />
+        <ods-button destructive="true" text="Organisationseinheit hinzufügen" />
+        <br />
+        <ods-button variant="outline" text="Organisationseinheit hinzufügen" />
+        <br />
+        <ods-button destructive="true" variant="outline" text="Organisationseinheit hinzufügen" /><br />
+
+        <ods-button destructive="true" disabled="true" variant="outline" text="Organisationseinheit hinzufügen" />
+        <br />
+        <ods-button variant="ghost" text="Organisationseinheit hinzufügen" />
+        <br />
+        <ods-button destructive="true" variant="ghost" text="Organisationseinheit hinzufügen" />
+      </div>
+
       <div class="my-12">
         <h1 class="mb-6 text-2xl font-semibold text-text">Organisationseinheiten</h1>
         <ods-button text="Organisationseinheit hinzufügen" />
diff --git a/alfa-client/apps/info/package.json b/alfa-client/apps/info/package.json
index a4621dd64ccdd9f6ac1a64524ac77364c02c6a6f..5861518686029b9621a5e39e361c49ce6f462690 100644
--- a/alfa-client/apps/info/package.json
+++ b/alfa-client/apps/info/package.json
@@ -1,4 +1,4 @@
 {
   "name": "info",
-  "version": "1.5.0-SNAPSHOT"
-}
\ No newline at end of file
+  "version": "1.6.0-SNAPSHOT"
+}
diff --git a/alfa-client/apps/info/src/pages/impressum/impressum-page-sh.component.ts b/alfa-client/apps/info/src/pages/impressum/impressum-page-sh.component.ts
index 443387d3a3af5dba195f4eb173d3a965f8803605..8acecebc1451d3a3c545c4e8a018b4799aafd5c4 100644
--- a/alfa-client/apps/info/src/pages/impressum/impressum-page-sh.component.ts
+++ b/alfa-client/apps/info/src/pages/impressum/impressum-page-sh.component.ts
@@ -15,7 +15,7 @@ import { Component } from '@angular/core';
     </p>
     <p>
       E-Mail: <br />
-      <a href="mailto:digitalisierung@stk.landsh.de">digitalisierung&#64;stk.landsh.de</a>
+      <a href="mailto:digitalisierung@stk.landsh.de">Digitalisierung&#64;stk.landsh.de</a>
     </p>
     <p>
       Verantwortlich <br />
@@ -25,7 +25,7 @@ import { Component } from '@angular/core';
 
     <p>
       E-Mail: <br />
-      <a href="mailto:digitalisierung@stk.landsh.de">digitalisierung&#64;stk.landsh.de</a>
+      <a href="mailto:digitalisierung@stk.landsh.de">Digitalisierung&#64;stk.landsh.de</a>
     </p>
   </div>`,
 })
diff --git a/alfa-client/libs/admin/keycloak-shared/src/index.ts b/alfa-client/libs/admin/keycloak-shared/src/index.ts
index b0e24572b79fae2fa13d859fc348d5319e8229e1..4197ca2f1a4afbeacb65191a3fbe565c72987da5 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/index.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/index.ts
@@ -1,3 +1,5 @@
+export * from './lib/keycloak-formservice';
 export * from './lib/keycloak-token.service';
+export * from './lib/keycloak.resource.service';
 export * from './lib/organisations-einheit.repository';
 export * from './lib/user.repository';
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..be3f115f38c800b3b1cf87b3aaec5044e9b3c121
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.spec.ts
@@ -0,0 +1,121 @@
+import { FormControl, FormGroup } from '@angular/forms';
+import { patchForm } from './form.util';
+
+describe('FormUtil', () => {
+  describe('patch form', () => {
+    it('should not throw any errors', () => {
+      const errorHandler = jest.fn();
+      window.onerror = errorHandler;
+      const formGroup: FormGroup = new FormGroup({
+        existingKey: new FormControl(null),
+      });
+
+      patchForm({ missingKey: 'dummyValue' }, formGroup);
+
+      expect(errorHandler).not.toHaveBeenCalled();
+    });
+
+    describe('on strings', () => {
+      it('should patch values', () => {
+        const formGroup: FormGroup = new FormGroup({
+          stringValue: new FormControl(null),
+        });
+
+        patchForm({ stringValue: 'test' }, formGroup);
+
+        expect(formGroup.controls['stringValue'].value).toBe('test');
+      });
+    });
+
+    describe('on array string value', () => {
+      it('should patch all', () => {
+        const formGroup: FormGroup = new FormGroup({
+          array: new FormGroup({
+            arrayValue1: new FormControl(false),
+            arrayValue2: new FormControl(false),
+          }),
+        });
+
+        patchForm({ array: ['arrayValue1', 'arrayValue2'] }, formGroup);
+
+        const arrayFormGroup: FormGroup = getControlAsFormGroup('array', formGroup);
+        expect(arrayFormGroup.controls['arrayValue1'].value).toBeTruthy();
+        expect(arrayFormGroup.controls['arrayValue2'].value).toBeTruthy();
+      });
+
+      it('should patch matching values only', () => {
+        const formGroup: FormGroup = new FormGroup({
+          array: new FormGroup({
+            arrayValue1: new FormControl(false),
+            arrayValue2: new FormControl(false),
+          }),
+        });
+
+        patchForm({ array: ['arrayValue1'] }, formGroup);
+
+        const arrayFormGroup: FormGroup = getControlAsFormGroup('array', formGroup);
+        expect(arrayFormGroup.controls['arrayValue1'].value).toBeTruthy();
+        expect(arrayFormGroup.controls['arrayValue2'].value).toBeFalsy();
+      });
+    });
+
+    describe('on object value', () => {
+      describe('contains strings', () => {
+        it('should patch values', () => {
+          const formGroup: FormGroup = new FormGroup({
+            object: new FormGroup({
+              stringValue: new FormControl(null),
+            }),
+          });
+
+          patchForm({ object: { stringValue: 'test' } }, formGroup);
+
+          const objectFormGroup: FormGroup = getControlAsFormGroup('object', formGroup);
+          expect(objectFormGroup.controls['stringValue'].value).toEqual('test');
+        });
+      });
+
+      describe('contains array string value', () => {
+        it('should patch all', () => {
+          const formGroup: FormGroup = new FormGroup({
+            object: new FormGroup({
+              array: new FormGroup({
+                arrayValue1: new FormControl(false),
+                arrayValue2: new FormControl(false),
+              }),
+            }),
+          });
+
+          patchForm({ object: { array: ['arrayValue1', 'arrayValue2'] } }, formGroup);
+
+          const objectFormGroup: FormGroup = getControlAsFormGroup('object', formGroup);
+          const arrayFormGroup: FormGroup = getControlAsFormGroup('array', objectFormGroup);
+          expect(arrayFormGroup.controls['arrayValue1'].value).toBeTruthy();
+          expect(arrayFormGroup.controls['arrayValue2'].value).toBeTruthy();
+        });
+
+        it('should patch matching values only', () => {
+          const formGroup: FormGroup = new FormGroup({
+            object: new FormGroup({
+              array: new FormGroup({
+                arrayValue1: new FormControl(false),
+                arrayValue2: new FormControl(false),
+              }),
+            }),
+          });
+
+          patchForm({ object: { array: ['arrayValue1'] } }, formGroup);
+
+          const objectFormGroup: FormGroup = getControlAsFormGroup('object', formGroup);
+          const arrayFormGroup: FormGroup = getControlAsFormGroup('array', objectFormGroup);
+          expect(arrayFormGroup.controls['arrayValue1'].value).toBeTruthy();
+          expect(arrayFormGroup.controls['arrayValue2'].value).toBeFalsy();
+        });
+      });
+    });
+  });
+
+  function getControlAsFormGroup(key: string, formGroup: FormGroup): FormGroup {
+    return <FormGroup>formGroup.controls[key];
+  }
+});
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..877cf9e458b14b0d2f7732086f5e033ba3b40bf5
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.ts
@@ -0,0 +1,26 @@
+import { FormGroup } from '@angular/forms';
+import { isBoolean, isString } from 'lodash-es';
+
+export function patchForm(valueToPatch: any, formGroup: FormGroup): void {
+  formGroup.patchValue(valueToPatch);
+
+  patchNonStringValues(valueToPatch, formGroup);
+}
+
+function patchNonStringValues(valueToPatch: any, formGroup: FormGroup): void {
+  Object.entries(valueToPatch).forEach(([key, value]) => {
+    if (formGroup.contains(key)) patchNonStringValue(value, getControlAsFormGroup(key, formGroup));
+  });
+}
+
+function patchNonStringValue(value: any, formGroup: FormGroup): void {
+  if (Array.isArray(value)) {
+    value.forEach((oneValue: any) => formGroup.controls[oneValue].patchValue(true));
+  } else if (!isString(value) && !isBoolean(value)) {
+    patchNonStringValues(value, formGroup);
+  }
+}
+
+function getControlAsFormGroup(key: string, formGroup: FormGroup): FormGroup {
+  return <FormGroup>formGroup.controls[key];
+}
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-formservice.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-formservice.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..865f904f83dbfd0ad22873ec8578531815b1c8dd
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-formservice.spec.ts
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { createEmptyStateResource, createStateResource, EMPTY_STRING, StateResource } from '@alfa-client/tech-shared';
+import { Injectable } from '@angular/core';
+import { TestBed } from '@angular/core/testing';
+import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
+import { ActivatedRoute, UrlSegment } from '@angular/router';
+import { createDummy, Dummy } from 'libs/tech-shared/test/dummy';
+import { singleCold, singleHot } from 'libs/tech-shared/test/marbles';
+import { createSpy, mock, Mock } from 'libs/test-utils/src/lib/mocking';
+import { Observable, of } from 'rxjs';
+import { createUrlSegment } from '../../../../navigation-shared/test/navigation-test-factory';
+import { KeycloakFormService, PatchConfig } from './keycloak-formservice';
+
+import * as FormUtil from './form.util';
+
+describe('KeycloakFormService', () => {
+  let service: KeycloakFormService<Dummy>;
+
+  let formBuilder: FormBuilder = new FormBuilder();
+  let activatedRoute: Mock<ActivatedRoute>;
+
+  let initFormSpy: jest.SpyInstance<FormGroup>;
+  let evaluateRouteSpy: jest.SpyInstance<void>;
+
+  const formGroup: FormGroup = new FormGroup({});
+  const activatedRouteSegements: UrlSegment[] = [createUrlSegment()];
+
+  beforeEach(() => {
+    activatedRoute = <any>{ ...mock(ActivatedRoute), url: of<UrlSegment[]>(activatedRouteSegements) };
+
+    initFormSpy = createSpy(TestKeycloakFormService, '_initForm').mockReturnValue(formGroup);
+    evaluateRouteSpy = createSpy(TestKeycloakFormService, '_evaluateRoute');
+
+    TestBed.configureTestingModule({
+      providers: [
+        TestKeycloakFormService,
+        { provide: FormBuilder, useValue: formBuilder },
+        { provide: ActivatedRoute, useValue: activatedRoute },
+      ],
+    });
+
+    service = TestBed.inject(TestKeycloakFormService);
+  });
+
+  it('should create', () => {
+    expect(service).toBeTruthy();
+  });
+
+  describe('after creation', () => {
+    describe('form', () => {
+      it('should be initialized', () => {
+        expect(initFormSpy).toHaveBeenCalled();
+      });
+
+      it('should be set', () => {
+        expect(service.form).toBe(formGroup);
+      });
+    });
+
+    it('should evaluate route', () => {
+      expect(evaluateRouteSpy).toHaveBeenCalled();
+    });
+  });
+
+  describe('evaluate route', () => {
+    const patchConfig: PatchConfig = { id: 'dummyId', doPatch: true };
+
+    beforeEach(() => {
+      service._patchConfig = undefined;
+      service._buildPatchConfig = jest.fn().mockReturnValue(patchConfig);
+    });
+
+    it('should build patch config by url segments form activated route', () => {
+      service._evaluateRoute();
+
+      expect(service._buildPatchConfig).toHaveBeenCalledWith(activatedRouteSegements);
+    });
+
+    it('should set patchConfig', () => {
+      service._evaluateRoute();
+
+      expect(service._patchConfig).toBe(patchConfig);
+    });
+  });
+
+  describe('get', () => {
+    describe('if patch is necessarry', () => {
+      const loadedStateResource: StateResource<Dummy> = createStateResource(createDummy());
+
+      beforeEach(() => {
+        service._initLoading = jest.fn().mockReturnValue(singleCold(loadedStateResource));
+        service._patchConfig = { doPatch: true };
+      });
+
+      it('should init loading', () => {
+        service.get();
+
+        expect(service._initLoading).toHaveBeenCalled();
+      });
+
+      it('should return loaded resource', () => {
+        const loadedResource: Observable<StateResource<Dummy>> = service.get();
+
+        expect(loadedResource).toBeObservable(singleCold(loadedStateResource));
+      });
+    });
+
+    it('should return empty state resource if patch is NOT necessarry', (done) => {
+      service._patchConfig = { doPatch: false };
+
+      service.get().subscribe((stateResource: StateResource<Dummy>) => {
+        expect(stateResource).toEqual(createEmptyStateResource());
+        done();
+      });
+    });
+  });
+
+  describe('init loading', () => {
+    const patchConfig: PatchConfig = { id: 'dummyId', doPatch: true };
+    const dummyStateResource: StateResource<unknown> = createStateResource(createDummy());
+
+    beforeEach(() => {
+      service._patchConfig = patchConfig;
+      service._load = jest.fn().mockReturnValue(singleHot(dummyStateResource));
+      service._patchIfLoaded = jest.fn();
+    });
+
+    it('should call load', () => {
+      service._initLoading();
+
+      expect(service._load).toHaveBeenCalledWith('dummyId');
+    });
+
+    it('should call patch if loaded', () => {
+      service._load = jest.fn().mockReturnValue(of(dummyStateResource));
+
+      service._initLoading().subscribe();
+
+      expect(service._patchIfLoaded).toHaveBeenCalledWith(dummyStateResource);
+    });
+
+    it('should return loaded value', () => {
+      const loadedDummyStateResource: Observable<StateResource<Dummy>> = service._initLoading();
+
+      expect(loadedDummyStateResource).toBeObservable(singleCold(dummyStateResource));
+    });
+  });
+
+  describe('patch if loaded', () => {
+    const dummy: Dummy = createDummy();
+
+    it('should call patch on loaded state resource', () => {
+      service._patch = jest.fn();
+
+      service._patchIfLoaded(createStateResource(dummy));
+
+      expect(service._patch).toHaveBeenCalledWith(dummy);
+    });
+  });
+
+  describe('submit', () => {
+    const dummyStateResource: StateResource<Dummy> = createStateResource(createDummy());
+
+    beforeEach(() => {
+      service._doSubmit = jest.fn().mockReturnValue(singleHot(dummyStateResource));
+    });
+
+    it('should call do submit', () => {
+      service.submit();
+
+      expect(service._doSubmit).toHaveBeenCalled();
+    });
+
+    it('should return submit response', () => {
+      const submitResponse: Observable<StateResource<Dummy>> = service.submit();
+
+      expect(submitResponse).toBeObservable(singleCold(dummyStateResource));
+    });
+  });
+
+  describe('patch', () => {
+    const valueToPatch: Dummy = { name: 'newName' };
+    let patchFormSpy: jest.SpyInstance;
+
+    beforeEach(() => {
+      service.form = formBuilder.group({ name: 'dummyName' });
+      patchFormSpy = jest.spyOn(FormUtil, 'patchForm').mockImplementation();
+    });
+
+    it('should call patch form', () => {
+      service._patch(valueToPatch);
+
+      expect(patchFormSpy).toHaveBeenCalledWith(valueToPatch, service.form);
+    });
+
+    it('should reset form value', () => {
+      service._patch(valueToPatch);
+
+      expect(service.form.value).toEqual({ name: null });
+    });
+
+    it('should set patched', () => {
+      service._patched = false;
+
+      service._patch(valueToPatch);
+
+      expect(service._patched).toBeTruthy();
+    });
+  });
+
+  describe('get form value', () => {
+    const dummyName: string = 'DummyName';
+
+    it('should return form value', () => {
+      service.form = formBuilder.group({ name: dummyName });
+
+      const formValue: unknown = service._getFormValue();
+
+      expect(formValue).toEqual({ name: dummyName });
+    });
+  });
+
+  describe('is patch', () => {
+    it('should return patched value', () => {
+      service._patched = true;
+
+      const isPatch: boolean = service.isPatch();
+
+      expect(isPatch).toBeTruthy();
+    });
+  });
+
+  describe('is invalid', () => {
+    it('should return true on invalid form', () => {
+      service.form = formBuilder.group({ name: [EMPTY_STRING, Validators.required] });
+
+      const isInvalid: boolean = service.isInvalid();
+
+      expect(isInvalid).toBeTruthy();
+    });
+  });
+});
+
+@Injectable()
+export class TestKeycloakFormService extends KeycloakFormService<Dummy> {
+  public static readonly FIELD: string = 'attribute';
+
+  public static SUBMIT_OBSERVABLE = () => of(createEmptyStateResource());
+  public static LOAD_OBSERVABLE = () => of(createEmptyStateResource());
+
+  _initForm(): FormGroup {
+    return this.formBuilder.group({
+      [TestKeycloakFormService.FIELD]: new FormControl(null),
+    });
+  }
+
+  _buildPatchConfig(urlSegments: UrlSegment[]): PatchConfig {
+    return <PatchConfig>{};
+  }
+
+  _load(id: string): Observable<StateResource<Dummy>> {
+    return TestKeycloakFormService.LOAD_OBSERVABLE();
+  }
+
+  _doSubmit(): Observable<StateResource<Dummy>> {
+    return TestKeycloakFormService.SUBMIT_OBSERVABLE();
+  }
+}
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-formservice.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-formservice.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ecd71702a2a6d3e6176dc5890bdc9cd61dc7fe7c
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-formservice.ts
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { createEmptyStateResource, isLoaded, StateResource } from '@alfa-client/tech-shared';
+import { inject, Injectable } from '@angular/core';
+import { FormBuilder, FormGroup } from '@angular/forms';
+import { ActivatedRoute, UrlSegment } from '@angular/router';
+import { first, Observable, of, tap } from 'rxjs';
+
+import * as FormUtil from './form.util';
+
+@Injectable()
+export abstract class KeycloakFormService<T> {
+  protected readonly formBuilder = inject(FormBuilder);
+  protected readonly activatedRoute = inject(ActivatedRoute);
+
+  form: FormGroup;
+  _patched: boolean = false;
+
+  _patchConfig: PatchConfig;
+
+  constructor() {
+    this.form = this._initForm();
+
+    this._evaluateRoute();
+  }
+
+  abstract _initForm(): FormGroup;
+
+  _evaluateRoute(): void {
+    this.activatedRoute.url.pipe(first()).subscribe((url: UrlSegment[]) => {
+      this._patchConfig = this._buildPatchConfig(url);
+    });
+  }
+
+  abstract _buildPatchConfig(urlSegments: UrlSegment[]): PatchConfig;
+
+  public get(): Observable<StateResource<T>> {
+    return this._patchConfig.doPatch ? this._initLoading() : of(createEmptyStateResource<T>());
+  }
+
+  _initLoading(): Observable<StateResource<T>> {
+    return this._load(this._patchConfig.id).pipe(tap((stateResource: StateResource<T>) => this._patchIfLoaded(stateResource)));
+  }
+
+  abstract _load(id: string): Observable<StateResource<T>>;
+
+  _patchIfLoaded(stateResource: StateResource<T>): void {
+    if (isLoaded(stateResource)) this._patch(stateResource.resource);
+  }
+
+  public submit(): Observable<StateResource<T>> {
+    return this._doSubmit();
+  }
+
+  abstract _doSubmit(): Observable<StateResource<T>>;
+
+  _patch(valueToPatch: T): void {
+    this.form.reset();
+
+    FormUtil.patchForm(valueToPatch, this.form);
+
+    this._patched = true;
+  }
+
+  _getFormValue(): T {
+    return this.form.value;
+  }
+
+  public isPatch(): boolean {
+    return this._patched;
+  }
+
+  public isInvalid(): boolean {
+    return this.form.invalid;
+  }
+}
+
+export interface PatchConfig {
+  id?: string;
+  doPatch: boolean;
+}
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.ts
index f609562b64c86a24c22f1e278bda74d5b0e4fe77..1c2893651d695b6700ee2a45a0c6d07b459b7106 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.ts
@@ -14,7 +14,7 @@ export class KeycloakTokenService {
 
   private getTokenProvider(): TokenProvider {
     return {
-      getAccessToken: () => Promise.resolve(this.oAuthService.getAccessToken()),
+      getAccessToken: (): Promise<string> => Promise.resolve(this.oAuthService.getAccessToken()),
     };
   }
 }
diff --git a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak.resource.service.spec.ts
similarity index 81%
rename from alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts
rename to alfa-client/libs/admin/keycloak-shared/src/lib/keycloak.resource.service.spec.ts
index 5e5990cb4b3432cd9fd1d69a228bbaa698c08347..ea3ca2d74ffe1eb2b6fb903a300d5b1b7b36e455 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak.resource.service.spec.ts
@@ -24,13 +24,14 @@
 import { TestBed, fakeAsync, tick } from '@angular/core/testing';
 import { faker } from '@faker-js/faker';
 import { cold } from 'jest-marbles';
-import * as resourceUtil from 'libs/tech-shared/src/lib/resource/resource.util';
-import { StateResource, createEmptyStateResource } from 'libs/tech-shared/src/lib/resource/resource.util';
+import { StateResource, createEmptyStateResource, createStateResource } from 'libs/tech-shared/src/lib/resource/resource.util';
 import { Dummy, createDummy } from 'libs/tech-shared/test/dummy';
 import { singleCold } from 'libs/tech-shared/test/marbles';
 import { Observable, of } from 'rxjs';
 import { KeycloakResourceService } from './keycloak.resource.service';
 
+import * as ResourceUtil from 'libs/tech-shared/src/lib/resource/resource.util';
+
 describe('KeycloakResourceService', () => {
   let service: KeycloakResourceService<unknown>;
 
@@ -47,20 +48,20 @@ describe('KeycloakResourceService', () => {
     service = TestBed.inject(TestResourceService);
   });
 
-  describe('get', () => {
+  describe('getAll', () => {
     beforeEach(() => {
       service.handleChanges = jest.fn();
     });
 
     it('should return stateResource as observable', (done) => {
-      service.get().subscribe((stateResource) => {
+      service.getAll().subscribe((stateResource) => {
         expect(stateResource).toBe(service.stateResource.value);
         done();
       });
     });
 
     it('should call handleChanges ', fakeAsync(() => {
-      service.get().subscribe();
+      service.getAll().subscribe();
 
       expect(service.handleChanges).toHaveBeenCalled();
     }));
@@ -68,7 +69,7 @@ describe('KeycloakResourceService', () => {
 
   describe('handleChanges', () => {
     it('should call doIfLoadingRequired', () => {
-      const doIfLoadingRequired: jest.SpyInstance<boolean> = jest.spyOn(resourceUtil, 'doIfLoadingRequired');
+      const doIfLoadingRequired: jest.SpyInstance<boolean> = jest.spyOn(ResourceUtil, 'doIfLoadingRequired');
 
       service.handleChanges(emptyStateResource);
 
@@ -87,7 +88,7 @@ describe('KeycloakResourceService', () => {
 
     it('should update Resource', fakeAsync(() => {
       const dummyItems = [createDummy(), createDummy()];
-      jest.spyOn(service, 'getItemsFromKeycloak' as any).mockReturnValue(of(dummyItems));
+      jest.spyOn(service, '_getItemsFromKeycloak' as any).mockReturnValue(of(dummyItems));
 
       service.loadResource();
       tick();
@@ -108,7 +109,7 @@ describe('KeycloakResourceService', () => {
     });
 
     it('should call createInKeycloak', () => {
-      const createInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'createInKeycloak' as any).mockReturnValue(of({}));
+      const createInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, '_createInKeycloak' as any).mockReturnValue(of({}));
 
       service.create(saveObject);
 
@@ -126,7 +127,7 @@ describe('KeycloakResourceService', () => {
     });
 
     it('should call createInKeycloak', () => {
-      const saveInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'saveInKeycloak' as any).mockReturnValue(of({}));
+      const saveInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, '_saveInKeycloak' as any).mockReturnValue(of({}));
 
       service.save(dummyObject);
 
@@ -144,7 +145,7 @@ describe('KeycloakResourceService', () => {
     });
 
     it('should call createInKeycloak', () => {
-      const saveInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'saveInKeycloak' as any).mockReturnValue(of({}));
+      const saveInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, '_saveInKeycloak' as any).mockReturnValue(of({}));
 
       service.save(id);
 
@@ -168,11 +169,11 @@ describe('KeycloakResourceService', () => {
     });
 
     it('should call progress', () => {
-      service.progress = jest.fn().mockReturnValue(dummyAction);
+      service.setLoadingInStateResource = jest.fn().mockReturnValue(dummyAction);
 
       service.handleLoading(dummyAction);
 
-      expect(service.progress).toHaveBeenCalled();
+      expect(service.setLoadingInStateResource).toHaveBeenCalled();
     });
   });
 
@@ -187,11 +188,11 @@ describe('KeycloakResourceService', () => {
     }));
   });
 
-  describe('progress', () => {
-    it('should emit true at the start and false after first parameter emit', () => {
-      const result: Observable<boolean> = service.progress(cold('--x', { x: dummyObject }));
+  describe('setLoadingInStateResource', () => {
+    it('should emit emptyState first with loading and then state without loading', () => {
+      const result: Observable<StateResource<Dummy>> = service.setLoadingInStateResource<Dummy>(cold('--x', { x: dummyObject }));
 
-      expect(result).toBeObservable(cold('a-b', { a: true, b: false }));
+      expect(result).toBeObservable(cold('a-b', { a: createEmptyStateResource(true), b: createStateResource(dummyObject) }));
     });
   });
 
@@ -215,7 +216,7 @@ describe('KeycloakResourceService', () => {
     it('should clear resource in state', () => {
       service.refresh();
 
-      expect(service.stateResource.value.resource).toBe(null);
+      expect(service.stateResource.value.resource).toEqual([]);
     });
   });
 
@@ -232,19 +233,19 @@ describe('KeycloakResourceService', () => {
 });
 
 class TestResourceService extends KeycloakResourceService<unknown> {
-  getItemsFromKeycloak(): Observable<unknown[]> {
+  _getItemsFromKeycloak(): Observable<unknown[]> {
     return of(null);
   }
 
-  saveInKeycloak(): Observable<void> {
+  _saveInKeycloak(): Observable<void> {
     return of(null);
   }
 
-  createInKeycloak(): Observable<void> {
+  _createInKeycloak(): Observable<void> {
     return of(null);
   }
 
-  deleteInKeycloak(): Observable<void> {
+  _deleteInKeycloak(): Observable<void> {
     return of(null);
   }
 }
diff --git a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak.resource.service.ts
similarity index 54%
rename from alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts
rename to alfa-client/libs/admin/keycloak-shared/src/lib/keycloak.resource.service.ts
index 1b081f6ea809183f332a3d40d3b2772c9fa100a4..572761923b93f3d3a21719659416b268fb17076f 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak.resource.service.ts
@@ -24,65 +24,69 @@
 import { createEmptyStateResource, createStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared';
 import { BehaviorSubject, first, map, Observable, startWith, tap } from 'rxjs';
 
-// todo: auslagern in ein shared module
 export abstract class KeycloakResourceService<T> {
-  readonly stateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject(createEmptyStateResource<T[]>());
-
-  public get(): Observable<StateResource<T[]>> {
-    return this.stateResource.asObservable().pipe(tap((stateResource: StateResource<T[]>) => this.handleChanges(stateResource)));
+  readonly stateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject({
+    ...createStateResource<T[]>([]),
+    loaded: false,
+  });
+
+  public getAll(): Observable<StateResource<T[]>> {
+    return this.stateResource
+      .asObservable()
+      .pipe(tap((stateResource: StateResource<T[]>): void => this.handleChanges(stateResource)));
   }
 
   handleChanges(stateResource: StateResource<T[]>): void {
-    doIfLoadingRequired(stateResource, () => this.loadResource());
+    doIfLoadingRequired(stateResource, (): void => this.loadResource());
   }
 
   loadResource(): void {
     this.setLoading();
-    this.getItemsFromKeycloak()
+    this._getItemsFromKeycloak()
       .pipe(first())
-      .subscribe((items) => this.updateResource(items));
+      .subscribe((items: T[]): void => this.updateResource(items));
   }
 
-  protected abstract getItemsFromKeycloak(): Observable<T[]>;
+  protected abstract _getItemsFromKeycloak(): Observable<T[]>;
 
   private updateResource(items: T[]): void {
     this.stateResource.next(createStateResource(items));
   }
 
-  public create(item: Partial<T>): Observable<boolean> {
-    return this.handleLoading(this.createInKeycloak(item));
+  public create(item: Partial<T>): Observable<StateResource<T>> {
+    return this.handleLoading<T>(this._createInKeycloak(item));
   }
 
-  protected abstract createInKeycloak(item: Partial<T>): Observable<T>;
+  protected abstract _createInKeycloak(item: Partial<T>): Observable<T>;
 
-  public save(item: T): Observable<boolean> {
-    return this.handleLoading(this.saveInKeycloak(item));
+  public save(item: T): Observable<StateResource<T>> {
+    return this.handleLoading<T>(this._saveInKeycloak(item));
   }
 
-  protected abstract saveInKeycloak(item: T): Observable<void>;
+  protected abstract _saveInKeycloak(item: T): Observable<T>;
 
-  public delete(id: string): Observable<boolean> {
-    return this.handleLoading(this.deleteInKeycloak(id));
+  public delete(id: string): Observable<StateResource<unknown>> {
+    return this.handleLoading(this._deleteInKeycloak(id));
   }
 
-  protected abstract deleteInKeycloak(id: string): Observable<void>;
+  protected abstract _deleteInKeycloak(id: string): Observable<void>;
 
-  handleLoading(action: Observable<unknown>): Observable<boolean> {
+  handleLoading<D>(action: Observable<D>): Observable<StateResource<D>> {
     this.setLoading();
-    return this.progress(this.refreshAfterFirstEmit(action));
+    return this.setLoadingInStateResource<D>(this.refreshAfterFirstEmit<D>(action));
   }
 
-  refreshAfterFirstEmit(action: Observable<unknown>): Observable<unknown> {
+  refreshAfterFirstEmit<D>(action: Observable<D>): Observable<D> {
     return action.pipe(
       first(),
-      tap(() => this.refresh()),
+      tap((): void => this.refresh()),
     );
   }
 
-  progress(action: Observable<unknown>): Observable<boolean> {
+  setLoadingInStateResource<D>(action: Observable<D>): Observable<StateResource<D>> {
     return action.pipe(
-      map(() => false),
-      startWith(true),
+      map((value: D): StateResource<D> => createStateResource<D>(value)),
+      startWith(createEmptyStateResource<D>(true)),
     );
   }
 
@@ -92,7 +96,7 @@ export abstract class KeycloakResourceService<T> {
 
   refresh(): void {
     this.stateResource.next({
-      ...createEmptyStateResource(),
+      ...createStateResource<T[]>([]),
       reload: true,
     });
   }
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
index 001f591f358f74c4fda4ea438e40e06268c6b162..043e5c2e056bb11eb29983c5eef09ce0fa17a74e 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
@@ -21,8 +21,7 @@ describe('AdminOrganisationsEinheitRepository', () => {
   });
 
   describe('getList', () => {
-    const groupRep: GroupRepresentation = createGroupRep();
-    const groupRepArray: GroupRepresentation[] = [groupRep, groupRep, groupRep];
+    const groupRepArray: GroupRepresentation[] = Array.from({ length: 3 }, createGroupRep);
 
     beforeEach(() => {
       kcAdminClient.groups = <any>{
@@ -34,12 +33,36 @@ describe('AdminOrganisationsEinheitRepository', () => {
       repository.getList();
       expect(kcAdminClient.groups['find']).toHaveBeenCalled();
     });
+
+    it('should return groups as organisationsEinheiten', (done) => {
+      const groupRepNames: AdminOrganisationsEinheit[] = groupRepArray.map(
+        (group: GroupRepresentation): AdminOrganisationsEinheit => ({
+          name: group.name,
+          id: group.id,
+        }),
+      );
+
+      repository.getList().subscribe((result: AdminOrganisationsEinheit[]): void => {
+        expect(result).toEqual(groupRepNames);
+        done();
+      });
+    });
+
+    it('should return empty array if no groups found', (done) => {
+      (<any>kcAdminClient.groups).find = jest.fn().mockReturnValue(Promise.resolve(null));
+
+      repository.getList().subscribe((result: AdminOrganisationsEinheit[]): void => {
+        expect(result).toEqual([]);
+        done();
+      });
+    });
   });
 
   describe('create', () => {
     const groupRep: GroupRepresentation = createGroupRep();
-    const organisationseinheit: AdminOrganisationsEinheit = {
+    const organisationsEinheit: AdminOrganisationsEinheit = {
       name: groupRep.name,
+      id: groupRep.id,
     };
 
     beforeEach(() => {
@@ -49,13 +72,13 @@ describe('AdminOrganisationsEinheitRepository', () => {
     });
 
     it('should call kcAdminClient groups create', () => {
-      repository.create(organisationseinheit);
+      repository.create(organisationsEinheit);
       expect(kcAdminClient.groups['create']).toHaveBeenCalled();
     });
 
-    it('should map group to organisationseinheit', (done) => {
-      repository.create(organisationseinheit).subscribe((result) => {
-        expect(result).toEqual(organisationseinheit);
+    it('should return result as organisationseinheit', (done) => {
+      repository.create(organisationsEinheit).subscribe((result: AdminOrganisationsEinheit): void => {
+        expect(result).toEqual(organisationsEinheit);
         done();
       });
     });
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts
index 3adc720bf780ff07752a434598d3c3abb1645c17..5dc1b0ee3bf1ea39b1668edf2fa7379a6836f81f 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts
@@ -11,11 +11,15 @@ export class AdminOrganisationsEinheitRepository {
   private readonly kcAdminClient = inject(KcAdminClient);
 
   public getList(): Observable<AdminOrganisationsEinheit[]> {
-    return this.getGroupsInKeycloak().pipe(map(this.mapToOrganisationsEinheiten));
+    return this.getGroupsInKeycloak().pipe(
+      map((groupReps: GroupRepresentation[]): AdminOrganisationsEinheit[] => this.mapToOrganisationsEinheiten(groupReps)),
+    );
   }
 
   private getGroupsInKeycloak(): Observable<GroupRepresentation[]> {
-    return from(this.kcAdminClient.groups.find({ briefRepresentation: false }));
+    return from(this.kcAdminClient.groups.find({ briefRepresentation: false })).pipe(
+      map((groups: GroupRepresentation[]): GroupRepresentation[] => groups || []),
+    );
   }
 
   public create(organisationseinheit: AdminOrganisationsEinheit): Observable<AdminOrganisationsEinheit> {
@@ -27,20 +31,15 @@ export class AdminOrganisationsEinheitRepository {
   }
 
   private mapToOrganisationsEinheiten(groupRepresentations: GroupRepresentation[]): AdminOrganisationsEinheit[] {
-    if (!groupRepresentations) {
-      return [];
-    }
-    //todo: warum geht hier groupRepresentations.map(mapToOrganisationsEinheit) nicht?
-    return groupRepresentations.map((group: GroupRepresentation) => {
-      return {
-        name: group.name,
-      };
-    });
+    return groupRepresentations.map(
+      (group: GroupRepresentation): AdminOrganisationsEinheit => this.mapToOrganisationsEinheit(group),
+    );
   }
 
-  private mapToOrganisationsEinheit = (group: GroupRepresentation): AdminOrganisationsEinheit => {
+  private mapToOrganisationsEinheit(group: GroupRepresentation): AdminOrganisationsEinheit {
     return {
+      id: group.id,
       name: group.name,
     };
-  };
+  }
 }
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
index 2c58c0f784361b21e27ca915453fb5b4748f632e..ae9c56bedd57177e3bac765ec968d7d00660794d 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
@@ -23,25 +23,37 @@
  */
 import { User } from '@admin-client/user-shared';
 import { UserRepository } from '@admin/keycloak-shared';
+import { StateResource } from '@alfa-client/tech-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { TestBed, fakeAsync, tick } from '@angular/core/testing';
 import { faker } from '@faker-js/faker';
 import KcAdminClient from '@keycloak/keycloak-admin-client';
 import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
 import MappingsRepresentation from '@keycloak/keycloak-admin-client/lib/defs/mappingsRepresentation';
-import { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
+import RoleRepresentation, { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
+import { Users } from '@keycloak/keycloak-admin-client/lib/resources/users';
 import { cold } from 'jest-marbles';
+import { omit } from 'lodash-es';
 import { throwError } from 'rxjs';
 import { createUser } from '../../../user-shared/test/user';
-import { UserAddFormservice } from '../../../user/src/lib/users-roles/user-add-form/user-add.formservice';
+import { UserFormService } from '../../../user/src/lib/user-form/user.formservice';
 
 describe('UserRepository', () => {
   let repository: UserRepository;
 
   let kcAdminClient: Mock<KcAdminClient>;
 
+  const user: User = createUser();
+  let kcAdminClientUsers: Mock<Users>;
+
   beforeEach(() => {
-    kcAdminClient = mock(KcAdminClient);
+    kcAdminClientUsers = {
+      ...mock(Users),
+      executeActionsEmail: jest.fn().mockImplementation(),
+      create: jest.fn().mockReturnValue(Promise.resolve({ id: user.id })),
+    };
+    kcAdminClient = { ...mock(KcAdminClient), users: <any>kcAdminClientUsers };
+
     TestBed.configureTestingModule({
       providers: [{ provide: KcAdminClient, useValue: kcAdminClient }],
     });
@@ -53,164 +65,359 @@ describe('UserRepository', () => {
   });
 
   describe('createInKeycloak', () => {
-    const user: User = createUser();
-
-    beforeEach(() => {
-      kcAdminClient.users = <any>{
-        create: jest.fn().mockReturnValue(Promise.resolve({ id: user.id })),
-        findOne: jest.fn().mockReturnValue(Promise.resolve(user)),
-        addClientRoleMappings: jest.fn().mockReturnValue(Promise.resolve()),
-        executeActionsEmail: jest.fn().mockReturnValue(Promise.resolve()),
-      };
-      kcAdminClient.clients = <any>{
-        find: jest.fn().mockReturnValue(Promise.resolve([{ id: faker.string.uuid() }])),
-        listRoles: jest.fn().mockReturnValue(Promise.resolve([{ id: faker.string.uuid(), name: faker.word.sample() }])),
-      };
-    });
-
     it('should call kcAdminClient users create', () => {
       repository.createInKeycloak(user);
 
-      expect(kcAdminClient.users['create']).toBeCalledWith(user);
+      expect(kcAdminClient.users['create']).toHaveBeenCalledWith(omit(user, 'groupIds'));
     });
 
     it('should call addUserRoles', fakeAsync(() => {
-      const addUserRolesSpy: jest.SpyInstance = jest.spyOn(repository, 'addUserRoles');
+      repository._addUserRoles = jest.fn();
 
       repository.createInKeycloak(user).subscribe();
       tick();
 
-      expect(addUserRolesSpy).toBeCalledWith(user.id, user.clientRoles);
+      expect(repository._addUserRoles).toHaveBeenCalledWith(user.id, user.clientRoles);
     }));
 
     it('should call sendActivationMail', (done) => {
-      const sendActivationMailSpy: jest.SpyInstance = jest.spyOn(repository, 'sendActivationMail');
-      jest.spyOn(repository, 'addUserRoles').mockReturnValue(Promise.resolve());
+      repository._sendActivationMail = jest.fn();
+      repository._addUserRoles = jest.fn().mockReturnValue(Promise.resolve());
 
       repository.createInKeycloak(user).subscribe(() => {
-        expect(sendActivationMailSpy).toBeCalledWith(user.id);
+        expect(repository._sendActivationMail).toHaveBeenCalledWith(user.id);
         done();
       });
     });
 
-    it('should call getUserById', (done) => {
-      const getUserByIdSpy: jest.SpyInstance = jest.spyOn(repository, 'getUserById');
+    it('should call handleError', fakeAsync(() => {
+      repository._handleCreateError = jest.fn();
+      kcAdminClient.users['create'] = jest.fn().mockReturnValue(throwError(() => new Error('error')));
 
-      repository.createInKeycloak(user).subscribe(() => {
-        expect(getUserByIdSpy).toBeCalledWith(user.id);
+      repository.createInKeycloak(user).subscribe({ error: () => {} });
+      tick();
+
+      expect(repository._handleCreateError).toHaveBeenCalled();
+    }));
+  });
+
+  describe('saveInKeycloak', () => {
+    beforeEach(() => {
+      kcAdminClient.users = <any>{
+        update: jest.fn().mockReturnValue(Promise.resolve()),
+      };
+
+      repository._addUserRoles = jest.fn().mockReturnValue(Promise.resolve());
+      repository._updateUserGroups = jest.fn().mockReturnValue(Promise.resolve());
+    });
+
+    it('should call kcAdminClient users update', () => {
+      repository.saveInKeycloak(user);
+
+      expect(kcAdminClient.users['update']).toHaveBeenCalledWith({ id: user.id }, omit(user, 'groupIds'));
+    });
+
+    it('should call addUserRoles', fakeAsync(() => {
+      repository.saveInKeycloak(user).subscribe();
+      tick();
+
+      expect(repository._addUserRoles).toHaveBeenCalledWith(user.id, user.clientRoles);
+    }));
+
+    it('should call updateUserGroups', (done) => {
+      repository.saveInKeycloak(user).subscribe(() => {
+        expect(repository._updateUserGroups).toHaveBeenCalledWith(user.id, user.groupIds);
         done();
       });
     });
 
     it('should call handleError', fakeAsync(() => {
-      const handleErrorSpy: jest.SpyInstance = jest.spyOn(repository, 'handleError');
-      kcAdminClient.users['create'] = jest.fn().mockReturnValue(throwError(() => new Error('error')));
+      repository._handleSaveError = jest.fn();
+      kcAdminClient.users['update'] = jest.fn().mockReturnValue(throwError(() => new Error('error')));
 
-      repository.createInKeycloak(user).subscribe({ error: () => {} });
+      repository.saveInKeycloak(user).subscribe({ error: () => {} });
       tick();
 
-      expect(handleErrorSpy).toHaveBeenCalled();
+      expect(repository._handleSaveError).toHaveBeenCalled();
     }));
+  });
 
-    describe('addUserRoles', () => {
-      it('should call addUserRolesForClient for admin', async () => {
-        const addUserRolesForClientSpy: jest.SpyInstance = jest.spyOn(repository, 'addUserRolesForClient');
+  describe('updateUserGroups', () => {
+    const oldGroups: string[] = Array.from({ length: 3 }, faker.string.uuid);
 
-        await repository.addUserRoles(user.id, { admin: [UserAddFormservice.ADMIN], alfa: [] });
+    beforeEach(() => {
+      repository._getOldUserGroupIds = jest.fn().mockReturnValue(Promise.resolve(oldGroups));
+      repository._deleteUserGroups = jest.fn();
+      repository._addUserGroups = jest.fn();
+    });
 
-        expect(addUserRolesForClientSpy).toBeCalledWith(user.id, [UserAddFormservice.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
-      });
+    it('should call getOldUserGroups', async () => {
+      await repository._updateUserGroups(user.id, user.groups);
 
-      it('should call addUserRolesForClient for admin', async () => {
-        const addUserRolesForClientSpy: jest.SpyInstance = jest.spyOn(repository, 'addUserRolesForClient');
+      expect(repository._getOldUserGroupIds).toHaveBeenCalled();
+    });
 
-        await repository.addUserRoles(user.id, { alfa: [UserAddFormservice.POSTSTELLE], admin: [] });
+    it('should call deleteUserGroups', async () => {
+      await repository._updateUserGroups(user.id, user.groups);
 
-        expect(addUserRolesForClientSpy).toBeCalledWith(
-          user.id,
-          [UserAddFormservice.POSTSTELLE],
-          UserRepository.ALFA_CLIENT_NAME,
-        );
-      });
+      expect(repository._deleteUserGroups).toHaveBeenCalledWith(user.id, user.groups, oldGroups);
+    });
 
-      it('should not call addUserRolesForClient if clientRoles alfa and admin are empty', async () => {
-        const addUserRolesForClientSpy: jest.SpyInstance = jest.spyOn(repository, 'addUserRolesForClient');
+    it('should call addUserGroups', async () => {
+      await repository._updateUserGroups(user.id, user.groups);
 
-        await repository.addUserRoles(user.id, { admin: [], alfa: [] });
+      expect(repository._addUserGroups).toHaveBeenCalledWith(user.id, user.groups, oldGroups);
+    });
+  });
 
-        expect(addUserRolesForClientSpy).not.toHaveBeenCalled();
-      });
+  describe('getOldUserGroupIds', () => {
+    const groupReps: GroupRepresentation[] = Array.from({ length: 3 }, () => ({ id: faker.string.uuid() }));
+    const groupIds: string[] = groupReps.map((group) => group.id);
+
+    beforeEach(() => {
+      kcAdminClient.users = <any>{
+        listGroups: jest.fn().mockReturnValue(Promise.resolve(groupReps)),
+      };
     });
 
-    describe('addUserRolesForClient', () => {
-      const clientId: string = faker.string.uuid();
-      const roleMapping: RoleMappingPayload[] = [{ id: faker.string.uuid(), name: faker.word.sample() }];
-      let getClientIdSpy: jest.SpyInstance;
-      let mapUserRolesSpy: jest.SpyInstance;
-      let addUserRolesInKeycloak: jest.SpyInstance;
-
-      beforeEach(() => {
-        getClientIdSpy = jest.spyOn(repository, 'getClientId').mockReturnValue(Promise.resolve(clientId));
-        mapUserRolesSpy = jest.spyOn(repository, 'mapUserRoles').mockReturnValue(Promise.resolve(roleMapping));
-        addUserRolesInKeycloak = jest.spyOn(repository, 'addUserRolesInKeycloak');
-      });
+    it('should call kcAdminClient users listGroups', async () => {
+      await repository._getOldUserGroupIds(user.id);
 
-      it('should call getClientId', async () => {
-        await repository.addUserRolesForClient(user.id, [UserAddFormservice.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
+      expect(kcAdminClient.users['listGroups']).toHaveBeenCalledWith({ id: user.id });
+    });
 
-        expect(getClientIdSpy).toBeCalled();
-      });
+    it('should return group ids', async () => {
+      const result: string[] = await repository._getOldUserGroupIds(user.id);
 
-      it('should call getAlfaClientId', async () => {
-        await repository.addUserRolesForClient(user.id, [UserAddFormservice.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
+      expect(result).toEqual(groupIds);
+    });
+  });
 
-        expect(mapUserRolesSpy).toHaveBeenCalledWith(clientId, [UserAddFormservice.ADMIN]);
-      });
+  describe('deleteUserGroups', () => {
+    const oldUserGroupIds: string[] = Array.from({ length: 2 }, faker.string.uuid);
+    const newUserGroupIds: string[] = [oldUserGroupIds[0]];
 
-      it('should call addUserRolesInKeycloak', async () => {
-        await repository.addUserRolesForClient(user.id, [UserAddFormservice.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
+    beforeEach(() => {
+      kcAdminClient.users = <any>{
+        delFromGroup: jest.fn().mockReturnValue(Promise.resolve()),
+      };
+    });
 
-        expect(addUserRolesInKeycloak).toHaveBeenCalledWith(user.id, clientId, roleMapping);
-      });
+    it('should call kcAdminClient users listGroups to be called', async () => {
+      await repository._deleteUserGroups(user.id, newUserGroupIds, oldUserGroupIds);
+
+      expect(kcAdminClient.users['delFromGroup']).toHaveBeenCalledWith({ id: user.id, groupId: oldUserGroupIds[1] });
     });
 
-    describe('sendActivationMail', () => {
-      it('should call kcAdminClient users executeActionsEmail', () => {
-        const userId: string = faker.string.uuid();
+    it('should call kcAdminClient users listGroups for every group to delete', async () => {
+      await repository._deleteUserGroups(user.id, [], oldUserGroupIds);
+
+      expect(kcAdminClient.users['delFromGroup']).toHaveBeenCalledTimes(oldUserGroupIds.length);
+    });
+  });
 
-        repository.sendActivationMail(userId);
+  describe('addUserGroups', () => {
+    const newUserGroupIds: string[] = Array.from({ length: 2 }, faker.string.uuid);
+    const oldUserGroupIds: string[] = [newUserGroupIds[0]];
 
-        expect(kcAdminClient.users['executeActionsEmail']).toBeCalledWith({
-          id: userId,
-          actions: ['VERIFY_EMAIL'],
-          lifespan: 3600 * 24 * 7,
-        });
-      });
+    beforeEach(() => {
+      kcAdminClient.users = <any>{
+        addToGroup: jest.fn().mockReturnValue(Promise.resolve()),
+      };
     });
 
-    describe('getUserById', () => {
-      it('should call kcAdminClient users findOne', () => {
-        const userId: string = faker.string.uuid();
+    it('should call kcAdminClient users addToGroup', () => {
+      repository._addUserGroups(user.id, newUserGroupIds, oldUserGroupIds);
 
-        repository.getUserById(userId);
+      expect(kcAdminClient.users['addToGroup']).toHaveBeenCalledWith({ id: user.id, groupId: newUserGroupIds[1] });
+    });
 
-        expect(kcAdminClient.users['findOne']).toBeCalledWith({ id: userId });
-      });
+    it('should call kcAdminClient users addToGroup for every group', () => {
+      const groups = Array.from({ length: 3 }, () => faker.string.uuid());
+      user.groups = groups;
+      repository._addUserGroups(user.id, newUserGroupIds, []);
+
+      expect(kcAdminClient.users['addToGroup']).toHaveBeenCalledTimes(newUserGroupIds.length);
+    });
+  });
+
+  describe('addUserRoles', () => {
+    it('should call addUserRolesForClient for admin', async () => {
+      repository._addUserRolesForClient = jest.fn();
+
+      await repository._addUserRoles(user.id, { admin: [UserFormService.ADMIN], alfa: [] });
+
+      expect(repository._addUserRolesForClient).toHaveBeenCalledWith(
+        user.id,
+        [UserFormService.ADMIN],
+        UserRepository.ADMIN_CLIENT_NAME,
+      );
+    });
+
+    it('should call addUserRolesForClient for admin', async () => {
+      repository._addUserRolesForClient = jest.fn();
+
+      await repository._addUserRoles(user.id, { alfa: [UserFormService.POSTSTELLE], admin: [] });
+
+      expect(repository._addUserRolesForClient).toHaveBeenCalledWith(
+        user.id,
+        [UserFormService.POSTSTELLE],
+        UserRepository.ALFA_CLIENT_NAME,
+      );
+    });
+
+    it('should not call addUserRolesForClient if clientRoles alfa and admin are empty', async () => {
+      repository._addUserRolesForClient = jest.fn();
+
+      await repository._addUserRoles(user.id, { admin: [], alfa: [] });
+
+      expect(repository._addUserRolesForClient).not.toHaveBeenCalled();
+    });
+  });
+
+  describe('addUserRolesForClient', () => {
+    const clientId: string = faker.string.uuid();
+    const roleMapping: RoleMappingPayload[] = [{ id: faker.string.uuid(), name: faker.word.sample() }];
+
+    beforeEach(() => {
+      repository._getClientId = jest.fn().mockReturnValue(Promise.resolve(clientId));
+      repository._mapUserRoles = jest.fn().mockReturnValue(Promise.resolve(roleMapping));
+      repository._addUserRolesInKeycloak = jest.fn();
+
+      kcAdminClient.users = <any>{
+        addClientRoleMappings: jest.fn().mockReturnValue(Promise.resolve()),
+      };
     });
 
-    describe('handleError', () => {
-      it('should throw error', () => {
-        const error: Error = new Error('error');
-        const result = repository.handleError(error);
+    it('should call getClientId', async () => {
+      await repository._addUserRolesForClient(user.id, [UserFormService.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
 
-        expect(result).toBeObservable(cold('#', null, new Error('An error occurred while creating the user.')));
+      expect(repository._getClientId).toHaveBeenCalled();
+    });
+
+    it('should call getAlfaClientId', async () => {
+      await repository._addUserRolesForClient(user.id, [UserFormService.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
+
+      expect(repository._mapUserRoles).toHaveBeenCalledWith(clientId, [UserFormService.ADMIN]);
+    });
+
+    it('should call addUserRolesInKeycloak', async () => {
+      await repository._addUserRolesForClient(user.id, [UserFormService.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
+
+      expect(repository._addUserRolesInKeycloak).toHaveBeenCalledWith(user.id, clientId, roleMapping);
+    });
+  });
+
+  describe('getclientId', () => {
+    const clientId = faker.string.uuid();
+
+    beforeEach(() => {
+      kcAdminClient.clients = <any>{
+        find: jest.fn().mockReturnValue(Promise.resolve([{ id: clientId }])),
+      };
+    });
+
+    it('should call kcAdminClient clients find', async () => {
+      await repository._getClientId(UserRepository.ADMIN_CLIENT_NAME);
+
+      expect(kcAdminClient.clients['find']).toHaveBeenCalledWith({ clientId: UserRepository.ADMIN_CLIENT_NAME });
+    });
+
+    it('should return clientId', async () => {
+      const result: string = await repository._getClientId(UserRepository.ADMIN_CLIENT_NAME);
+
+      expect(result).toEqual(clientId);
+    });
+  });
+
+  describe('mapUserRoles', () => {
+    const clientId: string = faker.string.uuid();
+    const clientRoles: RoleRepresentation[] = Array.from({ length: 3 }, () => ({
+      id: faker.string.uuid(),
+      name: faker.word.sample(),
+    }));
+    const userRoles: string[] = clientRoles.map((role) => role.name).slice(1);
+
+    beforeEach(() => {
+      kcAdminClient.clients = <any>{
+        listRoles: jest.fn().mockReturnValue(Promise.resolve(clientRoles)),
+      };
+    });
+
+    it('should call kcAdminClient clients listRoles', async () => {
+      await repository._mapUserRoles(clientId, userRoles);
+
+      expect(kcAdminClient.clients['listRoles']).toHaveBeenCalledWith({ id: clientId });
+    });
+
+    it('should return roleMapping', async () => {
+      const result: RoleMappingPayload[] = await repository._mapUserRoles(clientId, userRoles);
+
+      expect(result).toEqual(clientRoles.slice(1).map((role) => ({ id: role.id, name: role.name })));
+    });
+
+    it('should filter roles if they are not in clientRoles', async () => {
+      const result: RoleMappingPayload[] = await repository._mapUserRoles(clientId, [faker.word.sample()]);
+
+      expect(result).toEqual([]);
+    });
+  });
+
+  describe('addUserRolesInKeycloak', () => {
+    beforeEach(() => {
+      kcAdminClient.users = <any>{
+        addClientRoleMappings: jest.fn().mockReturnValue(Promise.resolve()),
+      };
+    });
+
+    it('should call kcAdminClient users addClientRoleMappings', async () => {
+      const clientId: string = faker.string.uuid();
+      const roles: RoleMappingPayload[] = Array.from({ length: 3 }, () => ({
+        id: faker.string.uuid(),
+        name: faker.word.sample(),
+      }));
+
+      await repository._addUserRolesInKeycloak(user.id, clientId, roles);
+
+      expect(kcAdminClient.users['addClientRoleMappings']).toHaveBeenCalledWith({ id: user.id, clientUniqueId: clientId, roles });
+    });
+  });
+
+  describe('sendActivationMail', () => {
+    it('should call kcAdminClient users executeActionsEmail', () => {
+      const userId: string = faker.string.uuid();
+
+      repository._sendActivationMail(userId);
+
+      expect(kcAdminClientUsers.executeActionsEmail).toHaveBeenCalledWith({
+        id: userId,
+        actions: ['VERIFY_EMAIL'],
+        lifespan: 3600 * 24 * 7,
       });
     });
   });
 
+  describe('handleCreateError', () => {
+    it('should throw error', () => {
+      const error: Error = new Error('error');
+      const result = repository._handleCreateError(error);
+
+      expect(result).toBeObservable(cold('#', null, new Error('An error occurred while creating the user.')));
+    });
+  });
+
+  describe('handleSaveError', () => {
+    it('should throw error', () => {
+      const error: Error = new Error('error');
+      const result = repository._handleSaveError(error);
+
+      expect(result).toBeObservable(cold('#', null, new Error('An error occurred while saving the user.')));
+    });
+  });
+
   describe('getUsers', () => {
-    const userRep: User = createUser();
-    const userRepArray: User[] = [userRep, userRep, userRep];
+    const user: User = createUser();
+    const userArray: User[] = [user, user, user];
     const group: string = faker.word.sample();
     const alfaRole: string = faker.word.sample();
     const adminRole: string = faker.word.sample();
@@ -225,7 +432,7 @@ describe('UserRepository', () => {
     beforeEach(() => {
       jest.clearAllMocks();
       kcAdminClient.users = <any>{
-        find: jest.fn().mockReturnValue(Promise.resolve(userRepArray)),
+        find: jest.fn().mockReturnValue(Promise.resolve(userArray)),
         listGroups: jest.fn().mockReturnValue(Promise.resolve(groupRep)),
         listRoleMappings: jest.fn().mockReturnValue(Promise.resolve(roleRep)),
       };
@@ -238,32 +445,32 @@ describe('UserRepository', () => {
     });
 
     it('should call mapToUser', fakeAsync(() => {
-      const mapToUser: jest.SpyInstance<User> = jest.spyOn(repository, 'mapToUser');
+      repository._mapToUser = jest.fn().mockReturnValue(user);
 
       repository.getUsers().subscribe();
       tick();
 
-      expect(mapToUser).toBeCalledTimes(userRepArray.length);
+      expect(repository._mapToUser).toHaveBeenCalledTimes(userArray.length);
     }));
 
     it('should call kcadminClient listGroups for every user', fakeAsync(() => {
       repository.getUsers().subscribe();
       tick();
 
-      expect(kcAdminClient.users['listGroups']).toBeCalledTimes(userRepArray.length);
+      expect(kcAdminClient.users['listGroups']).toHaveBeenCalledTimes(userArray.length);
     }));
 
     it('should call kcadminClient listRoleMappings for every user', fakeAsync(() => {
       repository.getUsers().subscribe();
       tick();
 
-      expect(kcAdminClient.users['listRoleMappings']).toBeCalledTimes(userRepArray.length);
+      expect(kcAdminClient.users['listRoleMappings']).toHaveBeenCalledTimes(userArray.length);
     }));
 
     it('should return users with groups and roles', (done) => {
       repository.getUsers().subscribe((users: User[]) => {
         users.forEach((user) =>
-          expect(user).toEqual({ ...userRep, groups: [group], clientRoles: { alfa: [alfaRole], admin: [adminRole] } }),
+          expect(user).toEqual({ ...user, groups: [group], clientRoles: { alfa: [alfaRole], admin: [adminRole] } }),
         );
         done();
       });
@@ -274,7 +481,57 @@ describe('UserRepository', () => {
       kcAdminClient.users['listRoleMappings'] = jest.fn().mockReturnValue(Promise.resolve({}));
 
       repository.getUsers().subscribe((users: User[]) => {
-        users.forEach((user) => expect(user).toEqual({ ...userRep, groups: [], clientRoles: { alfa: [], admin: [] } }));
+        users.forEach((user) => expect(user).toEqual({ ...user, groups: [], clientRoles: { alfa: [], admin: [] } }));
+        done();
+      });
+    });
+  });
+
+  describe('getUserById', () => {
+    const user: User = createUser();
+    const group: string = faker.word.sample();
+    const alfaRole: string = faker.word.sample();
+    const adminRole: string = faker.word.sample();
+    const groupRep: GroupRepresentation[] = [{ name: group }];
+    const roleRep: MappingsRepresentation = {
+      clientMappings: {
+        alfa: { mappings: [{ name: alfaRole }] },
+        admin: { mappings: [{ name: adminRole }] },
+      },
+    };
+
+    beforeEach(() => {
+      jest.clearAllMocks();
+      kcAdminClient.users = <any>{
+        findOne: jest.fn().mockReturnValue(Promise.resolve(user)),
+        listGroups: jest.fn().mockReturnValue(Promise.resolve(groupRep)),
+        listRoleMappings: jest.fn().mockReturnValue(Promise.resolve(roleRep)),
+      };
+    });
+
+    it('should call kcAdminClient users findOne', () => {
+      repository.getUserById(user.id);
+
+      expect(kcAdminClient.users['findOne']).toHaveBeenCalledWith({ id: user.id });
+    });
+
+    it('should call kcAdminClient users listGroups', fakeAsync(() => {
+      repository.getUserById(user.id).subscribe();
+      tick();
+
+      expect(kcAdminClient.users['listGroups']).toHaveBeenCalledWith({ id: user.id });
+    }));
+
+    it('should call kcAdminClient users listRoleMappings', fakeAsync(() => {
+      repository.getUserById(user.id).subscribe();
+      tick();
+
+      expect(kcAdminClient.users['listRoleMappings']).toHaveBeenCalledWith({ id: user.id });
+    }));
+
+    it('should return user with groups and roles', (done) => {
+      repository.getUserById(user.id).subscribe((userState: StateResource<User>) => {
+        expect(userState.resource).toEqual({ ...user, groups: [group], clientRoles: { alfa: [alfaRole], admin: [adminRole] } });
         done();
       });
     });
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
index 3cc644b06842127a2d4d62a79137b13a4957b22e..130176623c25c1cf1f848643b0a5687906fbae34 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
@@ -22,6 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { ClientMapping, ClientRoles, User } from '@admin-client/user-shared';
+import { createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { inject, Injectable } from '@angular/core';
 import KcAdminClient from '@keycloak/keycloak-admin-client';
 import ClientRepresentation from '@keycloak/keycloak-admin-client/lib/defs/clientRepresentation';
@@ -29,8 +30,8 @@ import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupR
 import MappingsRepresentation from '@keycloak/keycloak-admin-client/lib/defs/mappingsRepresentation';
 import RoleRepresentation, { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
 import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation';
-import { isNil } from 'lodash-es';
-import { catchError, concatMap, forkJoin, from, map, mergeMap, Observable, switchMap, tap, throwError } from 'rxjs';
+import { isNil, omit } from 'lodash-es';
+import { catchError, concatMap, forkJoin, from, map, mergeMap, Observable, tap, throwError } from 'rxjs';
 
 @Injectable({
   providedIn: 'root',
@@ -41,45 +42,90 @@ export class UserRepository {
   public static readonly ALFA_CLIENT_NAME: string = 'alfa';
   public static readonly ADMIN_CLIENT_NAME: string = 'admin';
 
-  public createInKeycloak(user: Partial<User>): Observable<User> {
-    return from(this.kcAdminClient.users.create(user)).pipe(
-      concatMap(async (response: { id: string }) => {
-        await this.addUserRoles(response.id, user.clientRoles);
+  public createInKeycloak(user: User): Observable<User> {
+    return from(this.kcAdminClient.users.create(omit(user, 'groupIds'))).pipe(
+      concatMap(async (response: { id: string }): Promise<{ id: string }> => {
+        await this._addUserRoles(response.id, user.clientRoles);
         return response;
       }),
-      tap((response: { id: string }) => this.sendActivationMail(response.id)),
-      switchMap((response: { id: string }): Observable<User> => this.getUserById(response.id)),
-      catchError((err) => this.handleError(err)),
+      tap((response: { id: string }): void => this._sendActivationMail(response.id)),
+      map((): User => user),
+      catchError((err: Error): Observable<never> => this._handleCreateError(err)),
     );
   }
 
-  async addUserRoles(userId: string, clientRoles: ClientRoles): Promise<void> {
+  public saveInKeycloak(user: User): Observable<User> {
+    const { groupIds, ...userToSave } = user;
+    return from(this.kcAdminClient.users.update({ id: user.id }, userToSave)).pipe(
+      concatMap(async (): Promise<void> => {
+        await this._addUserRoles(user.id, user.clientRoles);
+        await this._updateUserGroups(user.id, user.groupIds);
+      }),
+      map((): User => user),
+      catchError((err: Error): Observable<never> => this._handleSaveError(err)),
+    );
+  }
+
+  async _updateUserGroups(userId: string, newGroupIds: string[]): Promise<void> {
+    const oldUserGroups: string[] = await this._getOldUserGroupIds(userId);
+    await this._deleteUserGroups(userId, newGroupIds, oldUserGroups);
+    await this._addUserGroups(userId, newGroupIds, oldUserGroups);
+  }
+
+  async _getOldUserGroupIds(userId: string): Promise<string[]> {
+    const oldUserGroupsReps: GroupRepresentation[] = await this.kcAdminClient.users.listGroups({ id: userId });
+    return oldUserGroupsReps.map((group: GroupRepresentation): string => group.id);
+  }
+
+  async _deleteUserGroups(userId: string, newGroupIds: string[], oldGroupIds: string[]): Promise<void> {
+    await Promise.all(
+      oldGroupIds
+        .filter((group) => !newGroupIds.includes(group))
+        .map(async (groupId: string) => {
+          await this.kcAdminClient.users.delFromGroup({ id: userId, groupId });
+        }),
+    );
+  }
+
+  async _addUserGroups(userId: string, newGroupIds: string[], oldGroupIds): Promise<void> {
+    await Promise.all(
+      newGroupIds
+        .filter((group) => !oldGroupIds.includes(group))
+        .map(async (groupId: string) => {
+          await this.kcAdminClient.users.addToGroup({ id: userId, groupId: groupId });
+        }),
+    );
+  }
+
+  async _addUserRoles(userId: string, clientRoles: ClientRoles): Promise<void> {
     if (clientRoles.admin.length > 0) {
-      await this.addUserRolesForClient(userId, clientRoles.admin, UserRepository.ADMIN_CLIENT_NAME);
+      await this._addUserRolesForClient(userId, clientRoles.admin, UserRepository.ADMIN_CLIENT_NAME);
     }
 
     if (clientRoles.alfa.length > 0) {
-      await this.addUserRolesForClient(userId, clientRoles.alfa, UserRepository.ALFA_CLIENT_NAME);
+      await this._addUserRolesForClient(userId, clientRoles.alfa, UserRepository.ALFA_CLIENT_NAME);
     }
   }
 
-  async addUserRolesForClient(userId: string, userRoles: string[], client: string): Promise<void> {
-    const clientId: string = await this.getClientId(client);
-    const roles: RoleMappingPayload[] = await this.mapUserRoles(clientId, userRoles);
-    await this.addUserRolesInKeycloak(userId, clientId, roles);
+  async _addUserRolesForClient(userId: string, userRoles: string[], client: string): Promise<void> {
+    const clientId: string = await this._getClientId(client);
+    const roles: RoleMappingPayload[] = await this._mapUserRoles(clientId, userRoles);
+    await this._addUserRolesInKeycloak(userId, clientId, roles);
   }
 
-  async getClientId(client: string): Promise<string | undefined> {
+  async _getClientId(client: string): Promise<string | undefined> {
     const clients: ClientRepresentation[] = await this.kcAdminClient.clients.find({ clientId: client });
     return clients?.[0].id;
   }
 
-  async mapUserRoles(clientId: string, userRoles: string[]): Promise<RoleMappingPayload[]> {
+  async _mapUserRoles(clientId: string, userRoles: string[]): Promise<RoleMappingPayload[]> {
     const roles: RoleRepresentation[] = await this.kcAdminClient.clients.listRoles({ id: clientId });
-    return roles.filter((role) => userRoles.includes(role.name)).map((role) => ({ id: role.id, name: role.name }));
+    return roles
+      .filter((role: RoleRepresentation): boolean => userRoles.includes(role.name))
+      .map((role: RoleRepresentation): RoleMappingPayload => ({ id: role.id, name: role.name }));
   }
 
-  async addUserRolesInKeycloak(userId: string, clientId: string, roles: RoleMappingPayload[]): Promise<void> {
+  async _addUserRolesInKeycloak(userId: string, clientId: string, roles: RoleMappingPayload[]): Promise<void> {
     await this.kcAdminClient.users.addClientRoleMappings({
       id: userId,
       clientUniqueId: clientId,
@@ -87,7 +133,7 @@ export class UserRepository {
     });
   }
 
-  sendActivationMail(userId: string): void {
+  _sendActivationMail(userId: string): void {
     this.kcAdminClient.users.executeActionsEmail({
       id: userId,
       actions: ['VERIFY_EMAIL'],
@@ -95,23 +141,29 @@ export class UserRepository {
     });
   }
 
-  getUserById(userId: string): Observable<User> {
-    return from(this.kcAdminClient.users.findOne({ id: userId })) as Observable<User>;
+  _handleCreateError(err: any): Observable<never> {
+    console.error('Error on create user in Keycloak:', err);
+    return throwError(() => new Error('An error occurred while creating the user.'));
   }
 
-  handleError(err: any): Observable<never> {
-    console.error('Error creating user in Keycloak:', err);
-    return throwError(() => new Error('An error occurred while creating the user.'));
+  _handleSaveError(err: any): Observable<never> {
+    console.error('Error on patch user in Keycloak:', err);
+    return throwError(() => new Error('An error occurred while saving the user.'));
   }
 
   public getUsers(): Observable<User[]> {
     return from(this.kcAdminClient.users.find()).pipe(
-      map((userReps: UserRepresentation[]) => userReps.map((userReps) => this.mapToUser(userReps))),
-      mergeMap((users) => forkJoin(users.map((user) => this.addInformationToUser(user)))),
+      map((userReps: UserRepresentation[]): User[] =>
+        userReps.map((userReps: UserRepresentation): User => this._mapToUser(userReps)),
+      ),
+      mergeMap(
+        (users: User[]): Observable<User[]> =>
+          forkJoin(users.map((user: User): Observable<User> => this.addInformationToUser(user))),
+      ),
     );
   }
 
-  mapToUser(userRepresentation: UserRepresentation): User {
+  _mapToUser(userRepresentation: UserRepresentation): User {
     return {
       id: userRepresentation.id,
       email: userRepresentation.email,
@@ -127,25 +179,38 @@ export class UserRepository {
     };
   }
 
+  public getUserById(userId: string): Observable<StateResource<User>> {
+    return this.getUserByIdWithoutRolesAndGroups(userId).pipe(
+      mergeMap((user: User): Observable<User> => this.addInformationToUser(user)),
+      map((user: User): StateResource<User> => createStateResource(user)),
+    );
+  }
+
+  private getUserByIdWithoutRolesAndGroups(userId: string): Observable<User> {
+    return from(this.kcAdminClient.users.findOne({ id: userId })) as Observable<User>;
+  }
+
   private addInformationToUser(user: User): Observable<User> {
     return forkJoin([this.getUserGroups(user), this.getClientRoles(user)]).pipe(
-      map(([groups, clientRoles]) => ({
-        ...user,
-        groups,
-        clientRoles,
-      })),
+      map(
+        ([groups, clientRoles]: [string[], ClientRoles]): User => ({
+          ...user,
+          groups,
+          clientRoles,
+        }),
+      ),
     );
   }
 
   private getUserGroups(user: User): Observable<string[]> {
     return from(this.kcAdminClient.users.listGroups({ id: user.id })).pipe(
-      map((groups: GroupRepresentation[]) => groups.map((group) => group.name)),
+      map((groups: GroupRepresentation[]): string[] => groups.map((group: GroupRepresentation): string => group.name)),
     );
   }
 
   private getClientRoles(user: User): Observable<ClientRoles> {
     return from(this.kcAdminClient.users.listRoleMappings({ id: user.id })).pipe(
-      map((roleMappings: MappingsRepresentation) => {
+      map((roleMappings: MappingsRepresentation): ClientRoles => {
         return {
           alfa: this.mapToClientRoleNames(roleMappings, UserRepository.ALFA_CLIENT_NAME),
           admin: this.mapToClientRoleNames(roleMappings, UserRepository.ADMIN_CLIENT_NAME),
@@ -161,6 +226,6 @@ export class UserRepository {
       return [];
     }
 
-    return clientMappingsAlfa.mappings.map((role: RoleRepresentation) => role.name);
+    return clientMappingsAlfa.mappings.map((role: RoleRepresentation): string => role.name);
   }
 }
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.model.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.model.ts
index 04edb2411d6fea072062b1f7e82b4fcb752f5100..8a4b105a948caf4f288a8639468d888d2fb3c255 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.model.ts
+++ b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.model.ts
@@ -22,5 +22,6 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 export interface AdminOrganisationsEinheit {
+  id?: string;
   name: string;
 }
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts
index 9432f6afd471dc29274a21701da07b25311efe29..db8b44f6aad3242e172a407fa6731ce992a60fcc 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts
+++ b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts
@@ -43,7 +43,7 @@ describe('AdminOrganisationsEinheitService', () => {
 
   describe('getItemsFromKeycloak', () => {
     it('should call repository getList', () => {
-      (service as any).getItemsFromKeycloak();
+      service._getItemsFromKeycloak();
       expect(repository.getList).toHaveBeenCalled();
     });
   });
@@ -51,7 +51,7 @@ describe('AdminOrganisationsEinheitService', () => {
   describe('createInKeycloak', () => {
     const organisationsEinheit: AdminOrganisationsEinheit = createAdminOrganisationsEinheit();
     it('should call repository create', () => {
-      (service as any).createInKeycloak(organisationsEinheit);
+      service._createInKeycloak(organisationsEinheit);
       expect(repository.create).toHaveBeenCalledWith(organisationsEinheit);
     });
   });
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts
index ad2e0009e9a52c4a8970a4cdbe3f5b53cfe1d175..5c12d0613ef05cc74acb0ca4ee61794c61c5e95c 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts
+++ b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts
@@ -21,10 +21,9 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { AdminOrganisationsEinheitRepository } from '@admin/keycloak-shared';
+import { AdminOrganisationsEinheitRepository, KeycloakResourceService } from '@admin/keycloak-shared';
 import { inject, Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
-import { KeycloakResourceService } from '../../../user-shared/src/lib/keycloak.resource.service';
 import { AdminOrganisationsEinheit } from './organisations-einheit.model';
 
 @Injectable({
@@ -33,19 +32,19 @@ import { AdminOrganisationsEinheit } from './organisations-einheit.model';
 export class AdminOrganisationsEinheitService extends KeycloakResourceService<AdminOrganisationsEinheit> {
   private readonly repository = inject(AdminOrganisationsEinheitRepository);
 
-  protected getItemsFromKeycloak(): Observable<AdminOrganisationsEinheit[]> {
+  _getItemsFromKeycloak(): Observable<AdminOrganisationsEinheit[]> {
     return this.repository.getList();
   }
 
-  protected createInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<AdminOrganisationsEinheit> {
+  _createInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<AdminOrganisationsEinheit> {
     return this.repository.create(organisationsEinheit);
   }
 
-  protected saveInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<void> {
+  _saveInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<AdminOrganisationsEinheit> {
     throw new Error('Method not implemented.');
   }
 
-  protected deleteInKeycloak(id: string): Observable<void> {
+  _deleteInKeycloak(id: string): Observable<void> {
     throw new Error('Method not implemented.');
   }
 }
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/test/organisations-einheit.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/test/organisations-einheit.ts
index 60a50a96fce79da0a37cefc04c0ee0c86b0c8287..6bb1baad301e83997665d96347628cf092f1d5ea 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/test/organisations-einheit.ts
+++ b/alfa-client/libs/admin/organisations-einheit-shared/src/test/organisations-einheit.ts
@@ -27,6 +27,7 @@ import { AdminOrganisationsEinheit } from '../lib/organisations-einheit.model';
 
 export function createAdminOrganisationsEinheit(): AdminOrganisationsEinheit {
   return {
+    id: faker.string.uuid(),
     name: faker.lorem.word(),
   };
 }
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
index e881fea429fe05ebd5904bdda6ab0560df6ea0e0..5fd68cc789206b701f2adad2c2d0f5280917b55d 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
@@ -55,7 +55,7 @@ describe('OrganisationsEinheitContainerComponent', () => {
   beforeEach(() => {
     organisationsEinheitService = {
       ...mock(AdminOrganisationsEinheitService),
-      get: jest.fn().mockReturnValue(of(organisationsEinheitListStateResource)),
+      getAll: jest.fn().mockReturnValue(of(organisationsEinheitListStateResource)),
       create: jest.fn().mockReturnValue(of(false)),
       refresh: jest.fn(),
     };
@@ -85,11 +85,11 @@ describe('OrganisationsEinheitContainerComponent', () => {
 
   describe('component', () => {
     describe('ngOnInit', () => {
-      it('should call organisationsEinheitService get', (done) => {
+      it('should call organisationsEinheitService getAll', (done) => {
         component.ngOnInit();
 
         component.organisationsEinheitenStateResource$.subscribe(() => {
-          expect(organisationsEinheitService.get).toHaveBeenCalled();
+          expect(organisationsEinheitService.getAll).toHaveBeenCalled();
           done();
         });
       });
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.ts
index 5c731384dfe222155a4186cf0021c811f878550b..a1b124b07e83e6496d5409cef4cdd271e826b842 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.ts
@@ -52,10 +52,10 @@ export class OrganisationsEinheitContainerComponent implements OnInit, OnDestroy
   private readonly viewContainerRef = inject(ViewContainerRef);
 
   organisationsEinheitenStateResource$: Observable<StateResource<AdminOrganisationsEinheit[]>>;
-  createOrganisationsEinheitProgress$: Observable<boolean>;
+  createOrganisationsEinheitProgress$: Observable<StateResource<AdminOrganisationsEinheit>>;
 
   ngOnInit(): void {
-    this.organisationsEinheitenStateResource$ = this.organisationsEinheitService.get();
+    this.organisationsEinheitenStateResource$ = this.organisationsEinheitService.getAll();
   }
 
   ngOnDestroy(): void {
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html
index 589d673083efa7f8378ff8755184ec612dd36062..fc5ff5f37637c6c1cf2b9aa687ef25b0678b41f3 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html
@@ -24,13 +24,12 @@
 
 -->
 <ods-list data-test-id="organisations-einheit-list">
-  <ods-list-item
-    *ngFor="let organisationsEinheit of organisationsEinheitList"
-    [attr.data-test-id]="(organisationsEinheit.name | convertForDataTest) + '-organisation-item'"
-  >
-    <dl class="flex-1 basis-3/4 font-semibold">
-      <dt class="sr-only">Name</dt>
-      <dd data-test-id="organisations-einheit-name">{{ organisationsEinheit.name }}</dd>
-    </dl>
-  </ods-list-item>
+  @for (organisationsEinheit of organisationsEinheitList; track $index) {
+    <ods-list-item [attr.data-test-id]="(organisationsEinheit.name | convertForDataTest) + '-organisation-item'">
+      <dl class="flex-1 basis-3/4 font-semibold">
+        <dt class="sr-only">Name</dt>
+        <dd data-test-id="organisations-einheit-name">{{ organisationsEinheit.name }}</dd>
+      </dl>
+    </ods-list-item>
+  }
 </ods-list>
diff --git a/alfa-client/libs/admin/postfach/src/lib/postfach-container/postfach-form/postfach.formservice.ts b/alfa-client/libs/admin/postfach/src/lib/postfach-container/postfach-form/postfach.formservice.ts
index 7ee0899b4a08d35c7f5099ed495fdb1d473db504..78d946e3e7dd0360469046ea80afcf47c4af7954 100644
--- a/alfa-client/libs/admin/postfach/src/lib/postfach-container/postfach-form/postfach.formservice.ts
+++ b/alfa-client/libs/admin/postfach/src/lib/postfach-container/postfach-form/postfach.formservice.ts
@@ -29,7 +29,7 @@ import { isNil } from 'lodash-es';
 import { Observable } from 'rxjs';
 
 @Injectable()
-export class PostfachFormService extends AbstractFormService {
+export class PostfachFormService extends AbstractFormService<PostfachResource> {
   private postfachService: PostfachService = inject(PostfachService);
 
   public static readonly ASBSENDER_GROUP: string = 'absender';
diff --git a/alfa-client/libs/admin/shared/src/lib/routes.ts b/alfa-client/libs/admin/shared/src/lib/routes.ts
index cad5201d211d507ca858dc60dde25a412dfe4ba7..090a9f3a7d82d6c3489bfa5c542b31592c177e06 100644
--- a/alfa-client/libs/admin/shared/src/lib/routes.ts
+++ b/alfa-client/libs/admin/shared/src/lib/routes.ts
@@ -21,12 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-export const ROUTES = {
-  POSTFACH: 'postfach',
-  BENUTZER_UND_ROLLEN: 'benutzer_und_rollen',
-  BENUTZER_UND_ROLLEN_NEU: 'benutzer_und_rollen/neu',
-  ORGANISATIONSEINHEITEN: 'organisationseinheiten',
-  UNAVAILABLE: 'unavailable',
-  STATISTIK: 'statistik',
-  STATISTIK_NEU: 'statistik/neu',
-};
+export enum ROUTES {
+  POSTFACH = 'postfach',
+  BENUTZER = 'benutzer',
+  BENUTZER_NEU = 'benutzer/neu',
+  BENUTZER_ID = 'benutzer/:userid',
+  ORGANISATIONSEINHEITEN = 'organisationseinheiten',
+  UNAVAILABLE = 'unavailable',
+  STATISTIK = 'statistik',
+  STATISTIK_NEU = 'statistik/neu',
+}
diff --git a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
index 2f6610d53b9da6db523e167b77d8c5396be6d99d..229a7147d1b785c937d46c45c3ae65070a8b2608 100644
--- a/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
+++ b/alfa-client/libs/admin/statistik/src/lib/statistik-fields-form/statistik-fields.formservice.ts
@@ -5,7 +5,7 @@ import { Resource } from '@ngxp/rest';
 import { EMPTY, Observable } from 'rxjs';
 
 @Injectable()
-export class StatistikFieldsFormService extends AbstractFormService {
+export class StatistikFieldsFormService extends AbstractFormService<Resource> {
   public static readonly FIELD_FORM_ENGINE: string = 'formEngine';
   public static readonly FIELD_FORM_ID: string = 'formId';
   public static readonly FIELD_DATA_FIELDS: string = 'dataFields';
diff --git a/alfa-client/libs/admin/user-shared/src/index.ts b/alfa-client/libs/admin/user-shared/src/index.ts
index 68d4aaf50b5a1c67e1863d432b5abf2d9d8f1bbb..9950f5b5bfae85361d73134e3dc14007d2c3278c 100644
--- a/alfa-client/libs/admin/user-shared/src/index.ts
+++ b/alfa-client/libs/admin/user-shared/src/index.ts
@@ -1,3 +1,4 @@
 export * from './lib/to-user-name.pipe';
+export * from './lib/to-user-roles.pipe';
 export * from './lib/user.model';
 export * from './lib/user.service';
diff --git a/alfa-client/libs/admin/user-shared/src/lib/to-user-roles.pipe.spec.ts b/alfa-client/libs/admin/user-shared/src/lib/to-user-roles.pipe.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..aaad9082add4085029088a193cfca68be0f74d71
--- /dev/null
+++ b/alfa-client/libs/admin/user-shared/src/lib/to-user-roles.pipe.spec.ts
@@ -0,0 +1,14 @@
+import { User } from '@admin-client/user-shared';
+import { createUser } from '../../test/user';
+import { ToUserRolesPipe } from './to-user-roles.pipe';
+
+describe('toUserRolesPipe', () => {
+  const user: User = createUser();
+  const getUserRolesPipe = new ToUserRolesPipe();
+
+  it('should return admin and alfa user roles', () => {
+    const roles: string[] = getUserRolesPipe.transform(user);
+
+    expect(roles).toEqual([...user.clientRoles.alfa, ...user.clientRoles.admin]);
+  });
+});
diff --git a/alfa-client/libs/admin/user-shared/src/lib/to-user-roles.pipe.ts b/alfa-client/libs/admin/user-shared/src/lib/to-user-roles.pipe.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6d42aeab19407425621b25369616e4501be74b7d
--- /dev/null
+++ b/alfa-client/libs/admin/user-shared/src/lib/to-user-roles.pipe.ts
@@ -0,0 +1,15 @@
+import { User } from '@admin-client/user-shared';
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+  name: 'toUserRoles',
+  standalone: true,
+})
+export class ToUserRolesPipe implements PipeTransform {
+  transform(user: User): string[] {
+    return Object.keys(user.clientRoles).reduce((acc: string[], client: string): string[] => {
+      acc.push(...user.clientRoles[client]);
+      return acc;
+    }, []);
+  }
+}
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.model.ts b/alfa-client/libs/admin/user-shared/src/lib/user.model.ts
index f6dcac00ce2ddc7b7e50c0f908271e4140eaadde..db185a0209450a60d50e2ffc89a263d62f480d12 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.model.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/user.model.ts
@@ -24,13 +24,14 @@
 import RoleRepresentation from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
 
 export interface User {
-  id: string;
+  id?: string;
   username: string;
   email: string;
   firstName: string;
   lastName: string;
   enabled: boolean;
-  groups?: string[];
+  groups: string[];
+  groupIds?: string[];
   clientRoles: ClientRoles;
 }
 
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts b/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts
index 4769d32ed5c7629d3dc157426e8b581afedc346e..28e7e8cce9ce062979c43175587834aa818724ea 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts
@@ -22,12 +22,16 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { UserRepository } from '@admin/keycloak-shared';
+import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { mock, Mock } from '@alfa-client/test-utils';
 import { fakeAsync, TestBed, tick } from '@angular/core/testing';
-import { of } from 'rxjs';
+import { cold } from 'jest-marbles';
+import { singleCold } from 'libs/tech-shared/test/marbles';
+import { Observable, of } from 'rxjs';
 import { createUser } from '../../test/user';
 import { User } from './user.model';
 import { UserService } from './user.service';
+
 import * as UserUtil from './user.util';
 
 describe('UserService', () => {
@@ -37,7 +41,8 @@ describe('UserService', () => {
   const user: User = createUser();
 
   beforeEach(() => {
-    repository = { ...mock(UserRepository), getUsers: jest.fn().mockReturnValue(of([user])) };
+    repository = { ...mock(UserRepository), getUsers: jest.fn().mockReturnValue(of([user])), getUserById: jest.fn() };
+
     TestBed.configureTestingModule({
       providers: [{ provide: UserRepository, useValue: repository }],
     });
@@ -46,7 +51,7 @@ describe('UserService', () => {
 
   describe('getItemsFromKeycloak', () => {
     it('should call getUsers from userRepository', () => {
-      (service as any).getItemsFromKeycloak();
+      service._getItemsFromKeycloak();
 
       expect(repository.getUsers).toHaveBeenCalled();
     });
@@ -54,7 +59,7 @@ describe('UserService', () => {
     it('should call sortUsersByLastName', fakeAsync(() => {
       const sortUsersByLastNameSpy: jest.SpyInstance<User[]> = jest.spyOn(UserUtil, 'sortUsersByLastName');
 
-      (service as any).getItemsFromKeycloak().subscribe();
+      service._getItemsFromKeycloak().subscribe();
       tick();
 
       expect(sortUsersByLastNameSpy).toHaveBeenCalled();
@@ -62,12 +67,38 @@ describe('UserService', () => {
   });
 
   describe('createInKeycloak', () => {
-    const user: User = createUser();
-
     it('should call createInKeycloak from userRepository', () => {
-      (service as any).createInKeycloak(user);
+      service._createInKeycloak(user);
 
       expect(repository.createInKeycloak).toHaveBeenCalledWith(user);
     });
   });
+
+  describe('saveInKeycloak', () => {
+    it('should call saveInKeycloak from userRepository', () => {
+      service._saveInKeycloak(user);
+
+      expect(repository.saveInKeycloak).toHaveBeenCalledWith(user);
+    });
+  });
+
+  describe('getUserById', () => {
+    const userStateResource: StateResource<User> = createStateResource(user);
+
+    beforeEach(() => {
+      repository.getUserById.mockReturnValue(singleCold(userStateResource, '-a'));
+    });
+
+    it('should call getUserById from userRepository', () => {
+      service.getUserById(user.id);
+
+      expect(repository.getUserById).toHaveBeenCalledWith(user.id);
+    });
+
+    it('should return loading state resource at first and response at second', () => {
+      const user: Observable<StateResource<User>> = service.getUserById('userId');
+
+      expect(user).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: userStateResource }));
+    });
+  });
 });
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.service.ts b/alfa-client/libs/admin/user-shared/src/lib/user.service.ts
index 76ef2e216284522871b00c7715f7cb1f8997ba43..e927702221df953f2c5882fa6e8791ca98e0929e 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.service.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/user.service.ts
@@ -21,10 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { UserRepository } from '@admin/keycloak-shared';
+import { KeycloakResourceService, UserRepository } from '@admin/keycloak-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
 import { inject, Injectable } from '@angular/core';
-import { map, Observable } from 'rxjs';
-import { KeycloakResourceService } from './keycloak.resource.service';
+import { map, Observable, startWith } from 'rxjs';
 import { User } from './user.model';
 import { sortUsersByLastName } from './user.util';
 
@@ -34,19 +34,23 @@ import { sortUsersByLastName } from './user.util';
 export class UserService extends KeycloakResourceService<User> {
   private readonly userRepository = inject(UserRepository);
 
-  protected getItemsFromKeycloak(): Observable<User[]> {
+  _getItemsFromKeycloak(): Observable<User[]> {
     return this.userRepository.getUsers().pipe(map(sortUsersByLastName));
   }
 
-  protected createInKeycloak(user: Partial<User>): Observable<User> {
+  _createInKeycloak(user: User): Observable<User> {
     return this.userRepository.createInKeycloak(user);
   }
 
-  protected saveInKeycloak(user: User): Observable<void> {
-    throw new Error('Method not implemented.');
+  _saveInKeycloak(user: User): Observable<User> {
+    return this.userRepository.saveInKeycloak(user);
   }
 
-  protected deleteInKeycloak(id: string): Observable<void> {
+  _deleteInKeycloak(id: string): Observable<void> {
     throw new Error('Method not implemented.');
   }
+
+  public getUserById(userId: string): Observable<StateResource<User>> {
+    return this.userRepository.getUserById(userId).pipe(startWith(createEmptyStateResource<User>(true)));
+  }
 }
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.util.ts b/alfa-client/libs/admin/user-shared/src/lib/user.util.ts
index 13c763b37d1d2c4e81a1271caf786a88707e1e78..40b77c2b61e1dff6fbea3d5542e24eea04e08ca8 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.util.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/user.util.ts
@@ -21,8 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { EMPTY_STRING } from '@alfa-client/tech-shared';
 import { User } from './user.model';
 
 export function sortUsersByLastName(users: User[]): User[] {
-  return users.sort((a, b) => (a.lastName ?? '').localeCompare(b.lastName ?? ''));
+  return users.sort((userToCompare: User, userCompareWith: User) =>
+    (userToCompare.lastName ?? EMPTY_STRING).localeCompare(userCompareWith.lastName ?? EMPTY_STRING),
+  );
 }
diff --git a/alfa-client/libs/admin/user-shared/test/user.ts b/alfa-client/libs/admin/user-shared/test/user.ts
index 680d60824d2cebb018ca1c26b096f8c368d4bbbe..7cb1c4faf5af022243ff3af306c0c599fac98fe0 100644
--- a/alfa-client/libs/admin/user-shared/test/user.ts
+++ b/alfa-client/libs/admin/user-shared/test/user.ts
@@ -22,7 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { faker } from '@faker-js/faker';
-import { UserAddFormservice } from '../../user/src/lib/users-roles/user-add-form/user-add.formservice';
+import { UserFormService } from '../../user/src/lib/user-form/user.formservice';
 import { User } from '../src/lib/user.model';
 
 export function createUser(): User {
@@ -34,9 +34,10 @@ export function createUser(): User {
     email: faker.internet.email(),
     enabled: true,
     clientRoles: {
-      alfa: [UserAddFormservice.POSTSTELLE],
-      admin: [UserAddFormservice.ADMIN],
+      alfa: [UserFormService.POSTSTELLE],
+      admin: [UserFormService.ADMIN],
     },
-    groups: null,
+    groups: [faker.word.sample(), faker.word.sample()],
+    groupIds: [faker.string.uuid(), faker.string.uuid()],
   };
 }
diff --git a/alfa-client/libs/admin/user/src/index.ts b/alfa-client/libs/admin/user/src/index.ts
index 756b163e45acdd8eeb7dca2b01d792cdfadadd2c..3e51f2cb78aee00c5e5e63a02c8bdb3ed05478b5 100644
--- a/alfa-client/libs/admin/user/src/index.ts
+++ b/alfa-client/libs/admin/user/src/index.ts
@@ -1,2 +1,2 @@
-export * from './lib/users-roles/user-add-form/user-add-form.component';
-export * from './lib/users-roles/users-roles.component';
+export * from './lib/user-form/user-form.component';
+export * from './lib/user-list-container/user-list-container.component';
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.html b/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..430a3fde777062e005bab85507e57ef17883b311
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.html
@@ -0,0 +1,8 @@
+<div [formGroup]="formGroupParent">
+  <div class="mb-4 grid gap-4 xl:grid-cols-2">
+    <ods-text-editor [formControlName]="UserFormService.FIRST_NAME" [isRequired]="true" label="Vorname" />
+    <ods-text-editor [formControlName]="UserFormService.LAST_NAME" [isRequired]="true" label="Nachname" />
+    <ods-text-editor [formControlName]="UserFormService.USERNAME" [isRequired]="true" label="Benutzername" />
+    <ods-text-editor [formControlName]="UserFormService.EMAIL" [isRequired]="true" label="E-Mail" />
+  </div>
+</div>
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..40a8f3782988d250b27e9b7867c52eda96072b58
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { createUserFormGroup } from '../../../../test/form';
+import { UserFormDataComponent } from './user-form-data.component';
+
+describe('UserFormDataComponent', () => {
+  let component: UserFormDataComponent;
+  let fixture: ComponentFixture<UserFormDataComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UserFormDataComponent, ReactiveFormsModule],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserFormDataComponent);
+    component = fixture.componentInstance;
+    component.formGroupParent = createUserFormGroup();
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d40bee2ba526b9e7bb52d4f638bcb3f95f28095c
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-data/user-form-data.component.ts
@@ -0,0 +1,16 @@
+import { Component, Input } from '@angular/core';
+import { ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
+import { CheckboxEditorComponent, TextEditorComponent } from '@ods/component';
+import { UserFormService } from '../user.formservice';
+
+@Component({
+  selector: 'admin-user-form-data',
+  standalone: true,
+  imports: [CheckboxEditorComponent, ReactiveFormsModule, TextEditorComponent],
+  templateUrl: './user-form-data.component.html',
+})
+export class UserFormDataComponent {
+  @Input() formGroupParent: UntypedFormGroup;
+
+  public readonly UserFormService = UserFormService;
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.html b/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..56c74fd10047e5dece25229b0888dbbe70f9ed12
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.html
@@ -0,0 +1,7 @@
+<h1 class="heading-1 mb-4">
+  @if(isPatch){
+    Benutzer bearbeiten
+  } @else {
+    Benutzer anlegen
+  }
+</h1>
\ No newline at end of file
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c9d4fbbe883f1f1f3658f49ad9a463b232c4b43d
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.spec.ts
@@ -0,0 +1,45 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { getElementFromFixture } from '@alfa-client/test-utils';
+import { UserFormHeadlineComponent } from './user-form-headline.component';
+
+describe('UserFormHeadlineComponent', () => {
+  let component: UserFormHeadlineComponent;
+  let fixture: ComponentFixture<UserFormHeadlineComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UserFormHeadlineComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserFormHeadlineComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    describe('headline', () => {
+      it('should be "Benutzer anlegen"', () => {
+        component.isPatch = false;
+
+        fixture.detectChanges();
+
+        const headline: HTMLElement = getElementFromFixture(fixture, 'h1');
+        expect(headline.textContent).toContain('Benutzer anlegen');
+      });
+
+      it('should be "Benutzer bearbeiten"', () => {
+        component.isPatch = true;
+
+        fixture.detectChanges();
+
+        const headline: HTMLElement = getElementFromFixture(fixture, 'h1');
+        expect(headline.textContent).toContain('Benutzer bearbeiten');
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..22c9cad20d47c0bc8cc466a10f9b3091581ae8da
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-headline/user-form-headline.component.ts
@@ -0,0 +1,11 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'admin-user-form-headline',
+  standalone: true,
+  imports: [],
+  templateUrl: './user-form-headline.component.html',
+})
+export class UserFormHeadlineComponent {
+  @Input() isPatch: boolean;
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.html b/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..bbded315d7eb7b6b1b856c382e34b5972ea0c25c
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.html
@@ -0,0 +1,10 @@
+<div class="mb-12 block">
+  <h2 class="heading-2 mt-4">Organisationseinheiten</h2>
+  <div [formGroup]="formGroupParent">
+    <div [formGroupName]="UserFormService.GROUPS" class="flex flex-col gap-2">
+      @for (controlName of formGroupOrganisationsEinheiten.controls | keyvalue; track controlName.key) {
+        <ods-checkbox-editor [formControlName]="controlName.key" [label]="controlName.key" [inputId]="controlName.key"/>
+      }
+    </div>
+  </div>
+</div>
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4dca17978016da0adce94d5549ab528e5f2ebb81
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.spec.ts
@@ -0,0 +1,28 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormGroup, ReactiveFormsModule } from '@angular/forms';
+import { CheckboxEditorComponent } from '@ods/component';
+import { MockComponent } from 'ng-mocks';
+import { createUserFormGroup } from '../../../../test/form';
+import { UserFormService } from '../user.formservice';
+import { UserFormOrganisationsEinheitListComponent } from './user-form-organisations-einheit-list.component';
+
+describe('UserFormOrganisationsEinheitComponent', () => {
+  let component: UserFormOrganisationsEinheitListComponent;
+  let fixture: ComponentFixture<UserFormOrganisationsEinheitListComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UserFormOrganisationsEinheitListComponent, ReactiveFormsModule, MockComponent(CheckboxEditorComponent)],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserFormOrganisationsEinheitListComponent);
+    component = fixture.componentInstance;
+    component.formGroupParent = createUserFormGroup();
+    component.formGroupOrganisationsEinheiten = component.formGroupParent.get(UserFormService.GROUPS) as FormGroup;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..83e5ca5383750b3c9a4072efa9b39dc43e2aad69
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-organisations-einheit-list/user-form-organisations-einheit-list.component.ts
@@ -0,0 +1,18 @@
+import { KeyValuePipe, NgForOf } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
+import { CheckboxEditorComponent } from '@ods/component';
+import { UserFormService } from '../user.formservice';
+
+@Component({
+  selector: 'admin-user-form-organisations-einheit-list',
+  standalone: true,
+  imports: [ReactiveFormsModule, KeyValuePipe, CheckboxEditorComponent, NgForOf, KeyValuePipe],
+  templateUrl: './user-form-organisations-einheit-list.component.html',
+})
+export class UserFormOrganisationsEinheitListComponent {
+  @Input() formGroupParent: UntypedFormGroup;
+  @Input() formGroupOrganisationsEinheiten: UntypedFormGroup;
+
+  public readonly UserFormService = UserFormService;
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.html b/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..026e846163f1602e26c751e551e0cfa5f016663c
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.html
@@ -0,0 +1,15 @@
+<h2 class="heading-2 mt-4">Rollen für OZG-Cloud</h2>
+<div [formGroup]="formGroupParent">
+  <div [formGroupName]="UserFormService.CLIENT_ROLES" class="mb-8 flex gap-56">
+    <div [formGroupName]="UserFormService.ADMINISTRATION_GROUP" class="flex flex-col gap-2">
+      <h3 class="text-md block font-medium text-text">Administration</h3>
+      <ods-checkbox-editor [formControlName]="UserFormService.ADMIN" label="Admin" inputId="admin" />
+    </div>
+    <div [formGroupName]="UserFormService.ALFA_GROUP" class="flex flex-col gap-2">
+      <h3 class="text-md block font-medium text-text">Alfa</h3>
+      <ods-checkbox-editor [formControlName]="UserFormService.LOESCHEN" label="Löschen" inputId="delete" />
+      <ods-checkbox-editor [formControlName]="UserFormService.USER" label="User" inputId="user" />
+      <ods-checkbox-editor [formControlName]="UserFormService.POSTSTELLE" label="Poststelle" inputId="post_office" />
+    </div>
+  </div>
+</div>
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..386a028e927b68a8277cd8076ee11b357344cb48
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { createUserFormGroup } from '../../../../test/form';
+import { UserFormRolesComponent } from './user-form-roles.component';
+
+describe('UserFormRolesComponent', () => {
+  let component: UserFormRolesComponent;
+  let fixture: ComponentFixture<UserFormRolesComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UserFormRolesComponent, ReactiveFormsModule],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserFormRolesComponent);
+    component = fixture.componentInstance;
+    component.formGroupParent = createUserFormGroup();
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d3c25f54bb31a6d18a39ec113a8f166bc14271ef
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.ts
@@ -0,0 +1,16 @@
+import { Component, Input } from '@angular/core';
+import { ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
+import { CheckboxEditorComponent } from '@ods/component';
+import { UserFormService } from '../user.formservice';
+
+@Component({
+  selector: 'admin-user-form-roles',
+  standalone: true,
+  imports: [CheckboxEditorComponent, ReactiveFormsModule],
+  templateUrl: './user-form-roles.component.html',
+})
+export class UserFormRolesComponent {
+  @Input() formGroupParent: UntypedFormGroup;
+
+  public readonly UserFormService = UserFormService;
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.html b/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..0277da75dbb4169dd33e4927d89702b1105ce9d9
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.html
@@ -0,0 +1,6 @@
+<ods-button-with-spinner
+  [stateResource]="submitStateResource$ | async"
+  (clickEmitter)="submit()"
+  text="Speichern"
+  dataTestId="save-button"
+/>
\ No newline at end of file
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dcd4e3712eb848de5eea8e563c60987b2c310429
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.spec.ts
@@ -0,0 +1,89 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { User } from '@admin-client/user-shared';
+import { createStateResource, StateResource } from '@alfa-client/tech-shared';
+import { dispatchEventFromFixture, getDebugElementFromFixtureByCss, mock, Mock } from '@alfa-client/test-utils';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { cold } from 'jest-marbles';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { getDataTestIdAttributeOf } from '../../../../../../tech-shared/test/data-test';
+import { createUser } from '../../../../../user-shared/test/user';
+import { UserFormService } from '../user.formservice';
+import { UserFormSaveButtonComponent } from './user-form-save-button.component';
+
+describe('UserFormSaveButtonComponent', () => {
+  let component: UserFormSaveButtonComponent;
+  let fixture: ComponentFixture<UserFormSaveButtonComponent>;
+
+  let formService: Mock<UserFormService>;
+
+  const saveButton: string = getDataTestIdAttributeOf('save-button');
+
+  beforeEach(async () => {
+    formService = <any>{
+      ...mock(UserFormService),
+      submit: jest.fn(),
+    };
+
+    await TestBed.configureTestingModule({
+      declarations: [UserFormSaveButtonComponent, MockComponent(ButtonWithSpinnerComponent)],
+      providers: [{ provide: UserFormService, useValue: formService }],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserFormSaveButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('component', () => {
+    describe('submit', () => {
+      const userStateResource: StateResource<User> = createStateResource(createUser());
+
+      beforeEach(() => {
+        formService.submit.mockReturnValue(of(userStateResource));
+      });
+
+      it('should call formService submit', () => {
+        component.submit();
+
+        expect(formService.submit).toHaveBeenCalled();
+      });
+
+      it('should set submitState$', () => {
+        component.submit();
+
+        expect(component.submitStateResource$).toBeObservable(cold('(a|)', { a: userStateResource }));
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('button save', () => {
+      describe('input', () => {
+        it('should be set', () => {
+          const stateResource: StateResource<User> = createStateResource(createUser());
+          component.submitStateResource$ = of(stateResource);
+
+          fixture.detectChanges();
+
+          expect(getDebugElementFromFixtureByCss(fixture, saveButton).componentInstance.stateResource).toEqual(stateResource);
+        });
+      });
+
+      describe('output', () => {
+        it('should call submit', () => {
+          component.submit = jest.fn();
+
+          dispatchEventFromFixture(fixture, saveButton, 'clickEmitter');
+
+          expect(component.submit).toHaveBeenCalled();
+        });
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..941904eb8d84b9c72b9483cabcfdb354026fd48e
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-save-button/user-form-save-button.component.ts
@@ -0,0 +1,23 @@
+import { User } from '@admin-client/user-shared';
+import { StateResource } from '@alfa-client/tech-shared';
+import { AsyncPipe } from '@angular/common';
+import { Component, inject } from '@angular/core';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { Observable } from 'rxjs';
+import { UserFormService } from '../user.formservice';
+
+@Component({
+  selector: 'admin-user-form-save-button',
+  standalone: true,
+  imports: [AsyncPipe, ButtonWithSpinnerComponent],
+  templateUrl: './user-form-save-button.component.html',
+})
+export class UserFormSaveButtonComponent {
+  public readonly formService = inject(UserFormService);
+
+  public submitStateResource$: Observable<StateResource<User>>;
+
+  public submit(): void {
+    this.submitStateResource$ = this.formService.submit();
+  }
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.html b/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..dcab3c25b5a05434e0eedd7f56e889914253b5d7
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.html
@@ -0,0 +1,37 @@
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<ods-spinner [stateResource]="userStateResource$ | async">
+  <div class="max-w-[960px]" data-test-id="user-content">
+    <admin-user-form-headline [isPatch]="formService.isPatch()" />
+    <admin-user-form-data [formGroupParent]="formService.form" />
+    <admin-user-form-roles [formGroupParent]="formService.form" />
+    <admin-user-form-organisations-einheit-list
+      [formGroupParent]="formService.form"
+      [formGroupOrganisationsEinheiten]="formService.getOrganisationsEinheitenGroup()"
+    />
+    <admin-user-form-save-button />
+  </div>
+</ods-spinner>
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..085f2fe196fdb6d881240f4485527e72123b51ba
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.spec.ts
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { User } from '@admin-client/user-shared';
+import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared';
+import { getMockComponent, mock, Mock, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { CommonModule } from '@angular/common';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormGroup, ReactiveFormsModule } from '@angular/forms';
+import { ButtonWithSpinnerComponent, SpinnerComponent } from '@ods/component';
+import { cold } from 'jest-marbles';
+import { createUser } from 'libs/admin/user-shared/test/user';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { getDataTestIdOf } from '../../../../../tech-shared/test/data-test';
+import { UserFormDataComponent } from './user-form-data/user-form-data.component';
+import { UserFormHeadlineComponent } from './user-form-headline/user-form-headline.component';
+import { UserFormOrganisationsEinheitListComponent } from './user-form-organisations-einheit-list/user-form-organisations-einheit-list.component';
+import { UserFormRolesComponent } from './user-form-roles/user-form-roles.component';
+import { UserFormComponent } from './user-form.component';
+import { UserFormService } from './user.formservice';
+
+describe('UserFormComponent', () => {
+  let component: UserFormComponent;
+  let fixture: ComponentFixture<UserFormComponent>;
+
+  let formService: Mock<UserFormService>;
+
+  const userContent: string = getDataTestIdOf('user-content');
+
+  beforeEach(async () => {
+    formService = <any>{
+      ...mock(UserFormService),
+      get: jest.fn(),
+      isInvalid: jest.fn(),
+      form: new FormGroup({}),
+      isPatch: jest.fn(),
+    };
+
+    await TestBed.configureTestingModule({
+      imports: [CommonModule, ReactiveFormsModule, SpinnerComponent],
+      declarations: [
+        UserFormComponent,
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(UserFormDataComponent),
+        MockComponent(UserFormOrganisationsEinheitListComponent),
+        MockComponent(UserFormRolesComponent),
+        MockComponent(UserFormHeadlineComponent),
+      ],
+      providers: [{ provide: UserFormService, useValue: formService }],
+    })
+      .overrideComponent(UserFormComponent, {
+        set: {
+          providers: [
+            {
+              provide: UserFormService,
+              useValue: formService,
+            },
+          ],
+        },
+      })
+      .compileComponents();
+
+    fixture = TestBed.createComponent(UserFormComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('component', () => {
+    describe('on init', () => {
+      const userStateResource: StateResource<User> = createStateResource(createUser());
+
+      beforeEach(() => {
+        formService.get.mockReturnValue(of(userStateResource));
+      });
+
+      it('should call formservice to get user', () => {
+        component.ngOnInit();
+
+        expect(formService.get).toHaveBeenCalled();
+      });
+
+      it('should set user state resource', () => {
+        component.userStateResource$ = of(createEmptyStateResource<User>());
+
+        component.ngOnInit();
+
+        expect(component.userStateResource$).toBeObservable(cold('(a|)', { a: userStateResource }));
+      });
+    });
+  });
+
+  describe('template', () => {
+    describe('admin headline', () => {
+      it('should exist with input', () => {
+        formService.isPatch.mockReturnValue(true);
+
+        fixture.detectChanges();
+
+        const headlineComponent: UserFormHeadlineComponent = getMockComponent(fixture, UserFormHeadlineComponent);
+        expect(headlineComponent.isPatch).toBe(true);
+      });
+    });
+
+    describe('admin data', () => {
+      it('should exist with input', () => {
+        const formDataComponent: UserFormDataComponent = getMockComponent(fixture, UserFormDataComponent);
+
+        expect(formDataComponent).toBeTruthy();
+        expect(formDataComponent.formGroupParent).toBe(component.formService.form);
+      });
+    });
+
+    describe('admin roles', () => {
+      it('should exist with input', () => {
+        const rolesComponent: UserFormRolesComponent = getMockComponent(fixture, UserFormRolesComponent);
+
+        expect(rolesComponent).toBeTruthy();
+        expect(rolesComponent.formGroupParent).toBe(component.formService.form);
+      });
+    });
+
+    describe('admin organisations einheiten', () => {
+      it('should exist with input', () => {
+        const organisationsEinheitListComponent: UserFormOrganisationsEinheitListComponent = getMockComponent(
+          fixture,
+          UserFormOrganisationsEinheitListComponent,
+        );
+
+        expect(organisationsEinheitListComponent).toBeTruthy();
+        expect(organisationsEinheitListComponent.formGroupParent).toBe(component.formService.form);
+        expect(organisationsEinheitListComponent.formGroupOrganisationsEinheiten).toBe(
+          component.formService.getOrganisationsEinheitenGroup(),
+        );
+      });
+    });
+
+    it('should hide content on loading user', () => {
+      component.userStateResource$ = of(createEmptyStateResource<User>(true));
+
+      fixture.detectChanges();
+
+      notExistsAsHtmlElement(fixture, userContent);
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.ts b/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..03199641945f4841fcd0360b025262c2136d9ef3
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form.component.ts
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { User } from '@admin-client/user-shared';
+import { StateResource } from '@alfa-client/tech-shared';
+import { AsyncPipe } from '@angular/common';
+import { Component, inject, OnInit } from '@angular/core';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { SpinnerComponent } from '@ods/component';
+import { Observable } from 'rxjs';
+import { UserFormDataComponent } from './user-form-data/user-form-data.component';
+import { UserFormHeadlineComponent } from './user-form-headline/user-form-headline.component';
+import { UserFormOrganisationsEinheitListComponent } from './user-form-organisations-einheit-list/user-form-organisations-einheit-list.component';
+import { UserFormRolesComponent } from './user-form-roles/user-form-roles.component';
+import { UserFormSaveButtonComponent } from './user-form-save-button/user-form-save-button.component';
+import { UserFormService } from './user.formservice';
+
+@Component({
+  selector: 'admin-user-form',
+  providers: [UserFormService],
+  templateUrl: './user-form.component.html',
+  standalone: true,
+  imports: [
+    FormsModule,
+    ReactiveFormsModule,
+    AsyncPipe,
+    UserFormDataComponent,
+    UserFormRolesComponent,
+    UserFormOrganisationsEinheitListComponent,
+    UserFormHeadlineComponent,
+    UserFormSaveButtonComponent,
+    SpinnerComponent,
+  ],
+})
+export class UserFormComponent implements OnInit {
+  public readonly formService = inject(UserFormService);
+
+  public userStateResource$: Observable<StateResource<User>>;
+
+  ngOnInit(): void {
+    this.userStateResource$ = this.formService.get();
+  }
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.spec.ts b/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..92031a721d4ebb9e879f75308b003848c82d6cc0
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.spec.ts
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { AdminOrganisationsEinheit, AdminOrganisationsEinheitService } from '@admin-client/organisations-einheit-shared';
+import { ROUTES } from '@admin-client/shared';
+import { User, UserService } from '@admin-client/user-shared';
+import { PatchConfig } from '@admin/keycloak-shared';
+import { NavigationService } from '@alfa-client/navigation-shared';
+import { createEmptyStateResource, createStateResource, EMPTY_ARRAY, StateResource } from '@alfa-client/tech-shared';
+import { Mock, mock } from '@alfa-client/test-utils';
+import { SnackBarService } from '@alfa-client/ui';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
+import { ActivatedRoute, UrlSegment } from '@angular/router';
+import { faker } from '@faker-js/faker/locale/de';
+import { cold } from 'jest-marbles';
+import { createUser } from 'libs/admin/user-shared/test/user';
+import { Observable, of, throwError } from 'rxjs';
+import { createUrlSegment } from '../../../../../navigation-shared/test/navigation-test-factory';
+import { singleCold, singleColdCompleted, singleHot } from '../../../../../tech-shared/test/marbles';
+import { createAdminOrganisationsEinheit } from '../../../../organisations-einheit-shared/src/test/organisations-einheit';
+import { UserFormService } from './user.formservice';
+
+import SpyInstance = jest.SpyInstance;
+
+describe('UserFormService', () => {
+  let formService: UserFormService;
+  let roleGroup: UntypedFormGroup;
+  let alfaGroup: UntypedFormGroup;
+  let organisationsEinheitenGroup: UntypedFormGroup;
+  let administrationGroup: UntypedFormGroup;
+
+  let service: Mock<UserService>;
+  let adminOrganisationsEinheitService: Mock<AdminOrganisationsEinheitService>;
+  let navigationService: Mock<NavigationService>;
+  let snackBarService: Mock<SnackBarService>;
+  let activatedRoute: Mock<ActivatedRoute>;
+
+  const adminOrganisationsEinheit: AdminOrganisationsEinheit = createAdminOrganisationsEinheit();
+  const adminOrganisationsEinheitList: StateResource<AdminOrganisationsEinheit[]> = createStateResource([
+    adminOrganisationsEinheit,
+  ]);
+
+  beforeEach(() => {
+    service = { ...mock(UserService), refresh: jest.fn(), create: jest.fn(), save: jest.fn(), getUserById: jest.fn() };
+    adminOrganisationsEinheitService = {
+      ...mock(AdminOrganisationsEinheitService),
+      getAll: jest.fn().mockReturnValue(of(adminOrganisationsEinheitList)),
+    };
+    navigationService = mock(NavigationService);
+    snackBarService = mock(SnackBarService);
+    activatedRoute = <any>{ ...mock(ActivatedRoute), url: of<UrlSegment[]>(EMPTY_ARRAY) };
+
+    TestBed.configureTestingModule({
+      providers: [
+        UserFormService,
+        UntypedFormBuilder,
+        { provide: UserService, useValue: service },
+        { provide: AdminOrganisationsEinheitService, useValue: adminOrganisationsEinheitService },
+        { provide: NavigationService, useValue: navigationService },
+        { provide: SnackBarService, useValue: snackBarService },
+        { provide: ActivatedRoute, useValue: activatedRoute },
+      ],
+    });
+
+    formService = TestBed.inject(UserFormService);
+    organisationsEinheitenGroup = <UntypedFormGroup>formService.form.get(UserFormService.GROUPS);
+    roleGroup = <UntypedFormGroup>formService.form.get(UserFormService.CLIENT_ROLES);
+    alfaGroup = <UntypedFormGroup>roleGroup.get(UserFormService.ALFA_GROUP);
+    administrationGroup = <UntypedFormGroup>roleGroup.get(UserFormService.ADMINISTRATION_GROUP);
+  });
+
+  it('should create', () => {
+    expect(formService).toBeTruthy();
+  });
+
+  describe('build patch config', () => {
+    describe('on matching route', () => {
+      it('should contains id and value for patch indication', () => {
+        const benutzerUrlSegment: UrlSegment = <UrlSegment>{ ...createUrlSegment(), path: 'benutzer' };
+        const idUrlSegment: UrlSegment = <UrlSegment>{ ...createUrlSegment(), path: 'dummyId' };
+
+        const patchConfig: PatchConfig = formService._buildPatchConfig([benutzerUrlSegment, idUrlSegment]);
+
+        expect(patchConfig).toEqual({ id: 'dummyId', doPatch: true });
+      });
+    });
+
+    it('should contains value for patch indication only on non matching route', () => {
+      const benutzerUrlSegment: UrlSegment = <UrlSegment>{ ...createUrlSegment(), path: 'benutzer' };
+      const idUrlSegment: UrlSegment = <UrlSegment>{ ...createUrlSegment(), path: 'neu' };
+
+      const patchConfig: PatchConfig = formService._buildPatchConfig([benutzerUrlSegment, idUrlSegment]);
+
+      expect(patchConfig).toEqual({ doPatch: false });
+    });
+  });
+
+  describe('load', () => {
+    const id: string = 'dummyId';
+
+    const loadedUser: StateResource<User> = createStateResource(createUser());
+
+    beforeEach(() => {
+      service.getUserById.mockReturnValue(singleHot(loadedUser));
+    });
+
+    it('should call service to get user by id', () => {
+      formService._load(id);
+
+      expect(service.getUserById).toHaveBeenCalledWith(id);
+    });
+
+    it('should return loaded user', () => {
+      const response: Observable<StateResource<User>> = formService._load(id);
+
+      expect(response).toBeObservable(singleCold(loadedUser));
+    });
+  });
+
+  describe('listenToAlfaGroupChanges', () => {
+    it('should call handleAlfaGroupChange when value of form element changes', fakeAsync(() => {
+      formService._handleAlfaGroupChange = jest.fn();
+
+      alfaGroup.get(UserFormService.LOESCHEN).setValue(true);
+
+      tick();
+
+      expect(formService._handleAlfaGroupChange).toHaveBeenCalled();
+    }));
+  });
+
+  describe('initOrganisationsEinheiten', () => {
+    it('should call adminOrganisationsEinheitService getAll', () => {
+      expect(adminOrganisationsEinheitService.getAll).toHaveBeenCalled();
+    });
+
+    it('should return resource', () => {
+      const result: Observable<AdminOrganisationsEinheit[]> = formService._initOrganisationsEinheiten();
+
+      expect(result).toBeObservable(singleColdCompleted(adminOrganisationsEinheitList.resource));
+    });
+
+    it('should call addOrganisationsEinheitenToForm ', fakeAsync(() => {
+      formService._addOrganisationsEinheitenToForm = jest.fn();
+
+      formService._initOrganisationsEinheiten().subscribe();
+      tick();
+
+      expect(formService._addOrganisationsEinheitenToForm).toHaveBeenCalled();
+    }));
+
+    it('should save ids in map', () => {
+      formService._initOrganisationsEinheiten().subscribe();
+
+      expect(formService._organisationsEinheitToGroupIdMap.get(adminOrganisationsEinheit.name)).toEqual(
+        adminOrganisationsEinheit.id,
+      );
+    });
+
+    it('should set initOrganisationsEinheiten$', () => {
+      expect(formService['_initOrganisationsEinheiten$']).toBeDefined();
+    });
+  });
+
+  describe('addOrganisationsEinheitenToForm', () => {
+    it('should add organisationsEinheiten to form', () => {
+      const organisationsEinheitenGroup: UntypedFormGroup = <UntypedFormGroup>formService.form.get(UserFormService.GROUPS);
+
+      formService._addOrganisationsEinheitenToForm(adminOrganisationsEinheitList.resource, organisationsEinheitenGroup);
+
+      expect(organisationsEinheitenGroup.value).toEqual({ [adminOrganisationsEinheit.name]: false });
+    });
+  });
+
+  describe('roleValidator', () => {
+    it('should return error if no role is selected', () => {
+      const result = formService.roleValidator()(roleGroup);
+
+      expect(result).toEqual({ atLeastOneRoleSelected: true });
+    });
+
+    it('should return null if at least one role is selected', () => {
+      alfaGroup.get(UserFormService.LOESCHEN).setValue(true);
+
+      const result = formService.roleValidator()(roleGroup);
+
+      expect(result).toBeNull();
+    });
+  });
+
+  describe('handleAlfaGroupChange', () => {
+    it('should call disableUncheckedCheckboxes if any checkbox is checked', () => {
+      formService._isAnyChecked = jest.fn().mockReturnValue(true);
+      formService._disableUncheckedCheckboxes = jest.fn();
+
+      formService._handleAlfaGroupChange(alfaGroup);
+
+      expect(formService._disableUncheckedCheckboxes).toHaveBeenCalled();
+    });
+
+    it('should call enableAllCheckboxes if not any checkbox is checked', () => {
+      formService._isAnyChecked = jest.fn().mockReturnValue(false);
+      formService._enableAllCheckboxes = jest.fn();
+
+      formService._handleAlfaGroupChange(alfaGroup);
+
+      expect(formService._enableAllCheckboxes).toHaveBeenCalled();
+    });
+  });
+
+  describe('isAnyChecked', () => {
+    it('should return false if no checkbox is checked', () => {
+      const result = formService._isAnyChecked(alfaGroup);
+
+      expect(result).toBe(false);
+    });
+
+    it('should return true if any checkbox is checked', () => {
+      alfaGroup.get(UserFormService.LOESCHEN).setValue(true);
+
+      const result = formService._isAnyChecked(alfaGroup);
+
+      expect(result).toBe(true);
+    });
+  });
+
+  describe('disableUncheckedCheckboxes', () => {
+    it('if control value is false then control should be disabled', () => {
+      const control: AbstractControl = alfaGroup.get(UserFormService.LOESCHEN);
+      control.setValue(false);
+
+      formService._disableUncheckedCheckboxes(alfaGroup);
+
+      expect(control.disabled).toBe(true);
+    });
+
+    it('if control value is true then control should NOT be disabled', () => {
+      const control: AbstractControl = alfaGroup.get(UserFormService.LOESCHEN);
+      control.setValue(true);
+
+      formService._disableUncheckedCheckboxes(alfaGroup);
+
+      expect(control.disabled).toBe(false);
+    });
+  });
+
+  describe('updateCheckboxStates', () => {
+    it('if control value is false then control should be disabled', () => {
+      const control: AbstractControl = alfaGroup.get(UserFormService.LOESCHEN);
+      control.setValue(false);
+
+      formService._disableUncheckedCheckboxes(alfaGroup);
+
+      expect(control.disabled).toBe(true);
+    });
+  });
+
+  describe('enableAllCheckboxes', () => {
+    it('if control value is true then control should be enabled', () => {
+      const control: AbstractControl = alfaGroup.get(UserFormService.LOESCHEN);
+      const enableSpy = jest.spyOn(control, 'enable');
+
+      formService._enableAllCheckboxes(alfaGroup);
+
+      expect(enableSpy).toHaveBeenCalled();
+    });
+  });
+
+  describe('doSubmit', () => {
+    const user: User = createUser();
+
+    beforeEach(() => {
+      formService.isInvalid = jest.fn().mockReturnValue(false);
+      service.create.mockReturnValue(of(createStateResource(user)));
+    });
+
+    it('should return empty stateResource if form is invalid', () => {
+      formService.isInvalid = jest.fn().mockReturnValue(true);
+
+      const result: Observable<StateResource<User>> = formService._doSubmit();
+
+      expect(result).toBeObservable(singleColdCompleted(createEmptyStateResource<User>()));
+    });
+
+    it('should call createUser', () => {
+      formService._createUser = jest.fn();
+
+      formService.submit();
+
+      expect(formService._createUser).toHaveBeenCalled();
+    });
+
+    it('should call _createOrSave', () => {
+      formService._createUser = jest.fn().mockReturnValue(user);
+      formService._createOrSave = jest.fn().mockReturnValue(of(user));
+
+      formService.submit();
+
+      expect(formService._createOrSave).toHaveBeenCalledWith(user);
+    });
+
+    it('should call handleOnCreateUserSuccess if not loading', fakeAsync(() => {
+      const handleOnCreateUserSuccessSpy: SpyInstance = jest.spyOn(formService, 'handleOnCreateUserSuccess');
+
+      formService.submit().subscribe();
+      tick();
+
+      expect(handleOnCreateUserSuccessSpy).toHaveBeenCalled();
+    }));
+
+    it('should not call handleOnCreateUserSuccess if loading', fakeAsync(() => {
+      service.create.mockReturnValue(of(createEmptyStateResource(true)));
+      const handleOnCreateUserSuccessSpy: SpyInstance = jest.spyOn(formService, 'handleOnCreateUserSuccess');
+
+      formService.submit().subscribe();
+      tick();
+
+      expect(handleOnCreateUserSuccessSpy).not.toHaveBeenCalled();
+    }));
+
+    it('should call handleSubmitError on error', fakeAsync(() => {
+      service.create.mockReturnValue(throwError(() => new Error()));
+      const handleSubmitErrorSpy: SpyInstance = jest.spyOn(formService, 'handleSubmitError');
+
+      formService.submit().subscribe();
+      tick();
+
+      expect(handleSubmitErrorSpy).toHaveBeenCalled();
+    }));
+  });
+
+  describe('createOrSave', () => {
+    const user: User = createUser();
+
+    const id: string = faker.string.uuid();
+
+    const patchConfig: PatchConfig = { id, doPatch: true };
+
+    it('should call save if patched', () => {
+      formService.isPatch = jest.fn().mockReturnValue(true);
+      formService._patchConfig = patchConfig;
+      user.groups = [adminOrganisationsEinheit.name];
+      formService._organisationsEinheitToGroupIdMap.set(adminOrganisationsEinheit.name, adminOrganisationsEinheit.id);
+
+      formService._createOrSave(user);
+
+      expect(service.save).toHaveBeenCalledWith({ ...user, id, groupIds: [adminOrganisationsEinheit.id] });
+    });
+
+    it('should call create if not patched', () => {
+      formService.isPatch = jest.fn().mockReturnValue(false);
+
+      formService._createOrSave(user);
+
+      expect(service.create).toHaveBeenCalledWith(user);
+    });
+  });
+
+  describe('handleOnCreateUserSuccess', () => {
+    it('should show success message for create', () => {
+      formService.handleOnCreateUserSuccess();
+
+      expect(snackBarService.showInfo).toHaveBeenCalledWith('Der Benutzer wurde angelegt.');
+    });
+
+    it('should show success message for patch', () => {
+      formService.isPatch = jest.fn().mockReturnValue(true);
+
+      formService.handleOnCreateUserSuccess();
+
+      expect(snackBarService.showInfo).toHaveBeenCalledWith('Der Benutzer wurde gespeichert.');
+    });
+
+    it('should navigate back to user list', () => {
+      formService.handleOnCreateUserSuccess();
+
+      expect(navigationService.navigate).toHaveBeenCalledWith(ROUTES.BENUTZER);
+    });
+  });
+
+  describe('handleSubmitError', () => {
+    it('should return empty stateResource', () => {
+      const result = formService.handleSubmitError();
+
+      expect(result).toBeObservable(cold('(a|)', { a: createEmptyStateResource<User>() }));
+    });
+
+    it('should show error message', fakeAsync(() => {
+      formService.handleSubmitError().subscribe();
+      tick();
+
+      expect(snackBarService.showError).toHaveBeenCalledWith('Der Benutzer konnte nicht angelegt werden.');
+    }));
+  });
+
+  describe('getRoles', () => {
+    it('should return no roles when none are active', () => {
+      const result: string[] = formService._getRoles(UserFormService.ALFA_GROUP);
+
+      expect(result).toEqual([]);
+    });
+
+    it('should return poststelle role when active', () => {
+      alfaGroup.get(UserFormService.POSTSTELLE).setValue(true);
+
+      const result: string[] = formService._getRoles(UserFormService.ALFA_GROUP);
+
+      expect(result).toEqual([UserFormService.POSTSTELLE]);
+    });
+  });
+
+  describe('getActiveOrganisationsEinheiten', () => {
+    it('should return no groups when none are active', () => {
+      const result: string[] = formService._getActiveOrganisationsEinheiten();
+
+      expect(result).toEqual([]);
+    });
+
+    it('should return bauamt group when active', () => {
+      const organisationsEinheit: AdminOrganisationsEinheit = { name: 'bauamt' };
+      organisationsEinheitenGroup.addControl(organisationsEinheit.name, new FormControl(true));
+
+      const result: string[] = formService._getActiveOrganisationsEinheiten();
+
+      expect(result).toEqual([organisationsEinheit.name]);
+    });
+  });
+
+  describe('ngOnDestroy', () => {
+    it('should unsubscribe from initOrganisationsEinheiten$', () => {
+      formService._initOrganisationsEinheiten$.unsubscribe = jest.fn();
+
+      formService.ngOnDestroy();
+
+      expect(formService._initOrganisationsEinheiten$.unsubscribe).toHaveBeenCalled();
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.ts b/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e7e537b362cf5938842d80e3ededcf7297665b78
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.ts
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { AdminOrganisationsEinheit, AdminOrganisationsEinheitService } from '@admin-client/organisations-einheit-shared';
+import { ROUTES } from '@admin-client/shared';
+import { User, UserService } from '@admin-client/user-shared';
+import { KeycloakFormService, PatchConfig } from '@admin/keycloak-shared';
+import { NavigationService } from '@alfa-client/navigation-shared';
+import { createEmptyStateResource, EMPTY_STRING, mapToResource, StateResource } from '@alfa-client/tech-shared';
+import { SnackBarService } from '@alfa-client/ui';
+import { Injectable, OnDestroy } from '@angular/core';
+import {
+  AbstractControl,
+  FormControl,
+  UntypedFormBuilder,
+  UntypedFormGroup,
+  ValidationErrors,
+  ValidatorFn,
+  Validators,
+} from '@angular/forms';
+import { UrlSegment } from '@angular/router';
+import { catchError, Observable, of, Subscription, tap } from 'rxjs';
+
+@Injectable()
+export class UserFormService extends KeycloakFormService<User> implements OnDestroy {
+  public static readonly FIRST_NAME: string = 'firstName';
+  public static readonly LAST_NAME: string = 'lastName';
+  public static readonly USERNAME: string = 'username';
+  public static readonly EMAIL: string = 'email';
+
+  public static readonly CLIENT_ROLES: string = 'clientRoles';
+  public static readonly GROUPS: string = 'groups';
+  public static readonly ADMINISTRATION_GROUP: string = 'admin';
+  public static readonly ADMIN: string = 'ADMIN_ADMIN';
+  public static readonly ALFA_GROUP: string = 'alfa';
+  public static readonly LOESCHEN: string = 'VERWALTUNG_LOESCHEN';
+  public static readonly USER: string = 'VERWALTUNG_USER';
+  public static readonly POSTSTELLE: string = 'VERWALTUNG_POSTSTELLE';
+
+  _initOrganisationsEinheiten$: Subscription;
+
+  _organisationsEinheitToGroupIdMap: Map<string, string> = new Map<string, string>();
+
+  constructor(
+    public formBuilder: UntypedFormBuilder,
+    private userService: UserService,
+    private adminOrganisationsEinheitService: AdminOrganisationsEinheitService,
+    private navigationService: NavigationService,
+    private snackBarService: SnackBarService,
+  ) {
+    super();
+
+    this._initOrganisationsEinheiten$ = this._initOrganisationsEinheiten().subscribe();
+    this.listenToAlfaGroupChanges();
+  }
+
+  _buildPatchConfig(url: UrlSegment[]): PatchConfig {
+    const doPatch: boolean = this.shouldPatch(url);
+    return {
+      id: doPatch ? url[1].path : undefined,
+      doPatch,
+    };
+  }
+
+  private shouldPatch(url: UrlSegment[]): boolean {
+    return url.length == 2 && url[0].path == 'benutzer' && url[1].path != 'neu';
+  }
+
+  _load(id: string): Observable<StateResource<User>> {
+    return this.userService.getUserById(id);
+  }
+
+  _initForm(): UntypedFormGroup {
+    return this.formBuilder.group({
+      [UserFormService.FIRST_NAME]: new FormControl(EMPTY_STRING, Validators.required),
+      [UserFormService.LAST_NAME]: new FormControl(EMPTY_STRING, Validators.required),
+      [UserFormService.USERNAME]: new FormControl(EMPTY_STRING, Validators.required),
+      [UserFormService.EMAIL]: new FormControl(EMPTY_STRING, [Validators.required]),
+      [UserFormService.CLIENT_ROLES]: this.formBuilder.group(
+        {
+          [UserFormService.ADMINISTRATION_GROUP]: this.formBuilder.group({
+            [UserFormService.ADMIN]: new FormControl(false),
+          }),
+          [UserFormService.ALFA_GROUP]: this.formBuilder.group({
+            [UserFormService.LOESCHEN]: new FormControl(false),
+            [UserFormService.USER]: new FormControl(false),
+            [UserFormService.POSTSTELLE]: new FormControl(false),
+          }),
+        },
+        { validators: this.roleValidator() },
+      ),
+      [UserFormService.GROUPS]: this.formBuilder.group({}),
+    });
+  }
+
+  roleValidator(): ValidatorFn {
+    return (control: AbstractControl<UntypedFormGroup>): ValidationErrors | null => {
+      const rolesGroups: UntypedFormGroup = control.value;
+
+      if (this.anyRoleSelected(rolesGroups)) {
+        return null;
+      }
+
+      return { atLeastOneRoleSelected: true };
+    };
+  }
+
+  private anyRoleSelected(rolesGroups: UntypedFormGroup): boolean {
+    for (const subGroup of Object.values(rolesGroups)) {
+      if (Object.values(subGroup).includes(true)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  _initOrganisationsEinheiten(): Observable<AdminOrganisationsEinheit[]> {
+    const organisationsEinheitenGroup: UntypedFormGroup = this.getOrganisationsEinheitenGroup();
+    return this.adminOrganisationsEinheitService.getAll().pipe(
+      mapToResource<AdminOrganisationsEinheit[]>(),
+      tap((organisationsEinheiten: AdminOrganisationsEinheit[]): void => {
+        this.setOrganisationsEinheitenIdsInMap(organisationsEinheiten);
+        this._addOrganisationsEinheitenToForm(organisationsEinheiten, organisationsEinheitenGroup);
+      }),
+    );
+  }
+
+  private setOrganisationsEinheitenIdsInMap(organisationsEinheiten: AdminOrganisationsEinheit[]): void {
+    organisationsEinheiten.forEach((organisationsEinheit: AdminOrganisationsEinheit) => {
+      this._organisationsEinheitToGroupIdMap.set(organisationsEinheit.name, organisationsEinheit.id);
+    });
+  }
+
+  _addOrganisationsEinheitenToForm(
+    organisationsEinheiten: AdminOrganisationsEinheit[],
+    organisationsEinheitenGroup: UntypedFormGroup,
+  ): void {
+    organisationsEinheiten.forEach((organisationsEinheit: AdminOrganisationsEinheit) => {
+      organisationsEinheitenGroup.addControl(organisationsEinheit.name, new FormControl(false));
+    });
+  }
+
+  protected listenToAlfaGroupChanges(): void {
+    const alfaGroup: UntypedFormGroup = this.getRoleGroup(UserFormService.ALFA_GROUP);
+    alfaGroup.valueChanges.subscribe(() => {
+      this._handleAlfaGroupChange(alfaGroup);
+    });
+  }
+
+  _handleAlfaGroupChange(group: UntypedFormGroup): void {
+    const anyChecked: boolean = this._isAnyChecked(group);
+    if (anyChecked) {
+      this._disableUncheckedCheckboxes(group);
+    } else {
+      this._enableAllCheckboxes(group);
+    }
+  }
+
+  _isAnyChecked(group: UntypedFormGroup): boolean {
+    return Object.keys(group.controls).some((key) => group.controls[key].value);
+  }
+
+  _disableUncheckedCheckboxes(alfaGroup: UntypedFormGroup): void {
+    for (const control of Object.values<AbstractControl>(alfaGroup.controls)) {
+      if (control.value === false) control.disable({ emitEvent: false });
+    }
+  }
+
+  _enableAllCheckboxes(group: UntypedFormGroup): void {
+    for (const control of Object.values<AbstractControl>(group.controls)) {
+      control.enable({ emitEvent: false });
+    }
+  }
+
+  _doSubmit(): Observable<StateResource<User>> {
+    if (this.isInvalid()) {
+      return of(createEmptyStateResource<User>());
+    }
+
+    const user: User = this._createUser();
+    return this._createOrSave(user).pipe(
+      tap((state: StateResource<User>): void => {
+        if (!state.loading) this.handleOnCreateUserSuccess();
+      }),
+      catchError((): Observable<StateResource<User>> => this.handleSubmitError()),
+    );
+  }
+
+  _createOrSave(user: User): Observable<StateResource<User>> {
+    if (this.isPatch()) {
+      return this.userService.save({
+        ...user,
+        id: this._patchConfig.id,
+        groupIds: user.groups.map((groupName: string): string => this._organisationsEinheitToGroupIdMap.get(groupName)),
+      });
+    } else {
+      return this.userService.create(user);
+    }
+  }
+
+  handleOnCreateUserSuccess(): void {
+    this.snackBarService.showInfo(this.isPatch() ? 'Der Benutzer wurde gespeichert.' : 'Der Benutzer wurde angelegt.');
+    this.navigationService.navigate(ROUTES.BENUTZER);
+  }
+
+  handleSubmitError(): Observable<StateResource<User>> {
+    this.snackBarService.showError('Der Benutzer konnte nicht angelegt werden.');
+    return of(createEmptyStateResource<User>());
+  }
+
+  _createUser(): User {
+    return {
+      ...this._getFormValue(),
+      enabled: true,
+      clientRoles: {
+        alfa: this._getRoles(UserFormService.ALFA_GROUP),
+        admin: this._getRoles(UserFormService.ADMINISTRATION_GROUP),
+      },
+      groups: this._getActiveOrganisationsEinheiten(),
+    };
+  }
+
+  _getRoles(roleGroup: string): string[] {
+    return this.getActive(this.getRoleGroup(roleGroup));
+  }
+
+  _getActiveOrganisationsEinheiten(): string[] {
+    return this.getActive(this.getOrganisationsEinheitenGroup());
+  }
+
+  private getActive(formGroup: UntypedFormGroup): string[] {
+    return Object.keys(formGroup.controls).filter((key) => formGroup.get(key).value);
+  }
+
+  public getOrganisationsEinheitenGroup(): UntypedFormGroup {
+    return <UntypedFormGroup>this.form.get(UserFormService.GROUPS);
+  }
+
+  private getRoleGroup(roleGroup: string): UntypedFormGroup {
+    return <UntypedFormGroup>this.form.get(UserFormService.CLIENT_ROLES).get(roleGroup);
+  }
+
+  ngOnDestroy(): void {
+    this._initOrganisationsEinheiten$.unsubscribe();
+  }
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.html b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..b0f7d7ec9bc48aeec3ca7ebf097e35bf5008fd43
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.html
@@ -0,0 +1 @@
+<admin-user-list [usersStateResource]="usersStateResource$ | async" />
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e3b7bcedafc499a5bf7187d096e9bcb1eb9d6105
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.spec.ts
@@ -0,0 +1,58 @@
+import { User, UserService } from '@admin-client/user-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { getMockComponent, mock, Mock } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { Observable, of } from 'rxjs';
+import { UserListContainerComponent } from './user-list-container.component';
+import { UserListComponent } from './user-list/user-list.component';
+
+describe('UserListContainerComponent', () => {
+  let component: UserListContainerComponent;
+  let fixture: ComponentFixture<UserListContainerComponent>;
+
+  let userService: Mock<UserService>;
+
+  const usersStateResource: StateResource<User[]> = createEmptyStateResource<User[]>();
+  const usersStateResource$: Observable<StateResource<User[]>> = of(usersStateResource);
+
+  beforeEach(async () => {
+    userService = {
+      ...mock(UserService),
+      getAll: jest.fn().mockReturnValue(usersStateResource$),
+    };
+
+    await TestBed.configureTestingModule({
+      imports: [UserListContainerComponent, MockComponent(UserListComponent)],
+      providers: [{ provide: UserService, useValue: userService }],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserListContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('component', () => {
+    describe('ngOnInit', () => {
+      it('should get users from userService', () => {
+        component.ngOnInit();
+
+        expect(component.usersStateResource$).toBe(usersStateResource$);
+      });
+    });
+  });
+
+  describe('template', () => {
+    it('should have user list', async () => {
+      const userList: UserListComponent = getMockComponent(fixture, UserListComponent);
+
+      fixture.detectChanges();
+
+      expect(userList.usersStateResource).toBe(usersStateResource);
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..371df8b2664808b39e524439d4ae45d63016f177
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list-container.component.ts
@@ -0,0 +1,22 @@
+import { User, UserService } from '@admin-client/user-shared';
+import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
+import { AsyncPipe } from '@angular/common';
+import { Component, inject, OnInit } from '@angular/core';
+import { Observable, of } from 'rxjs';
+import { UserListComponent } from './user-list/user-list.component';
+
+@Component({
+  selector: 'admin-user-list-container',
+  standalone: true,
+  imports: [UserListComponent, AsyncPipe],
+  templateUrl: './user-list-container.component.html',
+})
+export class UserListContainerComponent implements OnInit {
+  private userService = inject(UserService);
+
+  public usersStateResource$: Observable<StateResource<User[]>> = of(createEmptyStateResource<User[]>());
+
+  ngOnInit(): void {
+    this.usersStateResource$ = this.userService.getAll();
+  }
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.html b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..bffb14da6bda5e9ae083f25f445a12b3d6854ae5
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.html
@@ -0,0 +1,32 @@
+<!--
+
+    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+    Ministerpräsidenten des Landes Schleswig-Holstein
+    Staatskanzlei
+    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+
+    Lizenziert unter der EUPL, Version 1.2 oder - sobald
+    diese von der Europäischen Kommission genehmigt wurden -
+    Folgeversionen der EUPL ("Lizenz");
+    Sie dürfen dieses Werk ausschließlich gemäß
+    dieser Lizenz nutzen.
+    Eine Kopie der Lizenz finden Sie hier:
+
+    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+    Sofern nicht durch anwendbare Rechtsvorschriften
+    gefordert oder in schriftlicher Form vereinbart, wird
+    die unter der Lizenz verbreitete Software "so wie sie
+    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+    ausdrücklich oder stillschweigend - verbreitet.
+    Die sprachspezifischen Genehmigungen und Beschränkungen
+    unter der Lizenz sind dem Lizenztext zu entnehmen.
+
+-->
+<h1 class="heading-1 mb-4">Benutzer & Rollen</h1>
+<ods-routing-button [linkPath]="ROUTES.BENUTZER_NEU" text="Benutzer hinzufügen" class="mb-4" dataTestId="add-user-button" />
+<ods-list>
+  @for (user of usersStateResource.resource; track $index) {
+    <admin-user [user]="user" class="block w-full" />
+  }
+</ods-list>
\ No newline at end of file
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..23bc4e3efe65add8ea04eaff6d4324b907190dc8
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.spec.ts
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { ROUTES } from '@admin-client/shared';
+import { User } from '@admin-client/user-shared';
+import { createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
+import { getMockComponent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RoutingButtonComponent } from '@ods/component';
+import { MockComponent } from 'ng-mocks';
+import { createUser } from '../../../../../user-shared/test/user';
+import { UserListComponent } from './user-list.component';
+import { UserComponent } from './user/user.component';
+
+describe('UsersListComponent', () => {
+  let component: UserListComponent;
+  let fixture: ComponentFixture<UserListComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UserListComponent],
+      declarations: [MockComponent(RoutingButtonComponent), MockComponent(UserComponent)],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserListComponent);
+    component = fixture.componentInstance;
+    component.usersStateResource = createEmptyStateResource();
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    it('should render routing button', () => {
+      const routingButton: RoutingButtonComponent = getMockComponent(fixture, RoutingButtonComponent);
+      expect(routingButton.linkPath).toBe(ROUTES.BENUTZER_NEU);
+    });
+
+    it('should render UserComponent if user in resource', () => {
+      const user: User = createUser();
+      component.usersStateResource = createStateResource([user]);
+
+      fixture.detectChanges();
+
+      const userComponent: UserComponent = getMockComponent(fixture, UserComponent);
+      expect(userComponent.user).toEqual(user);
+    });
+  });
+});
+//todo: fix datei herstellen
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.ts
similarity index 54%
rename from alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.ts
rename to alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.ts
index e5df17d9fb3bbf0f95105085e1943d58a13dbab7..984d6540945e2739b3b89e66eb9fc03ebc7264d6 100644
--- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.ts
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user-list.component.ts
@@ -21,39 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ROUTES } from '@admin-client/shared';
 import { User } from '@admin-client/user-shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { AsyncPipe } from '@angular/common';
-import { Component, inject } from '@angular/core';
-import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { ButtonWithSpinnerComponent, CheckboxEditorComponent, TextEditorComponent } from '@ods/component';
-import { Observable } from 'rxjs';
-import { UserAddFormservice } from './user-add.formservice';
+import { Component, Input } from '@angular/core';
+import { ButtonWithSpinnerComponent, RoutingButtonComponent } from '@ods/component';
+import { ListComponent, ListItemComponent } from '@ods/system';
+import { UserComponent } from './user/user.component';
 
 @Component({
-  selector: 'admin-user-add-form',
-  providers: [UserAddFormservice],
-  templateUrl: './user-add-form.component.html',
+  selector: 'admin-user-list',
+  templateUrl: './user-list.component.html',
   standalone: true,
-  imports: [
-    FormsModule,
-    ReactiveFormsModule,
-    TextEditorComponent,
-    ButtonWithSpinnerComponent,
-    CheckboxEditorComponent,
-    AsyncPipe,
-  ],
+  imports: [ButtonWithSpinnerComponent, ListComponent, UserComponent, AsyncPipe, ListItemComponent, RoutingButtonComponent],
 })
-export class UserAddFormComponent {
-  public readonly formService = inject(UserAddFormservice);
-
-  submitStateResource$: Observable<StateResource<User>>;
-
-  protected readonly UserAddFormService = UserAddFormservice;
-
-  public submit(): void {
-    if (!this.formService.form.invalid) {
-      this.submitStateResource$ = this.formService.submit();
-    }
-  }
+export class UserListComponent {
+  @Input() usersStateResource: StateResource<User[]>;
+  protected readonly ROUTES = ROUTES;
 }
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.html b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..7d455acd981b3767f809810878baea7ebedd5cf1
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.html
@@ -0,0 +1,16 @@
+<dl>
+  <div *ngIf="user.email" class="flex items-center gap-2">
+    <dt>
+      <span class="sr-only">E-Mail:</span>
+      <ods-mailbox-icon size="small" class="stroke-gray-600" />
+    </dt>
+    <dd>{{ user.email }}</dd>
+  </div>
+  <div class="flex items-center gap-2">
+    <dt>
+      <span class="sr-only">Benutzername:</span>
+      <ods-person-icon />
+    </dt>
+    <dd>{{ user.username }}</dd>
+  </div>
+</dl>
\ No newline at end of file
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1e7e38f5986de68deb361d2346d85575fe3b1e2f
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { createUser } from '../../../../../../../user-shared/test/user';
+import { UserDataComponent } from './user-data.component';
+
+describe('UserDataComponent', () => {
+  let component: UserDataComponent;
+  let fixture: ComponentFixture<UserDataComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UserDataComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserDataComponent);
+    component = fixture.componentInstance;
+    component.user = createUser();
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..06483d8051e1c29deb922fad3acd5e35e8a45c55
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-data/user-data.component.ts
@@ -0,0 +1,14 @@
+import { User } from '@admin-client/user-shared';
+import { NgIf } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { MailboxIconComponent, PersonIconComponent } from '@ods/system';
+
+@Component({
+  selector: 'admin-user-data',
+  standalone: true,
+  imports: [MailboxIconComponent, NgIf, PersonIconComponent],
+  templateUrl: './user-data.component.html',
+})
+export class UserDataComponent {
+  @Input() user: User;
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.html b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..550037d391c229139ce5248398ff7715a6e730d4
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.html
@@ -0,0 +1,18 @@
+<h4 class="sr-only">Zuständige Stellen</h4>
+
+@if (organisationsEinheiten.length > 0) {
+  <ul class="list-outside list-disc pl-4">
+    @for(group of organisationsEinheiten | slice: 0 : MAX_GROUPS_TO_DISPLAY; track $index) {
+      <li>{{ group }}</li>
+    }
+  </ul>
+  @if (organisationsEinheiten.length > MAX_GROUPS_TO_DISPLAY) {
+    @if(organisationsEinheiten.length - MAX_GROUPS_TO_DISPLAY === 1 ){
+      <p class="pl-4 text-gray-500">und 1 weiterer</p>
+    } @else {
+      <p class="pl-4 text-gray-500">und {{ organisationsEinheiten.length - MAX_GROUPS_TO_DISPLAY }} weitere</p>
+    }
+  }
+} @else {
+  <p> keine zuständige Stelle zugewiesen </p>
+}
\ No newline at end of file
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..356f6e35b57947e2023679b0a6050cbe7aa8461c
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.spec.ts
@@ -0,0 +1,74 @@
+import { getElementFromFixture } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { faker } from '@faker-js/faker/locale/de';
+import { UserOrganisationsEinheitenComponent } from './user-organisations-einheiten.component';
+
+describe('UserOrganisationsEinheitenComponent', () => {
+  let component: UserOrganisationsEinheitenComponent;
+  let fixture: ComponentFixture<UserOrganisationsEinheitenComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UserOrganisationsEinheitenComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserOrganisationsEinheitenComponent);
+    component = fixture.componentInstance;
+    component.organisationsEinheiten = [];
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    describe('list', () => {
+      it('should not exist if organisationsEinheiten is empty', () => {
+        const list: HTMLElement = getElementFromFixture(fixture, 'ul');
+        expect(list).toBeFalsy();
+      });
+
+      it('should exist if organisationsEinheiten is not empty', () => {
+        component.organisationsEinheiten = [faker.word.sample()];
+
+        fixture.detectChanges();
+
+        const list: HTMLElement = getElementFromFixture(fixture, 'ul');
+        expect(list).toBeTruthy();
+      });
+
+      it('should show first three organisations einheiten', () => {
+        component.organisationsEinheiten = Array.from({ length: 4 }, faker.word.sample);
+
+        fixture.detectChanges();
+
+        const list: HTMLElement = getElementFromFixture(fixture, 'ul');
+        expect(list.children.length).toBe(3);
+      });
+
+      it('should show "und 1 weiterer" for four organisations einheiten', () => {
+        component.organisationsEinheiten = Array.from({ length: 4 }, faker.word.sample);
+
+        fixture.detectChanges();
+
+        const text: HTMLElement = getElementFromFixture(fixture, 'p');
+        expect(text.textContent).toBe('und 1 weiterer');
+      });
+
+      it('should show "und #Anzahl weitere" for more then four organisations einheiten', () => {
+        component.organisationsEinheiten = Array.from({ length: 5 }, faker.word.sample);
+
+        fixture.detectChanges();
+
+        const text: HTMLElement = getElementFromFixture(fixture, 'p');
+        expect(text.textContent).toBe('und 2 weitere');
+      });
+    });
+
+    it('should show text if organisationsEinheiten is empty', () => {
+      const text: HTMLElement = getElementFromFixture(fixture, 'p');
+      expect(text).toBeTruthy();
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..edca1ee33858b19ccfa8cc3a7ca99b1ed01a26cc
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-organisations-einheiten/user-organisations-einheiten.component.ts
@@ -0,0 +1,14 @@
+import { NgForOf, SlicePipe } from '@angular/common';
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'admin-user-organisations-einheiten',
+  standalone: true,
+  imports: [NgForOf, SlicePipe],
+  templateUrl: './user-organisations-einheiten.component.html',
+})
+export class UserOrganisationsEinheitenComponent {
+  @Input() organisationsEinheiten: string[];
+
+  public readonly MAX_GROUPS_TO_DISPLAY: number = 3;
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.html b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..26b29dd6d1082879467997191335242a734aac76
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.html
@@ -0,0 +1,10 @@
+<dl class="flex flex-wrap gap-2">
+  <dt class="sr-only">Rollen:</dt>
+  @for (role of roles; track $index) {
+    <dd
+      class="inline-flex flex-shrink-0 items-center rounded-full bg-green-50 px-1.5 py-0.5 text-sm font-medium text-green-700 ring-1 ring-inset ring-green-600/20"
+    >
+      {{ role }}
+    </dd>
+  }
+</dl>
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8f52db7113826be222340eb6b544736ed9d0aca2
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UserRolesComponent } from './user-roles.component';
+
+describe('UserRolesComponent', () => {
+  let component: UserRolesComponent;
+  let fixture: ComponentFixture<UserRolesComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UserRolesComponent]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(UserRolesComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cce2e75634290372729bf2542f93299a917af780
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user-roles/user-roles.component.ts
@@ -0,0 +1,12 @@
+import { NgForOf } from '@angular/common';
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'admin-user-roles',
+  standalone: true,
+  imports: [NgForOf],
+  templateUrl: './user-roles.component.html',
+})
+export class UserRolesComponent {
+  @Input() roles: string[];
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.html b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..b19df22eb0537d270a9485c8a03b39bf04108939
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.html
@@ -0,0 +1,12 @@
+<ods-list-item [path]="user.id" [attr.data-test-id]="'user-entry-' + user.username">
+  <div class="flex-1 basis-1/2">
+    <div class="mb-2 flex flex-wrap items-center gap-3">
+      <h3 class="text-md font-semibold">{{ user | toUserName }}</h3>
+      <admin-user-roles [roles]="user | toUserRoles" />
+    </div>
+
+    <admin-user-data [user]="user" />
+  </div>
+
+  <admin-user-organisations-einheiten [organisationsEinheiten]="user.groups" class="flex-1 basis-1/2" />
+</ods-list-item>
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.spec.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..afd371e8c6812b03a5b6b671545b4e4344c18ac3
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.spec.ts
@@ -0,0 +1,64 @@
+import { getMockComponent } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ListItemComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { ToUserRolesPipe } from '../../../../../../user-shared/src/lib/to-user-roles.pipe';
+import { createUser } from '../../../../../../user-shared/test/user';
+import { UserDataComponent } from './user-data/user-data.component';
+import { UserOrganisationsEinheitenComponent } from './user-organisations-einheiten/user-organisations-einheiten.component';
+import { UserRolesComponent } from './user-roles/user-roles.component';
+import { UserComponent } from './user.component';
+
+describe('UserComponent', () => {
+  let component: UserComponent;
+  let fixture: ComponentFixture<UserComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [
+        UserComponent,
+        MockComponent(ListItemComponent),
+        MockComponent(UserRolesComponent),
+        MockComponent(UserDataComponent),
+        MockComponent(UserOrganisationsEinheitenComponent),
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UserComponent);
+    component = fixture.componentInstance;
+    component.user = createUser();
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    it('should render ListItemComponent', () => {
+      const listItem: ListItemComponent = getMockComponent(fixture, ListItemComponent);
+      expect(listItem.path).toBe(component.user.id);
+    });
+
+    it('should render user roles', () => {
+      const toUserRolesPipe = new ToUserRolesPipe();
+
+      const userRoles: UserRolesComponent = getMockComponent(fixture, UserRolesComponent);
+      expect(userRoles.roles).toEqual(toUserRolesPipe.transform(component.user));
+    });
+
+    it('should render user data', () => {
+      const userData: UserDataComponent = getMockComponent(fixture, UserDataComponent);
+      expect(userData.user).toBe(component.user);
+    });
+
+    it('should render user organisationsEinheiten', () => {
+      const userOrganisationsEinheiten: UserOrganisationsEinheitenComponent = getMockComponent(
+        fixture,
+        UserOrganisationsEinheitenComponent,
+      );
+
+      expect(userOrganisationsEinheiten.organisationsEinheiten).toBe(component.user.groups);
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.ts b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f46a2dc2950c2f651dc2e313a4831cbf10ca6ba8
--- /dev/null
+++ b/alfa-client/libs/admin/user/src/lib/user-list-container/user-list/user/user.component.ts
@@ -0,0 +1,25 @@
+import { ToUserNamePipe, ToUserRolesPipe, User } from '@admin-client/user-shared';
+import { NgForOf } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { ListItemComponent } from '@ods/system';
+import { UserDataComponent } from './user-data/user-data.component';
+import { UserOrganisationsEinheitenComponent } from './user-organisations-einheiten/user-organisations-einheiten.component';
+import { UserRolesComponent } from './user-roles/user-roles.component';
+
+@Component({
+  selector: 'admin-user',
+  standalone: true,
+  imports: [
+    ListItemComponent,
+    NgForOf,
+    ToUserNamePipe,
+    UserOrganisationsEinheitenComponent,
+    UserDataComponent,
+    UserRolesComponent,
+    ToUserRolesPipe,
+  ],
+  templateUrl: './user.component.html',
+})
+export class UserComponent {
+  @Input() user: User;
+}
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.html b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.html
deleted file mode 100644
index e95ce249045910cd9c9951d9f4851e905832a883..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!--
-
-    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
-
--->
-<div class="max-w-[960px]" [formGroup]="formService.form">
-  <h1 class="heading-1 mb-4">Benutzer anlegen</h1>
-  <div class="mb-4 grid gap-4 xl:grid-cols-2">
-    <ods-text-editor [formControlName]="UserAddFormService.VORNAME" [isRequired]="true" label="Vorname"/>
-    <ods-text-editor [formControlName]="UserAddFormService.NACHNAME" [isRequired]="true" label="Nachname"/>
-    <ods-text-editor [formControlName]="UserAddFormService.BENUTZERNAME" [isRequired]="true" label="Benutzername"/>
-    <ods-text-editor [formControlName]="UserAddFormService.EMAIL" [isRequired]="true" label="E-Mail"/>
-  </div>
-
-  <h3 class="text-md mb-4 block font-medium text-text">Organisationseinheiten</h3>
-  <ods-button-with-spinner text="Organisationseinheit hinzufügen" variant="outline"
-                           dataTestId="Add-organisationseinheit-button"/>
-
-  <h2 class="heading-2 mt-4">Rollen für OZG-Cloud</h2>
-  <div [formGroupName]="UserAddFormService.ROLLEN_GROUP" class="mb-8 flex gap-56">
-    <div [formGroupName]="UserAddFormService.ADMINISTRATION_GROUP" class="flex flex-col gap-2">
-      <h3 class="text-md block font-medium text-text">Administration</h3>
-      <ods-checkbox-editor [formControlName]="UserAddFormService.ADMIN" label="Admin" inputId="admin"/>
-    </div>
-    <div [formGroupName]="UserAddFormService.ALFA_GROUP" class="flex flex-col gap-2">
-      <h3 class="text-md block font-medium text-text">Alfa</h3>
-      <ods-checkbox-editor [formControlName]="UserAddFormService.LOESCHEN" label="Löschen" inputId="delete"/>
-      <ods-checkbox-editor [formControlName]="UserAddFormService.USER" label="User" inputId="user"/>
-      <ods-checkbox-editor [formControlName]="UserAddFormService.POSTSTELLE" label="Poststelle" inputId="post_office"/>
-    </div>
-  </div>
-
-  <ods-button-with-spinner [stateResource]="submitStateResource$ | async" (clickEmitter)="submit()" text="Speichern"
-                           dataTestId="save-button"/>
-</div>
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.spec.ts b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.spec.ts
deleted file mode 100644
index 085cc24dc7a7e2e2bdd84a63287424511d428146..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add-form.component.spec.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { User, UserService } from '@admin-client/user-shared';
-import { NavigationService } from '@alfa-client/navigation-shared';
-import { createStateResource, StateResource } from '@alfa-client/tech-shared';
-import { dispatchEventFromFixture, getDebugElementFromFixtureByCss, mock, Mock } from '@alfa-client/test-utils';
-import { SnackBarService } from '@alfa-client/ui';
-import { CommonModule } from '@angular/common';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { ReactiveFormsModule } from '@angular/forms';
-import { ButtonWithSpinnerComponent, CheckboxEditorComponent, TextEditorComponent } from '@ods/component';
-import { cold } from 'jest-marbles';
-import { createUser } from 'libs/admin/user-shared/test/user';
-import { MockComponent } from 'ng-mocks';
-import { of } from 'rxjs';
-import { getDataTestIdAttributeOf } from '../../../../../../tech-shared/test/data-test';
-import { UserAddFormComponent } from './user-add-form.component';
-import { UserAddFormservice } from './user-add.formservice';
-
-describe('UserAddFormComponent', () => {
-  let component: UserAddFormComponent;
-  let fixture: ComponentFixture<UserAddFormComponent>;
-
-  let formService: UserAddFormservice;
-
-  let userService: Mock<UserService>;
-  let navigationService: Mock<NavigationService>;
-  let snackBarService: Mock<SnackBarService>;
-
-  const saveButton: string = getDataTestIdAttributeOf('save-button');
-
-  beforeEach(async () => {
-    userService = mock(UserService);
-    navigationService = mock(NavigationService);
-    snackBarService = mock(SnackBarService);
-
-    await TestBed.configureTestingModule({
-      imports: [CommonModule, ReactiveFormsModule],
-      declarations: [
-        UserAddFormComponent,
-        MockComponent(ButtonWithSpinnerComponent),
-        MockComponent(TextEditorComponent),
-        MockComponent(CheckboxEditorComponent),
-      ],
-      providers: [
-        UserAddFormservice,
-        { provide: UserService, useValue: userService },
-        { provide: NavigationService, useValue: navigationService },
-        { provide: SnackBarService, useValue: snackBarService },
-      ],
-    }).compileComponents();
-
-    fixture = TestBed.createComponent(UserAddFormComponent);
-    component = fixture.componentInstance;
-    formService = component.formService;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-
-  describe('component', () => {
-    describe('submit', () => {
-      const userStateResource: StateResource<User> = createStateResource(createUser());
-
-      beforeEach(() => {
-        formService.submit = jest.fn().mockReturnValue(of(userStateResource));
-      });
-
-      it('should call formService submit if form is valid', () => {
-        jest.spyOn(formService.form, 'invalid', 'get').mockReturnValue(false);
-
-        component.submit();
-
-        expect(formService.submit).toHaveBeenCalled();
-      });
-
-      it('should not call formService submit if form is not valid', () => {
-        jest.spyOn(formService.form, 'invalid', 'get').mockReturnValue(true);
-
-        component.submit();
-
-        expect(formService.submit).not.toHaveBeenCalled();
-      });
-
-      it('should set submitState$ if form is valid', () => {
-        jest.spyOn(formService.form, 'invalid', 'get').mockReturnValue(false);
-
-        component.submit();
-
-        expect(component.submitStateResource$).toBeObservable(cold('(a|)', { a: userStateResource }));
-      });
-    });
-  });
-
-  describe('template', () => {
-    describe('ods-button-with-spinner save', () => {
-      describe('input', () => {
-        it('should be set', () => {
-          const stateResource: StateResource<User> = createStateResource(createUser());
-          component.submitStateResource$ = of(stateResource);
-
-          fixture.detectChanges();
-
-          expect(getDebugElementFromFixtureByCss(fixture, saveButton).componentInstance.stateResource).toEqual(stateResource);
-        });
-      });
-
-      describe('output', () => {
-        it('should call submit', () => {
-          const submitSpy: jest.SpyInstance = jest.spyOn(component, 'submit');
-
-          dispatchEventFromFixture(fixture, saveButton, 'clickEmitter');
-
-          expect(submitSpy).toHaveBeenCalled();
-        });
-      });
-    });
-  });
-});
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts
deleted file mode 100644
index f347f2a1a63692a3225c5824c19f2476af9855ef..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ROUTES } from '@admin-client/shared';
-import { User, UserService } from '@admin-client/user-shared';
-import { NavigationService } from '@alfa-client/navigation-shared';
-import { createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
-import { Mock, mock } from '@alfa-client/test-utils';
-import { SnackBarService } from '@alfa-client/ui';
-import { fakeAsync, TestBed, tick } from '@angular/core/testing';
-import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
-import { cold } from 'jest-marbles';
-import { createUser } from 'libs/admin/user-shared/test/user';
-import { of, throwError } from 'rxjs';
-import { UserAddFormservice } from './user-add.formservice';
-import SpyInstance = jest.SpyInstance;
-
-describe('UserAddFormService', () => {
-  let formService: UserAddFormservice;
-  let roleGroup: UntypedFormGroup;
-  let alfaGroup: UntypedFormGroup;
-  let administrationGroup: UntypedFormGroup;
-
-  let userService: Mock<UserService>;
-  let navigationService: Mock<NavigationService>;
-  let snackBarService: Mock<SnackBarService>;
-
-  beforeEach(() => {
-    userService = { ...mock(UserService), refresh: jest.fn(), create: jest.fn() };
-    navigationService = mock(NavigationService);
-    snackBarService = mock(SnackBarService);
-
-    TestBed.configureTestingModule({
-      providers: [
-        UserAddFormservice,
-        UntypedFormBuilder,
-        { provide: UserService, useValue: userService },
-        { provide: NavigationService, useValue: navigationService },
-        { provide: SnackBarService, useValue: snackBarService },
-      ],
-    });
-
-    formService = TestBed.inject(UserAddFormservice);
-    roleGroup = <UntypedFormGroup>formService.form.get(UserAddFormservice.ROLLEN_GROUP);
-    alfaGroup = <UntypedFormGroup>roleGroup.get(UserAddFormservice.ALFA_GROUP);
-    administrationGroup = <UntypedFormGroup>roleGroup.get(UserAddFormservice.ADMINISTRATION_GROUP);
-  });
-
-  it('should create', () => {
-    expect(formService).toBeTruthy();
-  });
-
-  describe('initAlfaGroupLogic', () => {
-    it('should call handleAlfaGroupChange when value of form element changes', fakeAsync(() => {
-      const handleAlfaGroupChangeSpy: SpyInstance = jest.spyOn(formService as any, 'handleAlfaGroupChange');
-
-      alfaGroup.get(UserAddFormservice.LOESCHEN).setValue(true);
-
-      tick();
-
-      expect(handleAlfaGroupChangeSpy).toHaveBeenCalled();
-    }));
-  });
-
-  describe('roleValidator', () => {
-    it('should return error if no role is selected', () => {
-      const result = formService.roleValidator()(roleGroup);
-
-      expect(result).toEqual({ atLeastOneRoleSelected: true });
-    });
-
-    it('should return null if at least one role is selected', () => {
-      alfaGroup.get(UserAddFormservice.LOESCHEN).setValue(true);
-
-      const result = formService.roleValidator()(roleGroup);
-
-      expect(result).toBeNull();
-    });
-  });
-
-  describe('handleAlfaGroupChange', () => {
-    it('should call disableUncheckedCheckboxes if any checkbox is checked', () => {
-      jest.spyOn(formService as any, 'isAnyChecked').mockReturnValue(true);
-      const disableUncheckedCheckboxesSpy: SpyInstance = jest.spyOn(formService as any, 'disableUncheckedCheckboxes');
-
-      formService.handleAlfaGroupChange(alfaGroup);
-
-      expect(disableUncheckedCheckboxesSpy).toHaveBeenCalled();
-    });
-
-    it('should call enableAllCheckboxes if not any checkbox is checked', () => {
-      jest.spyOn(formService as any, 'isAnyChecked').mockReturnValue(false);
-      const enableAllCheckboxesSpy: SpyInstance = jest.spyOn(formService as any, 'enableAllCheckboxes');
-
-      formService.handleAlfaGroupChange(alfaGroup);
-
-      expect(enableAllCheckboxesSpy).toHaveBeenCalled();
-    });
-  });
-
-  describe('isAnyChecked', () => {
-    it('should return false if no checkbox is checked', () => {
-      const result = formService.isAnyChecked(alfaGroup);
-
-      expect(result).toBe(false);
-    });
-
-    it('should return true if any checkbox is checked', () => {
-      alfaGroup.get(UserAddFormservice.LOESCHEN).setValue(true);
-
-      const result = formService.isAnyChecked(alfaGroup);
-
-      expect(result).toBe(true);
-    });
-  });
-
-  describe('disableUncheckedCheckboxes', () => {
-    it('if control value is false then control should be disabled', () => {
-      const control: AbstractControl = alfaGroup.get(UserAddFormservice.LOESCHEN);
-      control.setValue(false);
-
-      formService.disableUncheckedCheckboxes(alfaGroup);
-
-      expect(control.disabled).toBe(true);
-    });
-
-    it('if control value is true then control should NOT be disabled', () => {
-      const control: AbstractControl = alfaGroup.get(UserAddFormservice.LOESCHEN);
-      control.setValue(true);
-
-      formService.disableUncheckedCheckboxes(alfaGroup);
-
-      expect(control.disabled).toBe(false);
-    });
-  });
-
-  describe('updateCheckboxStates', () => {
-    it('if control value is false then control should be disabled', () => {
-      const control: AbstractControl = alfaGroup.get(UserAddFormservice.LOESCHEN);
-      control.setValue(false);
-
-      formService.disableUncheckedCheckboxes(alfaGroup);
-
-      expect(control.disabled).toBe(true);
-    });
-  });
-
-  describe('enableAllCheckboxes', () => {
-    it('if control value is true then control should be enabled', () => {
-      const control: AbstractControl = alfaGroup.get(UserAddFormservice.LOESCHEN);
-      const enableSpy = jest.spyOn(control, 'enable');
-
-      formService.enableAllCheckboxes(alfaGroup);
-
-      expect(enableSpy).toHaveBeenCalled();
-    });
-  });
-
-  describe('doSubmit', () => {
-    const user: User = createUser();
-
-    beforeEach(() => {
-      userService.create.mockReturnValue(of(false));
-    });
-
-    it('should call createUser', () => {
-      const createUserSpy: SpyInstance = jest.spyOn(formService as any, 'createUser');
-
-      formService.submit();
-
-      expect(createUserSpy).toHaveBeenCalled();
-    });
-
-    it('should call userService create', () => {
-      jest.spyOn(formService as any, 'createUser').mockReturnValue(user);
-
-      formService.submit();
-
-      expect(userService.create).toHaveBeenCalledWith(user);
-    });
-
-    it('should return user as stateResource', () => {
-      userService.create.mockReturnValue(cold('-ab', { a: true, b: false }));
-      jest.spyOn(formService as any, 'createUser').mockReturnValue(user);
-
-      const result = formService.submit();
-
-      expect(result).toBeObservable(
-        cold('abc', {
-          a: createEmptyStateResource<User>(true),
-          b: createStateResource(user, true),
-          c: createStateResource(user, false),
-        }),
-      );
-    });
-
-    it('should call handleOnCreateUserSuccess if not loading', fakeAsync(() => {
-      const handleOnCreateUserSuccessSpy: SpyInstance = jest.spyOn(formService, 'handleOnCreateUserSuccess');
-
-      formService.submit().subscribe();
-      tick();
-
-      expect(handleOnCreateUserSuccessSpy).toHaveBeenCalled();
-    }));
-
-    it('should not call handleOnCreateUserSuccess if loading', fakeAsync(() => {
-      userService.create.mockReturnValue(of(true));
-      const handleOnCreateUserSuccessSpy: SpyInstance = jest.spyOn(formService, 'handleOnCreateUserSuccess');
-
-      formService.submit().subscribe();
-      tick();
-
-      expect(handleOnCreateUserSuccessSpy).not.toHaveBeenCalled();
-    }));
-
-    it('should call handleSubmitError on error', fakeAsync(() => {
-      userService.create.mockReturnValue(throwError(() => new Error()));
-      const handleSubmitErrorSpy: SpyInstance = jest.spyOn(formService, 'handleSubmitError');
-
-      formService.submit().subscribe();
-      tick();
-
-      expect(handleSubmitErrorSpy).toHaveBeenCalled();
-    }));
-  });
-
-  describe('handleOnCreateUserSuccess', () => {
-    it('should show success message', () => {
-      formService.handleOnCreateUserSuccess();
-
-      expect(snackBarService.showInfo).toHaveBeenCalledWith('Der Benutzer wurde hinzugefügt.');
-    });
-
-    it('should navigate back to user list', () => {
-      formService.handleOnCreateUserSuccess();
-
-      expect(navigationService.navigate).toHaveBeenCalledWith(ROUTES.BENUTZER_UND_ROLLEN);
-    });
-  });
-
-  describe('handleSubmitError', () => {
-    it('should return empty stateResource', () => {
-      const result = formService.handleSubmitError();
-
-      expect(result).toBeObservable(cold('(a|)', { a: createEmptyStateResource<User>() }));
-    });
-
-    it('should show error message', fakeAsync(() => {
-      formService.handleSubmitError().subscribe();
-      tick();
-
-      expect(snackBarService.showError).toHaveBeenCalledWith('Der Benutzer konnte nicht hinzugefügt werden.');
-    }));
-  });
-
-  describe('getRoles', () => {
-    it('should return no roles when none are active', () => {
-      const result: string[] = formService.getRoles(UserAddFormservice.ALFA_GROUP);
-
-      expect(result).toEqual([]);
-    });
-
-    it('should return poststelle role when active', () => {
-      alfaGroup.get(UserAddFormservice.POSTSTELLE).setValue(true);
-
-      const result: string[] = formService.getRoles(UserAddFormservice.ALFA_GROUP);
-
-      expect(result).toEqual([UserAddFormservice.POSTSTELLE]);
-    });
-  });
-});
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts
deleted file mode 100644
index dd10a07fb294fc452d893af76750d33c5e7c4efc..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ROUTES } from '@admin-client/shared';
-import { User, UserService } from '@admin-client/user-shared';
-import { NavigationService } from '@alfa-client/navigation-shared';
-import {
-  AbstractFormService,
-  createEmptyStateResource,
-  createStateResource,
-  EMPTY_STRING,
-  StateResource,
-} from '@alfa-client/tech-shared';
-import { SnackBarService } from '@alfa-client/ui';
-import { Injectable } from '@angular/core';
-import {
-  AbstractControl,
-  FormControl,
-  UntypedFormBuilder,
-  UntypedFormGroup,
-  ValidationErrors,
-  ValidatorFn,
-  Validators,
-} from '@angular/forms';
-import { catchError, map, Observable, of, startWith, tap } from 'rxjs';
-
-@Injectable()
-export class UserAddFormservice extends AbstractFormService<User> {
-  public static readonly VORNAME: string = 'vorname';
-  public static readonly NACHNAME: string = 'nachname';
-  public static readonly BENUTZERNAME: string = 'benutzername';
-  public static readonly EMAIL: string = 'e-mail';
-
-  public static readonly ROLLEN_GROUP: string = 'rollen';
-  public static readonly ADMINISTRATION_GROUP: string = 'administration';
-  public static readonly ADMIN: string = 'ADMIN_ADMIN';
-  public static readonly ALFA_GROUP: string = 'alfa';
-  public static readonly LOESCHEN: string = 'VERWALTUNG_LOESCHEN';
-  public static readonly USER: string = 'VERWALTUNG_USER';
-  public static readonly POSTSTELLE: string = 'VERWALTUNG_POSTSTELLE';
-
-  public static readonly USER_ADD_PREFIX: string = 'userAdd';
-
-  constructor(
-    public formBuilder: UntypedFormBuilder,
-    private userService: UserService,
-    private navigationService: NavigationService,
-    private snackBarService: SnackBarService,
-  ) {
-    super(formBuilder);
-    this.initAlfaGroupLogic();
-  }
-
-  protected initForm(): UntypedFormGroup {
-    return this.formBuilder.group({
-      [UserAddFormservice.VORNAME]: new FormControl(EMPTY_STRING, Validators.required),
-      [UserAddFormservice.NACHNAME]: new FormControl(EMPTY_STRING, Validators.required),
-      [UserAddFormservice.BENUTZERNAME]: new FormControl(EMPTY_STRING, Validators.required),
-      [UserAddFormservice.EMAIL]: new FormControl(EMPTY_STRING, [Validators.required, Validators.email]),
-      [UserAddFormservice.ROLLEN_GROUP]: this.formBuilder.group(
-        {
-          [UserAddFormservice.ADMINISTRATION_GROUP]: this.formBuilder.group({
-            [UserAddFormservice.ADMIN]: new FormControl(false),
-          }),
-          [UserAddFormservice.ALFA_GROUP]: this.formBuilder.group({
-            [UserAddFormservice.LOESCHEN]: new FormControl(false),
-            [UserAddFormservice.USER]: new FormControl(false),
-            [UserAddFormservice.POSTSTELLE]: new FormControl(false),
-          }),
-        },
-        { validators: this.roleValidator() },
-      ),
-    });
-  }
-
-  roleValidator(): ValidatorFn {
-    return (control: AbstractControl<UntypedFormGroup>): ValidationErrors | null => {
-      const rolesGroups: UntypedFormGroup = control.value;
-
-      if (this.anyRoleSelected(rolesGroups)) {
-        return null;
-      }
-
-      return { atLeastOneRoleSelected: true };
-    };
-  }
-
-  private anyRoleSelected(rolesGroups: UntypedFormGroup): boolean {
-    for (const subGroup of Object.values(rolesGroups)) {
-      if (Object.values(subGroup).includes(true)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  protected initAlfaGroupLogic(): void {
-    const alfaGroup: UntypedFormGroup = this.getRoleGroup(UserAddFormservice.ALFA_GROUP);
-    alfaGroup.valueChanges.subscribe(() => {
-      this.handleAlfaGroupChange(alfaGroup);
-    });
-  }
-
-  handleAlfaGroupChange(group: UntypedFormGroup): void {
-    const anyChecked: boolean = this.isAnyChecked(group);
-    if (anyChecked) {
-      this.disableUncheckedCheckboxes(group);
-    } else {
-      this.enableAllCheckboxes(group);
-    }
-  }
-
-  isAnyChecked(group: UntypedFormGroup): boolean {
-    return Object.keys(group.controls).some((key) => group.controls[key].value);
-  }
-
-  disableUncheckedCheckboxes(alfaGroup: UntypedFormGroup): void {
-    for (const control of Object.values<AbstractControl>(alfaGroup.controls)) {
-      if (control.value === false) control.disable({ emitEvent: false });
-    }
-  }
-
-  enableAllCheckboxes(group: UntypedFormGroup): void {
-    for (const control of Object.values<AbstractControl>(group.controls)) {
-      control.enable({ emitEvent: false });
-    }
-  }
-
-  protected doSubmit(): Observable<StateResource<User>> {
-    const user: User = this.createUser();
-    return this.userService.create(user).pipe(
-      tap((loading: boolean): void => this.executeIfNotLoading(loading, () => this.handleOnCreateUserSuccess())),
-      map((loading: boolean): StateResource<User> => createStateResource<User>(user, loading)),
-      catchError((): Observable<StateResource<User>> => this.handleSubmitError()),
-      startWith(createEmptyStateResource<User>(true)),
-    );
-  }
-
-  private executeIfNotLoading(loading: boolean, func: () => void): void {
-    if (!loading) func();
-  }
-
-  handleOnCreateUserSuccess(): void {
-    this.snackBarService.showInfo('Der Benutzer wurde hinzugefügt.');
-    this.navigationService.navigate(ROUTES.BENUTZER_UND_ROLLEN);
-  }
-
-  handleSubmitError(): Observable<StateResource<User>> {
-    this.snackBarService.showError('Der Benutzer konnte nicht hinzugefügt werden.');
-    return of(createEmptyStateResource<User>());
-  }
-
-  createUser(): User {
-    return {
-      id: EMPTY_STRING,
-      email: this.form.get(UserAddFormservice.EMAIL).value,
-      username: this.form.get(UserAddFormservice.BENUTZERNAME).value,
-      firstName: this.form.get(UserAddFormservice.VORNAME).value,
-      lastName: this.form.get(UserAddFormservice.NACHNAME).value,
-      enabled: true,
-      clientRoles: {
-        alfa: this.getRoles(UserAddFormservice.ALFA_GROUP),
-        admin: this.getRoles(UserAddFormservice.ADMINISTRATION_GROUP),
-      },
-    };
-  }
-
-  getRoles(roleGroup: string): string[] {
-    return this.getActiveRoles(this.getRoleGroup(roleGroup));
-  }
-
-  private getActiveRoles(formGroup: UntypedFormGroup): string[] {
-    return Object.keys(formGroup.controls).filter((key) => formGroup.get(key).value);
-  }
-
-  private getRoleGroup(roleGroup: string): UntypedFormGroup {
-    return <UntypedFormGroup>this.form.get(UserAddFormservice.ROLLEN_GROUP).get(roleGroup);
-  }
-
-  protected getPathPrefix(): string {
-    return UserAddFormservice.USER_ADD_PREFIX;
-  }
-}
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.html b/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.html
deleted file mode 100644
index 4fb48e8cbc912f251454cf28d5e7a05109b93384..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!--
-
-    Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
-    Ministerpräsidenten des Landes Schleswig-Holstein
-    Staatskanzlei
-    Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
-
-    Lizenziert unter der EUPL, Version 1.2 oder - sobald
-    diese von der Europäischen Kommission genehmigt wurden -
-    Folgeversionen der EUPL ("Lizenz");
-    Sie dürfen dieses Werk ausschließlich gemäß
-    dieser Lizenz nutzen.
-    Eine Kopie der Lizenz finden Sie hier:
-
-    https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
-
-    Sofern nicht durch anwendbare Rechtsvorschriften
-    gefordert oder in schriftlicher Form vereinbart, wird
-    die unter der Lizenz verbreitete Software "so wie sie
-    ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
-    ausdrücklich oder stillschweigend - verbreitet.
-    Die sprachspezifischen Genehmigungen und Beschränkungen
-    unter der Lizenz sind dem Lizenztext zu entnehmen.
-
--->
-<h1 class="heading-1">Benutzer & Rollen</h1>
-<ods-button-with-spinner
-  text="Benutzer hinzufügen"
-  class="py-8"
-  dataTestId="Add-user-button"
-  (clickEmitter)="navigateToAddUser()"
-/>
-<ods-list *ngIf="users$ | async as users">
-  <ods-list-item *ngFor="let user of users.resource" [path]="user.username" [attr.data-test-id]="'User-entry-' + user.username">
-    <div class="flex-1 basis-1/2">
-      <div class="mb-2 flex flex-wrap items-center gap-3">
-        <h3 class="text-md font-semibold">{{ user | toUserName }}</h3>
-        <dl class="flex flex-wrap gap-2">
-          <dt class="sr-only">Rollen:</dt>
-          <dd
-            *ngFor="let role of getRoles(user)"
-            class="inline-flex flex-shrink-0 items-center rounded-full bg-green-50 px-1.5 py-0.5 text-sm font-medium text-green-700 ring-1 ring-inset ring-green-600/20"
-          >
-            {{ role }}
-          </dd>
-        </dl>
-      </div>
-
-      <dl>
-        <div *ngIf="user.email" class="flex items-center gap-2">
-          <dt>
-            <span class="sr-only">E-Mail:</span>
-            <ods-mailbox-icon size="small" class="stroke-gray-600" />
-          </dt>
-          <dd>{{ user.email }}</dd>
-        </div>
-        <div class="flex items-center gap-2">
-          <dt>
-            <span class="sr-only">Benutzername:</span>
-            <ods-person-icon />
-          </dt>
-          <dd>{{ user.username }}</dd>
-        </div>
-      </dl>
-    </div>
-
-    <div class="flex-1 basis-1/2">
-      <h4 class="sr-only">Zuständige Stellen</h4>
-
-      <ng-container *ngIf="user.groups.length > 0; else noGroups">
-        <ul class="list-outside list-disc pl-4">
-          <ng-container *ngFor="let group of user.groups | slice: 0 : GROUPS_TO_DISPLAY">
-            <li>{{ group }}</li>
-          </ng-container>
-        </ul>
-        <p *ngIf="user.groups.length > GROUPS_TO_DISPLAY" class="pl-4 text-gray-500">und {{ user.groups.length - 3 }} weitere</p>
-      </ng-container>
-      <ng-template #noGroups>keine zuständige Stelle zugewiesen</ng-template>
-    </div>
-  </ods-list-item>
-</ods-list>
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.spec.ts b/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.spec.ts
deleted file mode 100644
index feabd22992fa379e1ec37308132052edde220a2a..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.spec.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ROUTES } from '@admin-client/shared';
-import { createStateResource } from '@alfa-client/tech-shared';
-import { Mock, mock } from '@alfa-client/test-utils';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { Router } from '@angular/router';
-import { ButtonWithSpinnerComponent } from '@ods/component';
-import { MailboxIconComponent, PersonIconComponent } from '@ods/system';
-import { ToUserNamePipe } from 'libs/admin/user-shared/src/lib/to-user-name.pipe';
-import { UserService } from 'libs/admin/user-shared/src/lib/user.service';
-import { createUser } from 'libs/admin/user-shared/test/user';
-import { MockComponent, MockPipe } from 'ng-mocks';
-import { UsersRolesComponent } from './users-roles.component';
-
-describe('UsersRolesComponent', () => {
-  let component: UsersRolesComponent;
-  let fixture: ComponentFixture<UsersRolesComponent>;
-
-  let router: Mock<Router>;
-  let userService: Mock<UserService>;
-
-  beforeEach(() => {
-    userService = {
-      ...mock(UserService),
-      get: jest.fn(),
-      refresh: jest.fn(),
-    };
-    router = mock(Router);
-  });
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      providers: [
-        { provide: UserService, useValue: userService },
-        { provide: Router, useValue: router },
-      ],
-      imports: [
-        MockComponent(ButtonWithSpinnerComponent),
-        MockComponent(MailboxIconComponent),
-        MockComponent(PersonIconComponent),
-        MockPipe(ToUserNamePipe),
-        UsersRolesComponent,
-      ],
-    }).compileComponents();
-
-    fixture = TestBed.createComponent(UsersRolesComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  describe('component', () => {
-    describe('ngOnInit', () => {
-      it('should get users from userService', () => {
-        const userState = createStateResource([createUser()]);
-        userService.get.mockReturnValueOnce(userState);
-
-        component.ngOnInit();
-
-        expect(component.users$).toBe(userState);
-      });
-    });
-
-    describe('ngOnDestroy', () => {
-      it('should refresh users state resource', () => {
-        component.ngOnDestroy();
-
-        expect(userService.refresh).toHaveBeenCalled();
-      });
-    });
-
-    describe('navigateToAddUser', () => {
-      it('should navigate to add user', () => {
-        component.navigateToAddUser();
-
-        expect(router.navigate).toHaveBeenCalledWith([ROUTES.BENUTZER_UND_ROLLEN_NEU]);
-      });
-    });
-
-    describe('getRoles', () => {
-      it('should return roles', () => {
-        const user = createUser();
-        const roles = component.getRoles(user);
-
-        expect(roles).toEqual([...user.clientRoles.alfa, ...user.clientRoles.admin]);
-      });
-    });
-  });
-
-  describe('template', () => {
-    it('should create', () => {
-      expect(component).toBeTruthy();
-    });
-
-    describe('constructor', () => {
-      it('should call userService.get', () => {
-        expect(userService.get).toHaveBeenCalled();
-      });
-    });
-  });
-});
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.ts b/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.ts
deleted file mode 100644
index 916c81eaf876f94c6d5b18f8fe6c7803f55d2b00..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin/user/src/lib/users-roles/users-roles.component.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-import { ROUTES } from '@admin-client/shared';
-import { ToUserNamePipe, User, UserService } from '@admin-client/user-shared';
-import { StateResource } from '@alfa-client/tech-shared';
-import { CommonModule } from '@angular/common';
-import { Component, inject, OnDestroy, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { ButtonWithSpinnerComponent } from '@ods/component';
-import { ListComponent, ListItemComponent, MailboxIconComponent, PersonIconComponent } from '@ods/system';
-import { Observable } from 'rxjs';
-
-@Component({
-  selector: 'admin-users-roles',
-  templateUrl: './users-roles.component.html',
-  standalone: true,
-  imports: [
-    CommonModule,
-    ButtonWithSpinnerComponent,
-    ListComponent,
-    ListItemComponent,
-    MailboxIconComponent,
-    PersonIconComponent,
-    ToUserNamePipe,
-  ],
-})
-export class UsersRolesComponent implements OnInit, OnDestroy {
-  private router = inject(Router);
-  private userService = inject(UserService);
-
-  public users$: Observable<StateResource<User[]>>;
-  public readonly GROUPS_TO_DISPLAY: number = 3;
-
-  ngOnInit(): void {
-    this.users$ = this.userService.get();
-  }
-
-  ngOnDestroy(): void {
-    this.userService.refresh();
-  }
-
-  public navigateToAddUser(): void {
-    this.router.navigate([ROUTES.BENUTZER_UND_ROLLEN_NEU]);
-  }
-
-  getRoles(user: User): string[] {
-    return Object.keys(user.clientRoles).reduce((acc: string[], client: string): string[] => {
-      acc.push(...user.clientRoles[client]);
-      return acc;
-    }, []);
-  }
-}
diff --git a/alfa-client/libs/admin/user/test/form.ts b/alfa-client/libs/admin/user/test/form.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7b3f06850de1ff16504596b38056fb3752b3d5e5
--- /dev/null
+++ b/alfa-client/libs/admin/user/test/form.ts
@@ -0,0 +1,29 @@
+import { EMPTY_STRING } from '@alfa-client/tech-shared';
+import { FormControl, UntypedFormGroup } from '@angular/forms';
+import { faker } from '@faker-js/faker/locale/de';
+import { UserFormService } from '../src/lib/user-form/user.formservice';
+
+export function createUserFormGroup(): UntypedFormGroup {
+  return new UntypedFormGroup({
+    [UserFormService.FIRST_NAME]: new FormControl(EMPTY_STRING),
+    [UserFormService.LAST_NAME]: new FormControl(EMPTY_STRING),
+    [UserFormService.USERNAME]: new FormControl(EMPTY_STRING),
+    [UserFormService.EMAIL]: new FormControl(EMPTY_STRING),
+    [UserFormService.CLIENT_ROLES]: new UntypedFormGroup({
+      [UserFormService.ADMINISTRATION_GROUP]: new UntypedFormGroup({
+        [UserFormService.ADMIN]: new FormControl(false),
+      }),
+      [UserFormService.ALFA_GROUP]: new UntypedFormGroup({
+        [UserFormService.LOESCHEN]: new FormControl(false),
+        [UserFormService.USER]: new FormControl(false),
+        [UserFormService.POSTSTELLE]: new FormControl(false),
+      }),
+    }),
+    [UserFormService.GROUPS]: new UntypedFormGroup({
+      organisationsEinheiten: new FormControl([
+        { [faker.word.sample()]: new FormControl(true) },
+        { [faker.word.sample()]: new FormControl(true) },
+      ]),
+    }),
+  });
+}
diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.model.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.model.ts
index 0786840d01e7e6c4f0ae6e57e107a77efdc2fade..c03829b96e8049f9472d5cb482c78774264c3e6a 100644
--- a/alfa-client/libs/api-root-shared/src/lib/api-root.model.ts
+++ b/alfa-client/libs/api-root-shared/src/lib/api-root.model.ts
@@ -29,6 +29,7 @@ export interface ApiRoot {
   javaVersion: string;
   production: boolean;
   barrierefreiheitUrl: string;
+  impressumUrl: string;
 }
 
 export interface ApiRootResource extends ApiRoot, Resource {}
diff --git a/alfa-client/libs/api-root-shared/test/api-root.ts b/alfa-client/libs/api-root-shared/test/api-root.ts
index f0f8b4a7f3f717cc71c13609c159ce85d09f56c9..b18613718166ac6c923ac2ffdbd349da1f529d13 100644
--- a/alfa-client/libs/api-root-shared/test/api-root.ts
+++ b/alfa-client/libs/api-root-shared/test/api-root.ts
@@ -34,6 +34,7 @@ export function createApiRoot(): ApiRoot {
     buildTime: '1',
     javaVersion: '1',
     production: false,
-    barrierefreiheitUrl: 'https://example.com/',
+    barrierefreiheitUrl: 'https://example-barrierefreiheit.com/',
+    impressumUrl: 'https://example-impressum.com/',
   };
 }
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
index 995bfd1a0aaab32d118d524b2aad934752457e40..d799453d615d41bd0e21b7940461d59c7131adf0 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
@@ -1359,14 +1359,19 @@ describe('BescheidService', () => {
 
     it('should upload file', (done) => {
       service.uploadAttachment(bescheidResource, file).subscribe(() => {
-        expect(binaryFileService.uploadFile).toBeCalledWith(bescheidResource, BescheidLinkRel.UPLOAD_ATTACHMENT, file, false);
+        expect(binaryFileService.uploadFile).toHaveBeenCalledWith(
+          bescheidResource,
+          BescheidLinkRel.UPLOAD_ATTACHMENT,
+          file,
+          false,
+        );
         done();
       });
     });
 
     it('should handle attachment upload', (done) => {
       service.uploadAttachment(bescheidResource, file).subscribe(() => {
-        expect(service.handleAttachmentUpload).toBeCalledWith(binaryFileStateResource);
+        expect(service.handleAttachmentUpload).toHaveBeenCalledWith(binaryFileStateResource);
         done();
       });
     });
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.html
index 1cfba1363c99867c5f7ea006754866e9a73d03b7..dd3c548c5ab8b1d8b0811314cc637153af596aab 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard-container.component.html
@@ -31,7 +31,7 @@
       >
         <ng-container *ngIf="bescheidDraftStateResource$ | async as bescheidStateResource">
           <ods-button
-            variant="icon"
+            variant="ghost"
             size="fit"
             class="absolute right-0 top-0 text-text"
             (clickEmitter)="cancelWizard(bescheidStateResource.resource)"
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.ts b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.ts
index bd4c8efd4b9fd5fd6d9fb6bed4499d15c3746420..4f9036dadf2779eff368da4ceeef7709f53df4e7 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.ts
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid.formservice.ts
@@ -22,16 +22,17 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { Bescheid, BescheidLinkRel, BescheidResource, BescheidSendBy, BescheidService } from '@alfa-client/bescheid-shared';
+import { CommandResource } from '@alfa-client/command-shared';
 import { AbstractFormService, StateResource, convertToBoolean, formatForDatabase } from '@alfa-client/tech-shared';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Injectable } from '@angular/core';
 import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
-import { Resource, ResourceUri, getUrl, hasLink } from '@ngxp/rest';
+import { ResourceUri, getUrl, hasLink } from '@ngxp/rest';
 import { isUndefined } from 'lodash-es';
 import { Observable, startWith } from 'rxjs';
 
 @Injectable()
-export class BescheidFormService extends AbstractFormService {
+export class BescheidFormService extends AbstractFormService<CommandResource> {
   static readonly FIELD_BESCHIEDEN_AM = 'beschiedenAm';
   static readonly FIELD_BEWILLIGT = 'bewilligt';
   static readonly FIELD_BESCHEID_DOCUMENT = 'bescheidDocument';
@@ -63,7 +64,7 @@ export class BescheidFormService extends AbstractFormService {
     });
   }
 
-  protected doSubmit(): Observable<StateResource<Resource>> {
+  protected doSubmit(): Observable<StateResource<CommandResource>> {
     return this.bescheidService.createBescheid(this.vorgangWithEingangResource, this.getBescheidFormValue());
   }
 
diff --git a/alfa-client/libs/design-component/src/index.ts b/alfa-client/libs/design-component/src/index.ts
index 7e763fa075fc7b1b74492e8e4a18070c146bfb1a..745720be72b8665fb259372141e6ab5537efbfbe 100644
--- a/alfa-client/libs/design-component/src/index.ts
+++ b/alfa-client/libs/design-component/src/index.ts
@@ -30,3 +30,5 @@ export * from './lib/form/formcontrol-editor.abstract.component';
 export * from './lib/form/single-file-upload-editor/single-file-upload-editor.component';
 export * from './lib/form/text-editor/text-editor.component';
 export * from './lib/form/textarea-editor/textarea-editor.component';
+export * from './lib/routing-button/routing-button.component';
+export * from './lib/spinner/spinner.component';
diff --git a/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.spec.ts b/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.spec.ts
index 05eb9e49c06ecdc641672a33f31760984dd15714..de1242c608e560f453c76ee160ddaf89dc3b9b0c 100644
--- a/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.spec.ts
+++ b/alfa-client/libs/design-component/src/lib/button-with-spinner/button-with-spinner.component.spec.ts
@@ -22,10 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import {
-  createCommandErrorStateResource,
-  createCommandResource,
-} from 'libs/command-shared/test/command';
+import { createCommandErrorStateResource, createCommandResource } from 'libs/command-shared/test/command';
 import { createApiError } from 'libs/tech-shared/test/error';
 import { ButtonWithSpinnerComponent } from './button-with-spinner.component';
 
@@ -55,7 +52,7 @@ describe('ButtonWithSpinnerComponent', () => {
 
       component.ngOnInit();
 
-      expect(component.getStateResource).toBeCalled();
+      expect(component.getStateResource).toHaveBeenCalled();
     });
   });
 
diff --git a/alfa-client/libs/design-component/src/lib/download-button/download-button.component.ts b/alfa-client/libs/design-component/src/lib/download-button/download-button.component.ts
index 8ab53e9155bbce0ddef770c837fd20615bb6a503..7c479ec1713ce6efca5777e04880575c623ba23d 100644
--- a/alfa-client/libs/design-component/src/lib/download-button/download-button.component.ts
+++ b/alfa-client/libs/design-component/src/lib/download-button/download-button.component.ts
@@ -36,7 +36,7 @@ type IconVariants = VariantProps<typeof iconVariants>;
   imports: [CommonModule, ButtonComponent, SaveIconComponent],
   template: `<ods-button
     [dataTestId]="dataTestId"
-    variant="icon"
+    variant="ghost"
     size="fit"
     spinnerSize="small"
     [isLoading]="isLoading"
diff --git a/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.spec.ts b/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fb79d2714b85698c69bb8405f36470da96abe579
--- /dev/null
+++ b/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.spec.ts
@@ -0,0 +1,22 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterModule } from '@angular/router';
+import { RoutingButtonComponent } from './routing-button.component';
+
+describe('RoutingButtonComponent', () => {
+  let component: RoutingButtonComponent;
+  let fixture: ComponentFixture<RoutingButtonComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [RoutingButtonComponent, RouterModule.forRoot([])],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(RoutingButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.ts b/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2a25cd22e5df3e74e404a3fd986d737b29ab5a2c
--- /dev/null
+++ b/alfa-client/libs/design-component/src/lib/routing-button/routing-button.component.ts
@@ -0,0 +1,22 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { RouterLink } from '@angular/router';
+
+@Component({
+  selector: 'ods-routing-button',
+  standalone: true,
+  imports: [CommonModule, RouterLink],
+  host: { class: 'block' },
+  template: `<a
+    [routerLink]="'/' + linkPath"
+    [attr.data-test-id]="dataTestId"
+    class="block min-h-9 w-fit min-w-32 rounded bg-primary px-4 py-2 text-sm font-medium text-white shadow-sm outline-focus hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
+  >
+    {{ text }}
+  </a>`,
+})
+export class RoutingButtonComponent {
+  @Input() linkPath: string;
+  @Input() text: string;
+  @Input() dataTestId: string;
+}
diff --git a/alfa-client/libs/design-component/src/lib/spinner/spinner.component.spec.ts b/alfa-client/libs/design-component/src/lib/spinner/spinner.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1f288367d58f44b50f8e5d7b4100d8cfc7c75b60
--- /dev/null
+++ b/alfa-client/libs/design-component/src/lib/spinner/spinner.component.spec.ts
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { SpinnerComponent } from './spinner.component';
+
+describe('SpinnerComponent', () => {
+  let component: SpinnerComponent;
+  let fixture: ComponentFixture<SpinnerComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [SpinnerComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(SpinnerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('isLoading', () => {
+    it('should return false if stateResource is null', () => {
+      component.stateResource = null;
+
+      const isLoading: boolean = component.isLoading;
+
+      expect(isLoading).toBeFalsy();
+    });
+
+    it('should return false', () => {
+      component.stateResource.loading = component.stateResource.reload = false;
+
+      const isLoading: boolean = component.isLoading;
+
+      expect(isLoading).toBeFalsy();
+    });
+
+    it('should return true if stateResource is loading', () => {
+      component.stateResource.loading = true;
+      component.stateResource.reload = false;
+
+      const isLoading: boolean = component.isLoading;
+
+      expect(isLoading).toBeTruthy();
+    });
+
+    it('should return true if stateResource is reloading', () => {
+      component.stateResource.loading = false;
+      component.stateResource.reload = true;
+
+      const isLoading: boolean = component.isLoading;
+
+      expect(isLoading).toBeTruthy();
+    });
+  });
+});
diff --git a/alfa-client/libs/design-component/src/lib/spinner/spinner.component.ts b/alfa-client/libs/design-component/src/lib/spinner/spinner.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..df3873f7f5a966f9e2a0d385aa8f0e3d6cc0f452
--- /dev/null
+++ b/alfa-client/libs/design-component/src/lib/spinner/spinner.component.ts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { CommonModule } from '@angular/common';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { IconVariants, SpinnerIconComponent } from '@ods/system';
+import { isNil } from 'lodash-es';
+
+@Component({
+  selector: 'ods-spinner',
+  standalone: true,
+  imports: [CommonModule, SpinnerIconComponent],
+  template: `@if (isLoading) {
+      <ods-spinner-icon [size]="spinnerSize" />
+    } @else {
+      <ng-content />
+    }`,
+})
+export class SpinnerComponent {
+  @Input() dataTestId: string = '';
+  @Input() stateResource: StateResource<unknown> = createEmptyStateResource();
+  @Input() spinnerSize: IconVariants['size'] = 'extra-large';
+
+  @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
+
+  public get isLoading(): boolean {
+    return !isNil(this.stateResource) && (this.stateResource.loading || this.stateResource.reload);
+  }
+}
diff --git a/alfa-client/libs/design-system/src/index.ts b/alfa-client/libs/design-system/src/index.ts
index 1f46fdee2bf9ba94f5af17a5ee742be0afe2aa85..467032047c06e4ae9c4a6e3948cc13a704b8761d 100644
--- a/alfa-client/libs/design-system/src/index.ts
+++ b/alfa-client/libs/design-system/src/index.ts
@@ -30,6 +30,7 @@ export * from './lib/button-card/button-card.component';
 export * from './lib/button/button.component';
 export * from './lib/dropdown-menu/dropdown-menu-button-item/dropdown-menu-button-item.component';
 export * from './lib/dropdown-menu/dropdown-menu-item/dropdown-menu-item.component';
+export * from './lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component';
 export * from './lib/dropdown-menu/dropdown-menu-text-item/dropdown-menu-text-item.component';
 export * from './lib/dropdown-menu/dropdown-menu/dropdown-menu.component';
 export * from './lib/form/button-toggle/button-toggle.component';
@@ -41,18 +42,24 @@ export * from './lib/form/radio-button-card/radio-button-card.component';
 export * from './lib/form/text-input/text-input.component';
 export * from './lib/form/textarea/textarea.component';
 export * from './lib/icons/accessibility-icon/accessibility-icon.component';
+export * from './lib/icons/account-circle-icon/account-circle-icon.component';
 export * from './lib/icons/admin-logo-icon/admin-logo-icon.component';
 export * from './lib/icons/archive-icon/archive-icon.component';
+export * from './lib/icons/arrow-back-icon/arrow-back-icon.component';
 export * from './lib/icons/attachment-icon/attachment-icon.component';
 export * from './lib/icons/bescheid-generate-icon/bescheid-generate-icon.component';
 export * from './lib/icons/bescheid-upload-icon/bescheid-upload-icon.component';
+export * from './lib/icons/check-circle-icon/check-circle-icon.component';
 export * from './lib/icons/check-icon/check-icon.component';
 export * from './lib/icons/close-icon/close-icon.component';
+export * from './lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.component';
+export * from './lib/icons/discard-vorgang-icon/discard-vorgang-icon.component';
 export * from './lib/icons/edit-icon/edit-icon.component';
 export * from './lib/icons/error-icon/error-icon.component';
 export * from './lib/icons/exclamation-icon/exclamation-icon.component';
 export * from './lib/icons/external-unit-icon/external-unit-icon.component';
 export * from './lib/icons/file-icon/file-icon.component';
+export * from './lib/icons/forward-vorgang-icon/forward-vorgang-icon.component';
 export * from './lib/icons/help-icon/help-icon.component';
 export * from './lib/icons/iconVariants';
 export * from './lib/icons/logout-icon/logout-icon.component';
@@ -64,12 +71,17 @@ export * from './lib/icons/ozg-logo-icon/ozg-logo-icon.component';
 export * from './lib/icons/person-icon/person-icon.component';
 export * from './lib/icons/plus-icon/plus-icon.component';
 export * from './lib/icons/public-administration-icon/public-administration-icon.component';
+export * from './lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.component';
 export * from './lib/icons/save-icon/save-icon.component';
 export * from './lib/icons/search-icon/search-icon.component';
 export * from './lib/icons/send-icon/send-icon.component';
+export * from './lib/icons/settings-icon/settings-icon.component';
 export * from './lib/icons/spinner-icon/spinner-icon.component';
 export * from './lib/icons/stamp-icon/stamp-icon.component';
 export * from './lib/icons/statistic-icon/statistic-icon.component';
+export * from './lib/icons/undo-icon/undo-icon.component';
+export * from './lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.component';
+export * from './lib/icons/update-icon/update-icon.component';
 export * from './lib/icons/user-icon/user-icon.component';
 export * from './lib/icons/users-icon/users-icon.component';
 export * from './lib/instant-search/instant-search/instant-search.component';
diff --git a/alfa-client/libs/design-system/src/lib/button/button.component.ts b/alfa-client/libs/design-system/src/lib/button/button.component.ts
index 57f92a99128c13852d1c12a7fc265ac5653ee0ed..46b0308c205dff5a889142e76693dd27cffc30bb 100644
--- a/alfa-client/libs/design-system/src/lib/button/button.component.ts
+++ b/alfa-client/libs/design-system/src/lib/button/button.component.ts
@@ -22,34 +22,61 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { CommonModule } from '@angular/common';
-import { Component, EventEmitter, Input, Output } from '@angular/core';
-import { VariantProps, cva } from 'class-variance-authority';
+import { booleanAttribute, Component, EventEmitter, Input, Output } from '@angular/core';
+import { cva, VariantProps } from 'class-variance-authority';
 
 import { IconVariants } from '../icons/iconVariants';
 import { SpinnerIconComponent } from '../icons/spinner-icon/spinner-icon.component';
 
 export const buttonVariants = cva(
   [
-    'flex items-center gap-4 rounded-md disabled:cursor-wait text-sm font-medium box-border',
-    'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus',
+    'flex items-center gap-4 rounded-lg text-sm font-medium box-border',
+    'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
   ],
   {
     variants: {
       variant: {
-        primary: 'hover:enabled:bg-primary-hover bg-primary text-white shadow-sm',
+        primary: 'bg-primary text-whitetext shadow-md hover:enabled:bg-primary-hover focus-visible:bg-primary-hover',
         outline:
-          'border border-primary bg-background-50 text-primary hover:enabled:bg-background-100',
-        icon: 'border border-transparent hover:border-primary',
+          'border border-primary bg-background-50 text-primary shadow-md hover:enabled:bg-ghost-hover focus-visible:bg-ghost-hover focus-visible:border-background-200',
+        ghost:
+          'border border-transparent hover:enabled:bg-ghost-hover text-primary focus-visible:border-background-200 focus-visible:bg-ghost-hover font-semibold [&]:focus-visible:outline-offset-1',
       },
       size: {
         medium: 'h-9 py-2 px-4 min-w-32',
         fit: 'h-fit p-2',
       },
+      disabled: {
+        false: null,
+        true: ['opacity-70', 'cursor-not-allowed'],
+      },
+      destructive: {
+        false: 'outline-focus',
+        true: 'outline-destructive',
+      },
     },
     defaultVariants: {
       variant: 'primary',
       size: 'medium',
+      disabled: false,
     },
+    compoundVariants: [
+      {
+        variant: 'primary',
+        destructive: true,
+        class: '[&]:hover:enabled:bg-destructive-primary-hover [&]:bg-destructive [&]:outline-destructive',
+      },
+      {
+        variant: 'outline',
+        destructive: true,
+        class: '[&]:border-destructive [&]:text-destructive [&]:hover:enabled:bg-destructive-hover',
+      },
+      {
+        variant: 'ghost',
+        destructive: true,
+        class: '[&]:text-destructive [&]:hover:enabled:bg-destructive-hover',
+      },
+    ],
   },
 );
 type ButtonVariants = VariantProps<typeof buttonVariants>;
@@ -60,9 +87,9 @@ type ButtonVariants = VariantProps<typeof buttonVariants>;
   imports: [CommonModule, SpinnerIconComponent],
   template: `<button
     type="button"
-    [ngClass]="buttonVariants({ size, variant })"
-    [disabled]="isLoading"
-    [attr.aria-disabled]="isLoading"
+    [ngClass]="buttonVariants({ size, variant, disabled, destructive })"
+    [disabled]="isDisabled"
+    [attr.aria-disabled]="isDisabled"
     [attr.aria-label]="text"
     [attr.data-test-id]="dataTestId"
     (click)="clickEmitter.emit()"
@@ -75,12 +102,18 @@ type ButtonVariants = VariantProps<typeof buttonVariants>;
 export class ButtonComponent {
   @Input() text: string = '';
   @Input() dataTestId: string = '';
+  @Input() disabled: boolean = false;
   @Input() isLoading: boolean = false;
+  @Input({ transform: booleanAttribute }) destructive: boolean = false;
   @Input() variant: ButtonVariants['variant'];
   @Input() size: ButtonVariants['size'];
   @Input() spinnerSize: IconVariants['size'] = 'medium';
 
   @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
 
-  buttonVariants = buttonVariants;
+  get isDisabled() {
+    return this.disabled || this.isLoading;
+  }
+
+  readonly buttonVariants = buttonVariants;
 }
diff --git a/alfa-client/libs/design-system/src/lib/button/button.stories.ts b/alfa-client/libs/design-system/src/lib/button/button.stories.ts
index 85a01551e086059b33f8cd65cbba7fe2041e1fc5..e54dffa64fbe732a78aa27cf4e5074fbd4abfc91 100644
--- a/alfa-client/libs/design-system/src/lib/button/button.stories.ts
+++ b/alfa-client/libs/design-system/src/lib/button/button.stories.ts
@@ -45,29 +45,69 @@ export const Default: Story = {
   args: {
     text: 'Hello world!',
     isLoading: false,
+    disabled: false,
+    destructive: false,
     variant: 'primary',
     size: 'medium',
     spinnerSize: 'medium',
   },
   argTypes: {
     variant: {
-      options: ['primary', 'outline'],
+      options: ['primary', 'outline', 'ghost'],
       control: { type: 'radio' },
       table: { defaultValue: { summary: 'primary' } },
     },
+    size: {
+      options: ['medium', 'fit'],
+      control: { type: 'select' },
+      table: { defaultValue: { summary: 'medium' } },
+    },
+    spinnerSize: {
+      description: 'Size of loading spinner',
+      options: ['small', 'medium', 'large', 'extra-large', 'xxl', 'full'],
+      control: { type: 'select' },
+      table: { defaultValue: { summary: 'medium' } },
+    },
+    isLoading: { description: 'Show spinner icon if true' },
+    destructive: { description: 'Red version of a button' },
   },
 };
 
-export const WithIcon: Story = {
+export const PrimaryWithIcon: Story = {
   args: {
     text: 'I have an icon',
+    variant: 'primary',
+  },
+  render: (args) => ({
+    props: args,
+    template: `<ods-button ${argsToTemplate(args)}>
+      <ods-save-icon icon size="small" class="fill-whitetext" />
+    </ods-button>`,
+  }),
+};
+
+export const SecondaryWithIcon: Story = {
+  args: {
+    text: 'I have an icon too',
     variant: 'outline',
-    size: 'medium',
   },
   render: (args) => ({
     props: args,
     template: `<ods-button ${argsToTemplate(args)}>
-      <ods-save-icon icon size='small'></ods-save-icon>
+      <ods-save-icon icon size="small" />
+    </ods-button>`,
+  }),
+};
+
+export const SecondaryIconOnly: Story = {
+  args: {
+    variant: 'outline',
+    size: 'fit',
+  },
+  render: (args) => ({
+    props: args,
+    template: `<ods-button ${argsToTemplate(args)}>
+      <ods-save-icon icon size="small" />
     </ods-button>`,
   }),
 };
@@ -76,19 +116,60 @@ export const IsLoading: Story = {
   args: {
     text: 'Loading...',
     isLoading: true,
-    size: 'medium',
   },
 };
 
-export const OnlyIcon: Story = {
+export const Disabled: Story = {
+  args: {
+    text: "Can't click me",
+    disabled: true,
+  },
+};
+
+export const GhostIcon: Story = {
+  args: {
+    variant: 'ghost',
+    size: 'fit',
+  },
+  render: (args) => ({
+    props: args,
+    template: `<ods-button ${argsToTemplate(args)}>
+      <ods-save-icon icon size='medium' />
+    </ods-button>`,
+  }),
+};
+
+export const GhostIconDestructive: Story = {
   args: {
-    variant: 'icon',
+    variant: 'ghost',
     size: 'fit',
+    destructive: true,
   },
   render: (args) => ({
     props: args,
     template: `<ods-button ${argsToTemplate(args)}>
-      <ods-save-icon icon size='medium'></ods-save-icon>
+      <ods-save-icon icon size='medium' class="fill-destructive" />
     </ods-button>`,
   }),
 };
+
+export const GhostLoadingIcon: Story = {
+  args: {
+    variant: 'ghost',
+    size: 'fit',
+    isLoading: true,
+  },
+  render: (args) => ({
+    props: args,
+    template: `<ods-button ${argsToTemplate(args)}>
+      <ods-save-icon icon size='medium' />
+    </ods-button>`,
+  }),
+};
+
+export const GhostButton: Story = {
+  args: {
+    variant: 'ghost',
+    text: 'I am ghosted',
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.spec.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c97938ebf924672b181116c59a40f3e7906971c1
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.spec.ts
@@ -0,0 +1,40 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { getMockComponent } from '@alfa-client/test-utils';
+import { faker } from '@faker-js/faker';
+import { LinkComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { DropdownMenuLinkItemComponent } from './dropdown-menu-link-item.component';
+
+describe('DropdownMenuLinkItemComponent', () => {
+  let component: DropdownMenuLinkItemComponent;
+  let fixture: ComponentFixture<DropdownMenuLinkItemComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DropdownMenuLinkItemComponent, MockComponent(LinkComponent)],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(DropdownMenuLinkItemComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('template', () => {
+    describe('link', () => {
+      it('should exist with input', () => {
+        component.url = faker.word.sample();
+
+        fixture.detectChanges();
+
+        const link: LinkComponent = getMockComponent(fixture, LinkComponent);
+        expect(link).toBeTruthy();
+        expect(link.url).toBe(component.url);
+      });
+    });
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..52b3e46d6ac1e69ce02472bec600580c6e7663af
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-link-item/dropdown-menu-link-item.component.ts
@@ -0,0 +1,21 @@
+import { Component, Input } from '@angular/core';
+import { OpenLinkIconComponent } from '../../icons/open-link-icon/open-link-icon.component';
+import { LinkComponent } from '../../link/link.component';
+
+@Component({
+  selector: 'ods-dropdown-menu-link-item',
+  standalone: true,
+  imports: [LinkComponent, OpenLinkIconComponent],
+  styles: [':host {@apply first:mt-2}'],
+  template: ` <ods-link [url]="url" class="bg-whitetext" [openInNewTab]="true">
+    <div class="flex items-center gap-2 px-4 py-3">
+      <p class="font-medium text-primary">{{ text }}</p>
+      <ods-open-link-icon class="size-5" />
+      <span class="sr-only">Öffnet in einem neuen Tab</span>
+    </div>
+  </ods-link>`,
+})
+export class DropdownMenuLinkItemComponent {
+  @Input() url: string;
+  @Input() text: string;
+}
diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-text-item/dropdown-menu-text-item.component.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-text-item/dropdown-menu-text-item.component.ts
index f4ecc939dbea7c502369dbf706406d80822c9e09..270bdeef42b132e7ca1b022e11e9b2e9f8db225d 100644
--- a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-text-item/dropdown-menu-text-item.component.ts
+++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu-text-item/dropdown-menu-text-item.component.ts
@@ -5,10 +5,10 @@ import { Component, Input } from '@angular/core';
   selector: 'ods-dropdown-menu-text-item',
   standalone: true,
   imports: [CommonModule],
-  styles: [':host {@apply flex min-h-12 items-start gap-4 px-4 py-3 text-start first:mt-2 last:mb-2}'],
+  styles: [':host {@apply flex min-h-12 items-start gap-4 px-4 py-3 text-start}'],
   template: `
     <ng-content select="[icon]" />
-    <div class="w-80">
+    <div class="w-80 whitespace-normal">
       <p class="mb-1 text-base font-medium">{{ title }}</p>
       <p class="mb-3 text-sm font-normal">{{ description }}</p>
       <ng-content select="[additionalContent]" />
diff --git a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu/dropdown-menu.component.ts b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu/dropdown-menu.component.ts
index 5a7a7bba99728581d60fa65fd9fda66dbf093391..04a15c7eec0780ac9b8709224ab54aecaf77ab6f 100644
--- a/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu/dropdown-menu.component.ts
+++ b/alfa-client/libs/design-system/src/lib/dropdown-menu/dropdown-menu/dropdown-menu.component.ts
@@ -48,7 +48,7 @@ import { twMerge } from 'tailwind-merge';
     </button>
     <div
       *ngIf="isPopupOpen"
-      class="absolute z-50 max-h-120 min-w-44 max-w-96 animate-fadeIn overflow-y-auto rounded bg-dropdownBg shadow-md focus:outline-none"
+      class="absolute z-50 max-h-120 min-w-44 max-w-96 animate-fadeIn overflow-y-auto rounded bg-dropdownBg shadow-md ring-1 ring-grayborder focus:outline-none"
       [ngClass]="alignTo === 'left' ? 'right-0' : 'left-0'"
       role="menu"
       aria-modal="true"
diff --git a/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e50bb31c690ce54140e686a5a50d38d22ee42e22
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { AccountCircleIconComponent } from './account-circle-icon.component';
+
+describe('AccountCircleIconComponent', () => {
+  let component: AccountCircleIconComponent;
+  let fixture: ComponentFixture<AccountCircleIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [AccountCircleIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(AccountCircleIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b762c6cbe32f662f51bb5cb52effd1a267fa3602
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.component.ts
@@ -0,0 +1,27 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-account-circle-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path
+      d="M12.75 2C7.23 2 2.75 6.48 2.75 12C2.75 17.52 7.23 22 12.75 22C18.27 22 22.75 17.52 22.75 12C22.75 6.48 18.27 2 12.75 2ZM7.82 18.28C8.25 17.38 10.87 16.5 12.75 16.5C14.63 16.5 17.26 17.38 17.68 18.28C16.32 19.36 14.61 20 12.75 20C10.89 20 9.18 19.36 7.82 18.28ZM19.11 16.83C17.68 15.09 14.21 14.5 12.75 14.5C11.29 14.5 7.82 15.09 6.39 16.83C5.37 15.49 4.75 13.82 4.75 12C4.75 7.59 8.34 4 12.75 4C17.16 4 20.75 7.59 20.75 12C20.75 13.82 20.13 15.49 19.11 16.83ZM12.75 6C10.81 6 9.25 7.56 9.25 9.5C9.25 11.44 10.81 13 12.75 13C14.69 13 16.25 11.44 16.25 9.5C16.25 7.56 14.69 6 12.75 6ZM12.75 11C11.92 11 11.25 10.33 11.25 9.5C11.25 8.67 11.92 8 12.75 8C13.58 8 14.25 8.67 14.25 9.5C14.25 10.33 13.58 11 12.75 11Z"
+    />
+  </svg>`,
+})
+export class AccountCircleIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..46eae30d492ba7cee189fb67b1f5c63e6f69ba51
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/account-circle-icon/account-circle-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { AccountCircleIconComponent } from './account-circle-icon.component';
+
+const meta: Meta<AccountCircleIconComponent> = {
+  title: 'Icons/Account circle icon',
+  component: AccountCircleIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<AccountCircleIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..744a885c402d72290467b3efb341a2b7adeccf54
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ArrowBackIconComponent } from './arrow-back-icon.component';
+
+describe('ArrowBackIconComponent', () => {
+  let component: ArrowBackIconComponent;
+  let fixture: ComponentFixture<ArrowBackIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [ArrowBackIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ArrowBackIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d0ab0a9d8e61e9e6041df639992347326e0085b7
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.component.ts
@@ -0,0 +1,25 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-arrow-back-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path d="M20.75 11H8.58L14.17 5.41L12.75 4L4.75 12L12.75 20L14.16 18.59L8.58 13H20.75V11Z" />
+  </svg>`,
+})
+export class ArrowBackIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1305d80008efc57e965ebd61690fd6b8e3b2b21f
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/arrow-back-icon/arrow-back-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { ArrowBackIconComponent } from './arrow-back-icon.component';
+
+const meta: Meta<ArrowBackIconComponent> = {
+  title: 'Icons/Arrow back icon',
+  component: ArrowBackIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<ArrowBackIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eda5ec6e8368a70b8e46d9ccea7d18367e87b884
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { CheckCircleIconComponent } from './check-circle-icon.component';
+
+describe('CheckCircleIconComponent', () => {
+  let component: CheckCircleIconComponent;
+  let fixture: ComponentFixture<CheckCircleIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [CheckCircleIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(CheckCircleIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..86aa983a93efa1daf33aaab65d7490b25c2b1a03
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.component.ts
@@ -0,0 +1,27 @@
+import { NgClass } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-check-circle-icon',
+  standalone: true,
+  imports: [NgClass],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path
+      d="M22 5.18L10.59 16.6L6.35 12.36L7.76 10.95L10.59 13.78L20.59 3.78L22 5.18ZM19.79 10.22C19.92 10.79 20 11.39 20 12C20 16.42 16.42 20 12 20C7.58 20 4 16.42 4 12C4 7.58 7.58 4 12 4C13.58 4 15.04 4.46 16.28 5.25L17.72 3.81C16.1 2.67 14.13 2 12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 10.81 21.78 9.67 21.4 8.61L19.79 10.22Z"
+    />
+  </svg>`,
+})
+export class CheckCircleIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = undefined;
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.scss b/alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.stories.ts
similarity index 57%
rename from alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.scss
rename to alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.stories.ts
index dbb9218a330a285d37db355ff911cac5a991f9a9..21d0c5a0c4547882c131eb3e209c4d5fa2fa3d79 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.scss
+++ b/alfa-client/libs/design-system/src/lib/icons/check-circle-icon/check-circle-icon.stories.ts
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
@@ -21,9 +21,30 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import type { Meta, StoryObj } from '@storybook/angular';
 
-// Workaround Material's fixed 48px height
-:host ::ng-deep ozgcloud-icon-button-primary button {
-  position: absolute;
-  top: -14px;
-}
+import { CheckCircleIconComponent } from './check-circle-icon.component';
+
+const meta: Meta<CheckCircleIconComponent> = {
+  title: 'Icons/Check circle icon',
+  component: CheckCircleIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<CheckCircleIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'medium' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..badea86a5eec00f55d092e4af752922e9931d6bb
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { DeleteVorgangFinallyIconComponent } from './delete-vorgang-finally-icon.component';
+
+describe('DeleteVorgangFinallyIconComponent', () => {
+  let component: DeleteVorgangFinallyIconComponent;
+  let fixture: ComponentFixture<DeleteVorgangFinallyIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DeleteVorgangFinallyIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(DeleteVorgangFinallyIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4d99ed334f3142a16b1e91ff8b4d5664a8c7c4de
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.component.ts
@@ -0,0 +1,65 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { IconVariants, iconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-delete-vorgang-finally-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path
+      fill-rule="evenodd"
+      clip-rule="evenodd"
+      d="M17.7366 13V3.11101H12.4405L7.74777 8.05811L7.74777 13H5.75V8.05811C5.75 7.49738 5.96112 6.95968 6.3368 6.56365L11.0296 1.61654C11.4041 1.22173 11.9115 1 12.4405 1H17.7366C18.8399 1 19.7344 1.94513 19.7344 3.11101V13H17.7366Z"
+    />
+    <path
+      d="M7.75 20C7.75 19.4477 8.19772 19 8.75 19C9.30228 19 9.75 19.4477 9.75 20C9.75 20.5523 9.30228 21 8.75 21C8.19772 21 7.75 20.5523 7.75 20Z"
+    />
+    <path
+      d="M7.75 20C7.75 19.4477 8.19772 19 8.75 19C9.30228 19 9.75 19.4477 9.75 20C9.75 20.5523 9.30228 21 8.75 21C8.19772 21 7.75 20.5523 7.75 20Z"
+    />
+    <path
+      d="M11.75 21C11.75 20.4477 12.1977 20 12.75 20C13.3023 20 13.75 20.4477 13.75 21V22C13.75 22.5523 13.3023 23 12.75 23C12.1977 23 11.75 22.5523 11.75 22V21Z"
+    />
+    <path
+      d="M11.75 21C11.75 20.4477 12.1977 20 12.75 20C13.3023 20 13.75 20.4477 13.75 21V22C13.75 22.5523 13.3023 23 12.75 23C12.1977 23 11.75 22.5523 11.75 22V21Z"
+    />
+    <path
+      d="M11.75 13C11.75 12.4477 12.1977 12 12.75 12C13.3023 12 13.75 12.4477 13.75 13V17C13.75 17.5523 13.3023 18 12.75 18C12.1977 18 11.75 17.5523 11.75 17V13Z"
+    />
+    <path
+      d="M11.75 13C11.75 12.4477 12.1977 12 12.75 12C13.3023 12 13.75 12.4477 13.75 13V17C13.75 17.5523 13.3023 18 12.75 18C12.1977 18 11.75 17.5523 11.75 17V13Z"
+    />
+    <path
+      d="M7.75 15C7.75 14.4477 8.19772 14 8.75 14C9.30228 14 9.75 14.4477 9.75 15V16C9.75 16.5523 9.30228 17 8.75 17C8.19772 17 7.75 16.5523 7.75 16V15Z"
+    />
+    <path
+      d="M7.75 15C7.75 14.4477 8.19772 14 8.75 14C9.30228 14 9.75 14.4477 9.75 15V16C9.75 16.5523 9.30228 17 8.75 17C8.19772 17 7.75 16.5523 7.75 16V15Z"
+    />
+    <path
+      d="M15.75 20C15.75 19.4477 16.1977 19 16.75 19C17.3023 19 17.75 19.4477 17.75 20V21C17.75 21.5523 17.3023 22 16.75 22C16.1977 22 15.75 21.5523 15.75 21V20Z"
+    />
+    <path
+      d="M15.75 20C15.75 19.4477 16.1977 19 16.75 19C17.3023 19 17.75 19.4477 17.75 20V21C17.75 21.5523 17.3023 22 16.75 22C16.1977 22 15.75 21.5523 15.75 21V20Z"
+    />
+    <path
+      d="M15.75 15C15.75 14.4477 16.1977 14 16.75 14C17.3023 14 17.75 14.4477 17.75 15V16C17.75 16.5523 17.3023 17 16.75 17C16.1977 17 15.75 16.5523 15.75 16V15Z"
+    />
+    <path
+      d="M15.75 15C15.75 14.4477 16.1977 14 16.75 14C17.3023 14 17.75 14.4477 17.75 15V16C17.75 16.5523 17.3023 17 16.75 17C16.1977 17 15.75 16.5523 15.75 16V15Z"
+    />
+  </svg> `,
+})
+export class DeleteVorgangFinallyIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ddb92e8a002c686a14e3d1cdbfe8f39adc154995
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/delete-vorgang-finally-icon/delete-vorgang-finally-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { DeleteVorgangFinallyIconComponent } from './delete-vorgang-finally-icon.component';
+
+const meta: Meta<DeleteVorgangFinallyIconComponent> = {
+  title: 'Icons/Delete Vorgang finally icon',
+  component: DeleteVorgangFinallyIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<DeleteVorgangFinallyIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..42eed91241f8ca01ee0cb93f12f30a1d95ae608d
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { DiscardVorgangIconComponent } from './discard-vorgang-icon.component';
+
+describe('DiscardVorgangIconComponent', () => {
+  let component: DiscardVorgangIconComponent;
+  let fixture: ComponentFixture<DiscardVorgangIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DiscardVorgangIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(DiscardVorgangIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1cee910facd1e58b08ca945a39ff1267189b5f1e
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.component.ts
@@ -0,0 +1,32 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { IconVariants, iconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-discard-vorgang-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path
+      d="M12.75 19.4L14.35 21L16.75 18.6286L19.15 21L20.75 19.4L18.3786 17L20.75 14.6L19.15 13L16.75 15.4L14.35 13L12.75 14.6L15.15 17L12.75 19.4Z"
+    />
+    <path
+      fill-rule="evenodd"
+      clip-rule="evenodd"
+      d="M17 11V3.77384H12.0294L7.625 7.93078L7.625 18.408H10.75V20.1818H7.625C6.58947 20.1818 5.75 19.3876 5.75 18.408V7.93078C5.75 7.4596 5.94815 7.00779 6.30074 6.67501L10.7051 2.51807C11.0566 2.18631 11.5329 2 12.0294 2H17C18.0355 2 18.875 2.79417 18.875 3.77384V11H17Z"
+    />
+  </svg>`,
+})
+export class DiscardVorgangIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6c73a8fd5973fc24ee0e1464275b9858e004709e
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/discard-vorgang-icon/discard-vorgang-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { DiscardVorgangIconComponent } from './discard-vorgang-icon.component';
+
+const meta: Meta<DiscardVorgangIconComponent> = {
+  title: 'Icons/Discard Vorgang icon',
+  component: DiscardVorgangIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<DiscardVorgangIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/edit-icon/edit-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/edit-icon/edit-icon.component.ts
index c655b7df689e980d84fbf897a9f3b28c649fe416..c5c54a6669c048bc0c1dda16aa7b5680009b9ecf 100644
--- a/alfa-client/libs/design-system/src/lib/icons/edit-icon/edit-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/edit-icon/edit-icon.component.ts
@@ -32,9 +32,9 @@ import { iconVariants, IconVariants } from '../iconVariants';
   imports: [CommonModule],
   template: `<svg
     viewBox="0 0 24 24"
-    fill="none"
     xmlns="http://www.w3.org/2000/svg"
     [ngClass]="twMerge(iconVariants({ size }), 'fill-primary', class)"
+    aria-hidden="true"
   >
     <path
       d="M5 19H6.425L16.2 9.225L14.775 7.8L5 17.575V19ZM3 21V16.75L16.2 3.575C16.4 3.39167 16.6208 3.25 16.8625 3.15C17.1042 3.05 17.3583 3 17.625 3C17.8917 3 18.15 3.05 18.4 3.15C18.65 3.25 18.8667 3.4 19.05 3.6L20.425 5C20.625 5.18333 20.7708 5.4 20.8625 5.65C20.9542 5.9 21 6.15 21 6.4C21 6.66667 20.9542 6.92083 20.8625 7.1625C20.7708 7.40417 20.625 7.625 20.425 7.825L7.25 21H3ZM15.475 8.525L14.775 7.8L16.2 9.225L15.475 8.525Z"
diff --git a/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dcbe4c3e63807d7e41086d40633d1b6de143a088
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.component.spec.ts
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ForwardVorgangIconComponent } from './forward-vorgang-icon.component';
+
+describe('ForwardVorgangIconComponent', () => {
+  let component: ForwardVorgangIconComponent;
+  let fixture: ComponentFixture<ForwardVorgangIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [ForwardVorgangIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ForwardVorgangIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..983f66161939b2ff51a7133707e323c35543f396
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.component.ts
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { NgClass } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-forward-vorgang-icon',
+  standalone: true,
+  imports: [NgClass],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="twMerge(iconVariants({ size }), 'fill-primary', class)"
+    aria-hidden="true"
+  >
+    <path d="M17.7222 16.4V14L22 18.2L17.7222 22.4V19.94C14.6667 19.94 12.5278 20.9 11 23C11.6111 20 13.4444 17 17.7222 16.4Z" />
+    <path
+      fill-rule="evenodd"
+      clip-rule="evenodd"
+      d="M16.25 11V3.77384H11.2794L6.875 7.93078L6.875 18.408H9V20.1818H6.875C5.83947 20.1818 5 19.3876 5 18.408V7.93078C5 7.4596 5.19815 7.00779 5.55074 6.67501L9.95513 2.51807C10.3066 2.18631 10.7829 2 11.2794 2H16.25C17.2855 2 18.125 2.79417 18.125 3.77384V11H16.25Z"
+    />
+  </svg>`,
+})
+export class ForwardVorgangIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = undefined;
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2fd3fa932eddb7319eb468c0a3e4d2e8c4dbdf4a
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/forward-vorgang-icon/forward-vorgang-icon.stories.ts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { ForwardVorgangIconComponent } from './forward-vorgang-icon.component';
+
+const meta: Meta<ForwardVorgangIconComponent> = {
+  title: 'Icons/Forward Vorgang icon',
+  component: ForwardVorgangIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<ForwardVorgangIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.scss b/alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.component.spec.ts
similarity index 60%
rename from alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.scss
rename to alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.component.spec.ts
index 073c7c4392d2b1dd921d4ac949942297033a68c4..391bb8a99d42df4aeeadb2aec507e2419a765ef5 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.scss
+++ b/alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.component.spec.ts
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
  * Ministerpräsidenten des Landes Schleswig-Holstein
  * Staatskanzlei
@@ -21,14 +21,24 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-:host {
-  display: flex;
-  flex-grow: 1;
-  z-index: 1;
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { OpenLinkIconComponent } from './open-link-icon.component';
 
-  ::ng-deep {
-    a {
-      color: inherit;
-    }
-  }
-}
+describe('OpenLinkIconComponent', () => {
+  let component: OpenLinkIconComponent;
+  let fixture: ComponentFixture<OpenLinkIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [OpenLinkIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(OpenLinkIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e4774466ae21148dff848fd7c66e9803f159f3fb
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.component.ts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import { NgClass } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-open-link-icon',
+  standalone: true,
+  imports: [NgClass],
+  template: `<svg
+    xmlns="http://www.w3.org/2000/svg"
+    viewBox="0 0 24 24"
+    [ngClass]="twMerge(iconVariants({ size }), 'fill-primary', class)"
+    aria-hidden="true"
+  >
+    <path
+      d="M5 21c-.55 0-1.02-.196-1.413-.587A1.926 1.926 0 0 1 3 19V5c0-.55.196-1.02.587-1.413A1.926 1.926 0 0 1 5 3h7v2H5v14h14v-7h2v7c0 .55-.196 1.02-.587 1.413A1.926 1.926 0 0 1 19 21H5Zm4.7-5.3-1.4-1.4L17.6 5H14V3h7v7h-2V6.4l-9.3 9.3Z"
+    />
+  </svg>`,
+})
+export class OpenLinkIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = undefined;
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8941a073fa54c45de732de7cfa2b1870514d85a0
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/open-link-icon/open-link-icon.stories.ts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { OpenLinkIconComponent } from './open-link-icon.component';
+
+const meta: Meta<OpenLinkIconComponent> = {
+  title: 'Icons/Open link icon',
+  component: OpenLinkIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<OpenLinkIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'medium' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e8655275d9a25c7cc96ad3823668079bf2518bf0
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RequestVorgangDeletionIconComponent } from './request-vorgang-deletion-icon.component';
+
+describe('RequestVorgangDeletionIconComponent', () => {
+  let component: RequestVorgangDeletionIconComponent;
+  let fixture: ComponentFixture<RequestVorgangDeletionIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [RequestVorgangDeletionIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(RequestVorgangDeletionIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ca9dd83e0e886b1c28dd535951326e4880db7928
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.component.ts
@@ -0,0 +1,28 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-request-vorgang-deletion-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path d="M11.75 8H13.75V12.15L15.35 10.6L16.75 12L12.75 16L8.75 12L10.15 10.6L11.75 12.15V8Z" />
+    <path
+      d="M7.75 21C7.2 21 6.72917 20.8042 6.3375 20.4125C5.94583 20.0208 5.75 19.55 5.75 19V6H4.75V4H9.75V3H15.75V4H20.75V6H19.75V19C19.75 19.55 19.5542 20.0208 19.1625 20.4125C18.7708 20.8042 18.3 21 17.75 21H7.75ZM17.75 6H7.75V19H17.75V6Z"
+    />
+  </svg>`,
+})
+export class RequestVorgangDeletionIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eed9f6bc607a9bf3483a158f6e89e850ab475181
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/request-vorgang-deletion-icon/request-vorgang-deletion-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { RequestVorgangDeletionIconComponent } from './request-vorgang-deletion-icon.component';
+
+const meta: Meta<RequestVorgangDeletionIconComponent> = {
+  title: 'Icons/Request Vorgang deletion icon',
+  component: RequestVorgangDeletionIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<RequestVorgangDeletionIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/spinner-icon/spinner-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/spinner-icon/spinner-icon.component.ts
index 6d8cc0547aa086099447fbf0b20226050dd8b2df..503f6865258a83c1ce2073c288e47f68b87e99ef 100644
--- a/alfa-client/libs/design-system/src/lib/icons/spinner-icon/spinner-icon.component.ts
+++ b/alfa-client/libs/design-system/src/lib/icons/spinner-icon/spinner-icon.component.ts
@@ -30,7 +30,6 @@ import { IconVariants, iconVariants } from '../iconVariants';
   selector: 'ods-spinner-icon',
   standalone: true,
   imports: [NgClass],
-  styles: [':host {@apply flex}'],
   template: `<svg
       xmlns="http://www.w3.org/2000/svg"
       [ngClass]="iconVariants({ size })"
diff --git a/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fda1f7e237ce8667e4f4194fc58f85384d3bb985
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { UndoIconComponent } from './undo-icon.component';
+
+describe('UndoIconComponent', () => {
+  let component: UndoIconComponent;
+  let fixture: ComponentFixture<UndoIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UndoIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UndoIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7b36f81af4fbc7989233efacfd1c4df124af94dc
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.component.ts
@@ -0,0 +1,27 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-undo-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path
+      d="M13.25 8C10.6 8 8.2 8.99 6.35 10.6L2.75 7V16H11.75L8.13 12.38C9.52 11.22 11.29 10.5 13.25 10.5C16.79 10.5 19.8 12.81 20.85 16L23.22 15.22C21.83 11.03 17.9 8 13.25 8Z"
+    />
+  </svg>`,
+})
+export class UndoIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0d2d78f8148e451628802851ce122c012e99c9b2
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/undo-icon/undo-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { UndoIconComponent } from './undo-icon.component';
+
+const meta: Meta<UndoIconComponent> = {
+  title: 'Icons/Undo icon',
+  component: UndoIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<UndoIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8ac05bee99d59932ae4bbddf8bebe1612085d2f0
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { UndoRequestVorgangDeletionIconComponent } from './undo-request-vorgang-deletion-icon.component';
+
+describe('UndoRequestVorgangDeletionIconComponent', () => {
+  let component: UndoRequestVorgangDeletionIconComponent;
+  let fixture: ComponentFixture<UndoRequestVorgangDeletionIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UndoRequestVorgangDeletionIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UndoRequestVorgangDeletionIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0140ae651fb6c5dd42cbc1370509fae3226bdc7c
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.component.ts
@@ -0,0 +1,27 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-undo-request-vorgang-deletion-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path
+      d="M11.75 16H13.75V11.85L15.35 13.4L16.75 12L12.75 8L8.75 12L10.15 13.4L11.75 11.85V16ZM7.75 21C7.2 21 6.72917 20.8042 6.3375 20.4125C5.94583 20.0208 5.75 19.55 5.75 19V6H4.75V4H9.75V3H15.75V4H20.75V6H19.75V19C19.75 19.55 19.5542 20.0208 19.1625 20.4125C18.7708 20.8042 18.3 21 17.75 21H7.75ZM17.75 6H7.75V19H17.75V6Z"
+    />
+  </svg>`,
+})
+export class UndoRequestVorgangDeletionIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c5f0bd31fa92c4e11ef9286d9d13f2d41663ef26
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/undo-request-vorgang-deletion-icon/undo-request-vorgang-deletion-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { UndoRequestVorgangDeletionIconComponent } from './undo-request-vorgang-deletion-icon.component';
+
+const meta: Meta<UndoRequestVorgangDeletionIconComponent> = {
+  title: 'Icons/Undo request vorgang deletion icon',
+  component: UndoRequestVorgangDeletionIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<UndoRequestVorgangDeletionIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.component.spec.ts b/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d2e3620badccfec4c031b9d6bf8f700cb1e571c0
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { UpdateIconComponent } from './update-icon.component';
+
+describe('UpdateIconComponent', () => {
+  let component: UpdateIconComponent;
+  let fixture: ComponentFixture<UpdateIconComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [UpdateIconComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(UpdateIconComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.component.ts b/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..34e40d8150deb19ab77923d576b6567e87cf2911
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.component.ts
@@ -0,0 +1,27 @@
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { twMerge } from 'tailwind-merge';
+import { iconVariants, IconVariants } from '../iconVariants';
+
+@Component({
+  selector: 'ods-update-icon',
+  standalone: true,
+  imports: [CommonModule],
+  template: `<svg
+    viewBox="0 0 24 24"
+    xmlns="http://www.w3.org/2000/svg"
+    [ngClass]="[twMerge(iconVariants({ size }), 'fill-primary', class)]"
+    aria-hidden="true"
+  >
+    <path
+      d="M21.75 10.12H14.97L17.71 7.3C14.98 4.6 10.56 4.5 7.83 7.2C5.1 9.91 5.1 14.28 7.83 16.99C10.56 19.7 14.98 19.7 17.71 16.99C19.07 15.65 19.75 14.08 19.75 12.1H21.75C21.75 14.08 20.87 16.65 19.11 18.39C15.6 21.87 9.9 21.87 6.39 18.39C2.89 14.92 2.86 9.28 6.37 5.81C9.88 2.34 15.51 2.34 19.02 5.81L21.75 3V10.12ZM13.25 8V12.25L16.75 14.33L16.03 15.54L11.75 13V8H13.25Z"
+    />
+  </svg>`,
+})
+export class UpdateIconComponent {
+  @Input() size: IconVariants['size'] = 'medium';
+  @Input() class: string = '';
+
+  readonly iconVariants = iconVariants;
+  readonly twMerge = twMerge;
+}
diff --git a/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.stories.ts b/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.stories.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7814dc21f79f972ad09ff1aa1c1a93fc3d59ac98
--- /dev/null
+++ b/alfa-client/libs/design-system/src/lib/icons/update-icon/update-icon.stories.ts
@@ -0,0 +1,27 @@
+import type { Meta, StoryObj } from '@storybook/angular';
+
+import { UpdateIconComponent } from './update-icon.component';
+
+const meta: Meta<UpdateIconComponent> = {
+  title: 'Icons/Update icon',
+  component: UpdateIconComponent,
+  excludeStories: /.*Data$/,
+  tags: ['autodocs'],
+};
+
+export default meta;
+type Story = StoryObj<UpdateIconComponent>;
+
+export const Default: Story = {
+  args: { size: 'large' },
+  argTypes: {
+    size: {
+      control: 'select',
+      options: ['small', 'medium', 'large', 'extra-large', 'full'],
+      description: 'Size of icon. Property "full" means 100%',
+      table: {
+        defaultValue: { summary: 'medium' },
+      },
+    },
+  },
+};
diff --git a/alfa-client/libs/design-system/src/lib/link/link.component.ts b/alfa-client/libs/design-system/src/lib/link/link.component.ts
index 3331d0c65b04128f6954a52a2a22b43da50308e2..64830deee7cf6873156013281ec33d7e2a56199e 100644
--- a/alfa-client/libs/design-system/src/lib/link/link.component.ts
+++ b/alfa-client/libs/design-system/src/lib/link/link.component.ts
@@ -11,7 +11,7 @@ import { twMerge } from 'tailwind-merge';
     [href]="url"
     [class]="
       twMerge(
-        'block rounded border-2 border-transparent text-text outline-2 outline-offset-2 outline-focus hover:border-primary-600 focus-visible:border-transparent focus-visible:outline',
+        'block rounded-lg border-2 border-transparent text-text hover:bg-ghost-hover focus-visible:border-focus focus-visible:bg-ghost-hover focus-visible:outline-none dark:hover:bg-neutral-700',
         class
       )
     "
diff --git a/alfa-client/libs/design-system/src/lib/list/list-item/list-item.component.ts b/alfa-client/libs/design-system/src/lib/list/list-item/list-item.component.ts
index 54922cf06c831e54ecadca0558cb487476349a2d..92e203ce5673af16e7b2102a1928c1b5a49eb4b3 100644
--- a/alfa-client/libs/design-system/src/lib/list/list-item/list-item.component.ts
+++ b/alfa-client/libs/design-system/src/lib/list/list-item/list-item.component.ts
@@ -34,8 +34,9 @@ import { RouterLink } from '@angular/router';
       [routerLink]="path"
       data-test-class="list-item-link"
       class="flex flex-col items-start justify-between gap-6 border-primary-600/50 px-6 py-4 hover:bg-background-150 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus lg:flex-row"
-      ><ng-content
-    /></a>
+    >
+      <ng-content />
+    </a>
   </li>`,
   styles: [':host { @apply block w-full }'],
 })
diff --git a/alfa-client/libs/design-system/src/lib/tailwind-preset/root.css b/alfa-client/libs/design-system/src/lib/tailwind-preset/root.css
index 3a5219869889a28d277bb50409e9f7cfeac73063..a3c8f7b01b5e1b8342761bf3190841ef059b5cc8 100644
--- a/alfa-client/libs/design-system/src/lib/tailwind-preset/root.css
+++ b/alfa-client/libs/design-system/src/lib/tailwind-preset/root.css
@@ -19,6 +19,12 @@
   --color-disabled: 206 14% 95%;
   --color-disabled-dark: 208 12% 65%;
 
+  --color-destructive: 360, 71%, 49%, 1;
+  --color-destructive-hover: 360, 71%, 49%, 0.07;
+  --color-destructive-primary-hover: 360, 71%, 49%, 0.9;
+
+  --color-ghost-hover: 212, 80%, 42%, 0.07;
+
   --color-background-secondary: 0 0% 98%;
   --color-mainbg: 0 0% 100%;
   --text: 0 0% 0%;
@@ -54,6 +60,12 @@
   --color-disabled: 206 14% 15%;
   --color-disabled-dark: 208 12% 33%;
 
+  --color-destructive: 360, 71%, 49%, 1;
+  --color-destructive-hover: 360, 71%, 49%, 0.2;
+  --color-destructive-primary-hover: 360, 71%, 49%, 0.9;
+
+  --color-ghost-hover: 43, 96%, 58%, 0.18;
+
   --color-background-secondary: 0 0% 16%;
   --color-mainbg: 0 0% 14%;
   --text: 0 0% 100%;
diff --git a/alfa-client/libs/design-system/src/lib/tailwind-preset/tailwind.config.js b/alfa-client/libs/design-system/src/lib/tailwind-preset/tailwind.config.js
index 7044c674c79ae488f286b93344c8b72a5f956827..cf2abfcb2f32821bcb410f4d9bcd817f2aa2efb0 100644
--- a/alfa-client/libs/design-system/src/lib/tailwind-preset/tailwind.config.js
+++ b/alfa-client/libs/design-system/src/lib/tailwind-preset/tailwind.config.js
@@ -148,6 +148,10 @@ module.exports = {
           dark: 'hsl(var(--color-disabled-dark) / <alpha-value>)',
           DEFAULT: 'hsl(var(--color-disabled) / <alpha-value>)',
         },
+        destructive: 'hsla(var(--color-destructive))',
+        'destructive-primary-hover': 'hsla(var(--color-destructive-primary-hover))',
+        'destructive-hover': 'hsla(var(--color-destructive-hover))',
+        'ghost-hover': 'hsla(var(--color-ghost-hover))',
       },
       backdropBlur: {
         1: '1px',
diff --git a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts
index 1f813a9e5ea79cb5e30111a132dca50be8ebcc2f..f82fe2102cb07bea080f2b61738c783515d58672 100644
--- a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts
+++ b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.component.ts
@@ -29,7 +29,7 @@ import { TooltipPosition } from './tooltip.directive';
   selector: 'ods-tooltip',
   imports: [NgClass],
   template: `<span
-    class="tooltip fixed z-[100] max-w-md animate-fadeIn cursor-default whitespace-pre rounded bg-ozggray-900 px-3 py-2 text-sm text-whitetext before:absolute before:border-l-[0.5rem] before:border-r-[0.5rem] before:border-l-transparent before:border-r-transparent dark:bg-white md:max-w-[calc(90vw)]"
+    class="tooltip fixed z-[100] max-w-md animate-fadeIn cursor-default break-words rounded bg-ozggray-900 px-3 py-2 text-sm text-whitetext before:absolute before:border-l-[0.5rem] before:border-r-[0.5rem] before:border-l-transparent before:border-r-transparent dark:bg-white md:max-w-[calc(90vw)]"
     [ngClass]="class"
     [class.visible]="show"
     [class.invisible]="!show"
diff --git a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts
index ce1f687ce7a0df7411b5d3169f42d9c152f9c88e..ad238fc30e5c06357950f574eae44f518582a75a 100644
--- a/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts
+++ b/alfa-client/libs/design-system/src/lib/tooltip/tooltip.directive.ts
@@ -23,17 +23,7 @@
  */
 import { isEscapeKey, isNotNull } from '@alfa-client/tech-shared';
 import { InteractivityChecker } from '@angular/cdk/a11y';
-import {
-  ComponentRef,
-  Directive,
-  ElementRef,
-  HostListener,
-  inject,
-  Input,
-  OnDestroy,
-  Renderer2,
-  ViewContainerRef,
-} from '@angular/core';
+import { ComponentRef, Directive, ElementRef, HostListener, inject, Input, OnDestroy, Renderer2, ViewContainerRef, } from '@angular/core';
 import { isEmpty, isNull, uniqueId } from 'lodash-es';
 import { TooltipComponent } from './tooltip.component';
 
@@ -41,6 +31,7 @@ export enum TooltipPosition {
   ABOVE = 'above',
   BELOW = 'below',
 }
+
 const OUTLINE_INDENT = 4; // Outline offset (2) + outline width (2)
 type TooltipAriaType = 'aria-describedby' | 'aria-labelledby';
 
@@ -60,6 +51,7 @@ export class TooltipDirective implements OnDestroy {
 
     this.createTooltip(value);
   }
+
   @Input() tooltipPosition: TooltipPosition = TooltipPosition.BELOW;
   @Input() tooltipAriaType: TooltipAriaType = 'aria-describedby';
 
@@ -92,9 +84,7 @@ export class TooltipDirective implements OnDestroy {
   }
 
   @HostListener('mouseleave')
-  @HostListener('window:scroll')
   @HostListener('focusout')
-  @HostListener('window:resize')
   hideTooltip(): void {
     this.hide();
   }
diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.spec.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.spec.ts
index f675f96336086e4fdc7edd5937b502494662830d..34a7bd065f0c85b3ddc80a39d2fbe195e9c33655 100644
--- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.spec.ts
+++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.spec.ts
@@ -43,9 +43,7 @@ describe('ForwardingRepository', () => {
   });
 
   describe('getForwardings', () => {
-    const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([
-      VorgangWithEingangLinkRel.FORWARDING,
-    ]);
+    const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD_BY_EMAIL]);
     const commandList: ForwardingListResource = createForwardingListResource();
 
     beforeEach(() => {
@@ -61,7 +59,7 @@ describe('ForwardingRepository', () => {
     it('should call resourceWrapper', () => {
       repository.getForwardings(vorgang);
 
-      expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.FORWARDING);
+      expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.FORWARD_BY_EMAIL);
     });
 
     it('should return result', () => {
diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.ts
index 33d6a4d7a96721d3ef65c8ee39b018e9bd9a2389..a83ca3536dabe921ff4dc10719dbbdd1f5c74943 100644
--- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.ts
+++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.ts
@@ -21,8 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable } from '@angular/core';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Injectable } from '@angular/core';
 import { ResourceFactory } from '@ngxp/rest';
 import { Observable } from 'rxjs';
 import { ForwardingListResource } from './forwarding.model';
@@ -32,6 +32,6 @@ export class ForwardingRepository {
   constructor(private resourceFactory: ResourceFactory) {}
 
   public getForwardings(vorgang: VorgangWithEingangResource): Observable<ForwardingListResource> {
-    return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.FORWARDING);
+    return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.FORWARD_BY_EMAIL);
   }
 }
diff --git a/alfa-client/libs/forwarding/src/index.ts b/alfa-client/libs/forwarding/src/index.ts
index 504fbb0e7ec702fb29520609ef67645757c8e52b..24d937c3408da87eef49107297ff05faf4ffd709 100644
--- a/alfa-client/libs/forwarding/src/index.ts
+++ b/alfa-client/libs/forwarding/src/index.ts
@@ -21,5 +21,6 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+export * from './lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component';
 export * from './lib/forwarding.module';
 export * from './lib/vorgang-forwarding-container/vorgang-forwarding-container.component';
diff --git a/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.html b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c3a536b79edb8516518911255a4e1d40eeb2448b
--- /dev/null
+++ b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.html
@@ -0,0 +1,16 @@
+@if (vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.FORWARD_BY_OZGCLOUD) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      tooltip="Vorgang weiterleiten"
+      variant="ghost"
+      size="fit"
+      dataTestId="forward-by-ozgcloud-icon-button"
+    >
+      <ods-forward-vorgang-icon icon class="fill-text" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner text="Weiterleiten" variant="outline" dataTestId="forward-by-ozgcloud-button">
+      <ods-forward-vorgang-icon icon />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.spec.ts b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0bdb21fd38ad815027918f1b3e13b7a1818f57d4
--- /dev/null
+++ b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.spec.ts
@@ -0,0 +1,90 @@
+import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { ForwardVorgangIconComponent, TooltipDirective } from '@ods/system';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
+import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
+import { MockComponent, MockDirective } from 'ng-mocks';
+import { ForwardByOzgcloudButtonContainerComponent } from './forward-by-ozgcloud-button-container.component';
+
+describe('ForwardByOzgcloudButtonContainerComponent', () => {
+  let component: ForwardByOzgcloudButtonContainerComponent;
+  let fixture: ComponentFixture<ForwardByOzgcloudButtonContainerComponent>;
+
+  const iconButton: string = getDataTestIdAttributeOf('forward-by-ozgcloud-icon-button');
+  const button: string = getDataTestIdAttributeOf('forward-by-ozgcloud-button');
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [ForwardByOzgcloudButtonContainerComponent],
+      declarations: [
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(ForwardVorgangIconComponent),
+        MockDirective(TooltipDirective),
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ForwardByOzgcloudButtonContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('on existing link', () => {
+    beforeEach(() => {
+      component.vorgangWithEingang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD_BY_OZGCLOUD]);
+    });
+
+    describe('show as icon button', () => {
+      beforeEach(() => {
+        component.showAsIconButton = true;
+        fixture.detectChanges();
+      });
+
+      it('should hide button', () => {
+        notExistsAsHtmlElement(fixture, button);
+      });
+
+      it('should show iconButton', () => {
+        existsAsHtmlElement(fixture, iconButton);
+      });
+    });
+
+    describe('show as button', () => {
+      beforeEach(() => {
+        component.showAsIconButton = false;
+        fixture.detectChanges();
+      });
+
+      it('should hide iconButton', () => {
+        notExistsAsHtmlElement(fixture, iconButton);
+      });
+
+      it('should show button', () => {
+        existsAsHtmlElement(fixture, button);
+      });
+    });
+  });
+
+  describe('on missing link', () => {
+    it('should hide button', () => {
+      component.vorgangWithEingang = createVorgangWithEingangResource();
+
+      fixture.detectChanges();
+
+      notExistsAsHtmlElement(fixture, button);
+    });
+
+    it('should hide icon button', () => {
+      component.vorgangWithEingang = createVorgangWithEingangResource();
+
+      fixture.detectChanges();
+
+      notExistsAsHtmlElement(fixture, iconButton);
+    });
+  });
+});
diff --git a/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.ts b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b00da7ddb3c481ac14502f9091ec29c4b9af2748
--- /dev/null
+++ b/alfa-client/libs/forwarding/src/lib/forward-by-ozgcloud-button-container/forward-by-ozgcloud-button-container.component.ts
@@ -0,0 +1,20 @@
+import { TechSharedModule } from '@alfa-client/tech-shared';
+import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { ForwardVorgangIconComponent, TooltipDirective } from '@ods/system';
+
+@Component({
+  selector: 'alfa-forward-by-ozgcloud-button-container',
+  standalone: true,
+  imports: [CommonModule, TechSharedModule, ButtonWithSpinnerComponent, ForwardVorgangIconComponent, TooltipDirective],
+  templateUrl: './forward-by-ozgcloud-button-container.component.html',
+  styles: [':host {@apply empty:hidden}'],
+})
+export class ForwardByOzgcloudButtonContainerComponent {
+  @Input() vorgangWithEingang: VorgangWithEingangResource;
+  @Input() showAsIconButton: boolean = false;
+
+  public readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel;
+}
diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.ts
index 70077ddb0cbcead2f722eeb25fb3050a44a0c4bb..68fc4c4a960aa2635f161a4b4413da33b7da7a7e 100644
--- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.ts
+++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.ts
@@ -21,16 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable } from '@angular/core';
-import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { CommandResource } from '@alfa-client/command-shared';
 import { ForwardingService } from '@alfa-client/forwarding-shared';
 import { AbstractFormService, StateResource } from '@alfa-client/tech-shared';
 import { VorgangResource } from '@alfa-client/vorgang-shared';
+import { Injectable } from '@angular/core';
+import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { Observable } from 'rxjs';
 
 @Injectable()
-export class VorgangForwardFormService extends AbstractFormService {
+export class VorgangForwardFormService extends AbstractFormService<CommandResource> {
   static readonly FIELD_PATH_PREFIX = 'command.redirectRequest';
 
   static readonly FIELD_EMAIL = 'email';
diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.html b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.html
index 435e66f60107cd9951b54af1ef059b04d7aef2fb..2698ddc7e78cbb2a6b8c6d0a4a6bbd67806ecc85 100644
--- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.html
+++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.html
@@ -23,20 +23,14 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container
-  *ngIf="
-    (vorgang | hasLink: vorgangLinkRel.FORWARD) || (vorgang | hasLink: vorgangLinkRel.FORWARDING)
-  "
->
+<ng-container *ngIf="(vorgang | hasLink: vorgangLinkRel.FORWARD) || (vorgang | hasLink: vorgangLinkRel.FORWARD_BY_EMAIL)">
   <ozgcloud-expansion-panel
     headline="Vorgang weiterleiten"
     data-test-id="forwarding"
     *ngIf="forwardingStateResources$ | async as forwardingStateResources"
   >
     <ozgcloud-spinner [stateResource]="forwardingStateResources">
-      <alfa-vorgang-forwarding-info-list
-        [forwardingList]="forwardingStateResources"
-      ></alfa-vorgang-forwarding-info-list>
+      <alfa-vorgang-forwarding-info-list [forwardingList]="forwardingStateResources"></alfa-vorgang-forwarding-info-list>
     </ozgcloud-spinner>
 
     <alfa-vorgang-forward-formular
diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.spec.ts
index 33d4a94562258a2c0a84d905a09ddb7cccfad35d..25691e2e369a3024d426d9a1e7a4e8976b37d228 100644
--- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.spec.ts
+++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.spec.ts
@@ -21,18 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { UntypedFormBuilder } from '@angular/forms';
 import { ForwardingService } from '@alfa-client/forwarding-shared';
 import { createStateResource, HasLinkPipe } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
 import { ExpansionPanelComponent, SpinnerComponent } from '@alfa-client/ui';
 import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { UntypedFormBuilder } from '@angular/forms';
 import { createCommandResource } from 'libs/command-shared/test/command';
-import {
-  createVorgangForwardRequest,
-  createVorgangWithEingangResource,
-} from 'libs/vorgang-shared/test/vorgang';
+import { createVorgangForwardRequest, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
 import { VorgangForwardFormService } from './vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice';
@@ -127,7 +124,7 @@ describe('VorgangForwardingContainerComponent', () => {
     });
 
     it('should call service get forward commands', () => {
-      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARDING]);
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD_BY_EMAIL]);
       fixture.detectChanges();
 
       component.getForwardings();
@@ -150,9 +147,7 @@ describe('VorgangForwardingContainerComponent', () => {
   describe('forwarding', () => {
     describe('on forwarding link', () => {
       it('should show if exists', () => {
-        component.vorgang = createVorgangWithEingangResource([
-          VorgangWithEingangLinkRel.FORWARDING,
-        ]);
+        component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD_BY_EMAIL]);
         fixture.detectChanges();
 
         const element = fixture.nativeElement.querySelector(forwarding);
diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.ts
index e9aedf34419e9afc0aaf65709857c364ee9caee2..9613957552ae86a387c108ecfa05f71463c8218b 100644
--- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.ts
+++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.ts
@@ -21,11 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input, OnChanges } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { ForwardingListResource, ForwardingService } from '@alfa-client/forwarding-shared';
 import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input, OnChanges } from '@angular/core';
 import { hasLink } from '@ngxp/rest';
 import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel';
 import { Observable, of } from 'rxjs';
@@ -40,12 +40,9 @@ import { VorgangForwardFormService } from './vorgang-forward-formular/vorgang-fo
 export class VorgangForwardingContainerComponent implements OnChanges {
   @Input() public vorgang: VorgangWithEingangResource;
 
-  forwardingStateResources$: Observable<StateResource<ForwardingListResource>> = of(
-    createEmptyStateResource<ForwardingListResource>(),
-  );
-  pendingForwardStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  forwardingStateResources$: Observable<StateResource<ForwardingListResource>> =
+    of(createEmptyStateResource<ForwardingListResource>());
+  pendingForwardStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   readonly linkRel = CommandLinkRel;
   readonly vorgangLinkRel = VorgangWithEingangLinkRel;
@@ -67,7 +64,7 @@ export class VorgangForwardingContainerComponent implements OnChanges {
   }
 
   getForwardings(): void {
-    if (hasLink(this.vorgang, VorgangWithEingangLinkRel.FORWARDING)) {
+    if (hasLink(this.vorgang, VorgangWithEingangLinkRel.FORWARD_BY_EMAIL)) {
       this.forwardingStateResources$ = this.forwardingService.getForwardings(this.vorgang);
     }
   }
@@ -77,8 +74,6 @@ export class VorgangForwardingContainerComponent implements OnChanges {
   }
 
   submit(): void {
-    this.pendingForwardStateResource$ = <Observable<StateResource<CommandResource>>>(
-      this.formService.submit()
-    );
+    this.pendingForwardStateResource$ = <Observable<StateResource<CommandResource>>>this.formService.submit();
   }
 }
diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts
index 63f04c87b86b51af9ac35b2a42cd5b67259391f9..b58d69bba724fa6a291ddc7ed4725955888ad8de 100644
--- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts
+++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts
@@ -21,19 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable } from '@angular/core';
-import {
-  UntypedFormArray,
-  UntypedFormBuilder,
-  UntypedFormControl,
-  UntypedFormGroup,
-} from '@angular/forms';
+import { CommandResource } from '@alfa-client/command-shared';
 import { KommentarService } from '@alfa-client/kommentar-shared';
 import { AbstractFormService, StateResource } from '@alfa-client/tech-shared';
+import { Injectable } from '@angular/core';
+import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { Observable } from 'rxjs';
 
 @Injectable()
-export class KommentarFormService extends AbstractFormService {
+export class KommentarFormService extends AbstractFormService<CommandResource> {
   static readonly TEXT = 'text';
 
   static readonly FIELD_PATH_PREFIX = 'kommentar';
@@ -53,7 +49,7 @@ export class KommentarFormService extends AbstractFormService {
     });
   }
 
-  protected doSubmit(): Observable<StateResource<any>> {
+  protected doSubmit(): Observable<StateResource<CommandResource>> {
     if (this.isPatch()) {
       return this.kommentarService.editKommentar(this.getSourceValue(), this.getFormValue());
     } else {
diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts
index 9777813705006f3f026f47d31d792f6b663a31da..44794b0072f9b661cd22120938e0a045e9b5d330 100644
--- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts
+++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts
@@ -21,14 +21,11 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { KommentarListLinkRel, KommentarService } from '@alfa-client/kommentar-shared';
 import { createStateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import {
-  ExpansionPanelComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
+import { ExpansionPanelComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { cold } from 'jest-marbles';
 import { MockComponent } from 'ng-mocks';
 import { Observable } from 'rxjs';
@@ -77,13 +74,7 @@ describe('KommentarListInVorgangContainerComponent', () => {
     beforeEach(() => {
       kommentarService.isFormularVisible.mockReturnValue(new Observable((o) => o.next(false)));
       kommentarService.getKommentareByVorgang.mockReturnValue(
-        new Observable((o) =>
-          o.next(
-            createStateResource(
-              createKommentarListResource([KommentarListLinkRel.CREATE_KOMMENTAR]),
-            ),
-          ),
-        ),
+        new Observable((o) => o.next(createStateResource(createKommentarListResource([KommentarListLinkRel.CREATE_KOMMENTAR])))),
       );
     });
 
@@ -96,21 +87,15 @@ describe('KommentarListInVorgangContainerComponent', () => {
     it('should call kommentar service getKommentareByVorgang', () => {
       component.ngOnChanges();
 
-      expect(kommentarService.getKommentareByVorgang).toHaveBeenCalledWith(
-        component.vorgangStateResource.resource,
-      );
+      expect(kommentarService.getKommentareByVorgang).toHaveBeenCalledWith(component.vorgangStateResource.resource);
     });
 
     it('should create new Kommentare', () => {
       const canCreateNewKommentar$ = cold('a', { a: true });
       const kommentarListStateResource = createStateResource(createKommentarListResource());
-      const kommentarListStateResource$ = new Observable((observer) =>
-        observer.next(kommentarListStateResource),
-      );
+      const kommentarListStateResource$ = new Observable((observer) => observer.next(kommentarListStateResource));
       kommentarService.getKommentareByVorgang.mockReturnValue(kommentarListStateResource$);
-      kommentarService.canCreateNewKommentar.mockReturnValue(
-        new Observable((observer) => observer.next(true)),
-      );
+      kommentarService.canCreateNewKommentar.mockReturnValue(new Observable((observer) => observer.next(true)));
 
       component.ngOnChanges();
 
@@ -120,13 +105,9 @@ describe('KommentarListInVorgangContainerComponent', () => {
     it('should not create new Kommentare', () => {
       const canCreateNewKommentar$ = cold('a', { a: false });
       const kommentarListStateResource = createStateResource(createKommentarListResource());
-      const kommentarListStateResource$ = new Observable((observer) =>
-        observer.next(kommentarListStateResource),
-      );
+      const kommentarListStateResource$ = new Observable((observer) => observer.next(kommentarListStateResource));
       kommentarService.getKommentareByVorgang.mockReturnValue(kommentarListStateResource$);
-      kommentarService.canCreateNewKommentar.mockReturnValue(
-        new Observable((observer) => observer.next(false)),
-      );
+      kommentarService.canCreateNewKommentar.mockReturnValue(new Observable((observer) => observer.next(false)));
 
       component.ngOnChanges();
 
@@ -134,9 +115,7 @@ describe('KommentarListInVorgangContainerComponent', () => {
     });
 
     it('should call reloadKommentarListOnVorgangReload', () => {
-      const reloadKommentarListOnVorgangReload = jest
-        .spyOn(component, 'reloadKommentarListOnVorgangReload')
-        .mockReturnThis();
+      const reloadKommentarListOnVorgangReload = jest.spyOn(component, 'reloadKommentarListOnVorgangReload').mockReturnThis();
 
       component.ngOnChanges();
 
@@ -157,7 +136,7 @@ describe('KommentarListInVorgangContainerComponent', () => {
 
       component.reloadKommentarListOnVorgangReload();
 
-      expect(kommentarService.setKommentarListReload).toBeCalled();
+      expect(kommentarService.setKommentarListReload).toHaveBeenCalled();
     });
 
     it('should not call kommentarService', () => {
@@ -168,7 +147,7 @@ describe('KommentarListInVorgangContainerComponent', () => {
 
       component.reloadKommentarListOnVorgangReload();
 
-      expect(kommentarService.setKommentarListReload).not.toBeCalled();
+      expect(kommentarService.setKommentarListReload).not.toHaveBeenCalled();
     });
   });
 
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.scss b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.ts b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.ts
index 1b0cade59c61d1431bba83e8967f5eaf0e9c84b3..bb94290b756c5a9f47aa07135a50ba2247313d68 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.ts
+++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.ts
@@ -21,34 +21,25 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
-import { MatDialogRef } from '@angular/material/dialog';
 import { CommandResource } from '@alfa-client/command-shared';
-import {
-  LoeschAnforderungResource,
-  LoeschAnforderungService,
-} from '@alfa-client/loesch-anforderung-shared';
+import { LoeschAnforderungResource, LoeschAnforderungService } from '@alfa-client/loesch-anforderung-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
 import { BasicDialogComponent, BasicDialogData, DialogService } from '@alfa-client/ui';
-import {
-  LoeschAnforderungLinkRel,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { LoeschAnforderungLinkRel, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input } from '@angular/core';
+import { MatDialogRef } from '@angular/material/dialog';
 import { Observable, filter, first, of } from 'rxjs';
 
 @Component({
   selector: 'alfa-endgueltig-loeschen-button-container',
   templateUrl: './endgueltig-loeschen-button-container.component.html',
-  styleUrls: ['./endgueltig-loeschen-button-container.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class EndgueltigLoeschenButtonContainerComponent {
   @Input() vorgang: VorgangWithEingangResource;
   @Input() showAsIconButton: boolean = false;
 
-  commandStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
   loeschAnforderungResource$: Observable<StateResource<LoeschAnforderungResource>>;
 
   readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel;
@@ -66,12 +57,8 @@ export class EndgueltigLoeschenButtonContainerComponent {
     this.loeschAnforderungResource$ = this.loeschAnforderungService.getLoeschAnforderung();
   }
 
-  public openEndgueltigLoeschenDialog(
-    loeschAnforderungResource: StateResource<LoeschAnforderungResource>,
-  ): void {
-    const dialogRef: MatDialogRef<BasicDialogComponent> = this.dialogService.openBasic(
-      this.createBasicDialogConfig(),
-    );
+  public openEndgueltigLoeschenDialog(loeschAnforderungResource: StateResource<LoeschAnforderungResource>): void {
+    const dialogRef: MatDialogRef<BasicDialogComponent> = this.dialogService.openBasic(this.createBasicDialogConfig());
 
     dialogRef
       .afterClosed()
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.html b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.html
index d02765b7ba2a514cbe791390a0a8fe753a0c47b2..bf476f537b1107285627ef7d450f2a6ad8b3a57f 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.html
+++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.html
@@ -23,20 +23,23 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-stroked-button-with-spinner
-  *ngIf="!showAsIconButton"
-  data-test-id="endgueltig-loeschen-button"
-  text="Endgültig löschen"
-  svgIcon="delete_finally"
-  (clickEmitter)="endgueltigLoeschen.emit()"
->
-</ozgcloud-stroked-button-with-spinner>
-
-<ozgcloud-icon-button-with-spinner
-  *ngIf="showAsIconButton"
-  data-test-id="endgueltig-loeschen-icon-button"
-  toolTip="Endgültig löschen"
-  svgIcon="delete_finally"
-  (clickEmitter)="endgueltigLoeschen.emit()"
->
-</ozgcloud-icon-button-with-spinner>
+@if (showAsIconButton) {
+  <ods-button-with-spinner
+    data-test-id="endgueltig-loeschen-icon-button"
+    tooltip="Endgültig löschen"
+    variant="ghost"
+    size="fit"
+    (clickEmitter)="endgueltigLoeschen.emit()"
+  >
+    <ods-delete-vorgang-finally-icon icon class="fill-text" />
+  </ods-button-with-spinner>
+} @else {
+  <ods-button-with-spinner
+    data-test-id="endgueltig-loeschen-button"
+    text="Endgültig löschen"
+    variant="outline"
+    (clickEmitter)="endgueltigLoeschen.emit()"
+  >
+    <ods-delete-vorgang-finally-icon icon />
+  </ods-button-with-spinner>
+}
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.spec.ts
index 783c0b0f700f25abc8cc525763425d877476d5f1..66d46e2f07886affa2ff4603762c800b9f04798c 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.spec.ts
+++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.spec.ts
@@ -21,12 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { DeleteVorgangFinallyIconComponent } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { EndgueltigLoeschenButtonComponent } from './endgueltig-loeschen-button.component';
@@ -42,8 +40,8 @@ describe('EndgueltigLoeschenButtonComponent', () => {
     await TestBed.configureTestingModule({
       declarations: [
         EndgueltigLoeschenButtonComponent,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(DeleteVorgangFinallyIconComponent),
       ],
     }).compileComponents();
 
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.scss b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.ts
index 8d60d118a2611ca1588d07e4574ffe2429fcfb85..104b574f16e4f3efc873dcc3fd37633a2139a193 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.ts
+++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.ts
@@ -21,7 +21,6 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import {
   LoeschAnforderungLinkRel,
@@ -29,34 +28,31 @@ import {
   LoeschAnforderungService,
 } from '@alfa-client/loesch-anforderung-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
+import { Component, Input } from '@angular/core';
 import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'alfa-loesch-anforderung-zuruecknehmen-button-container',
   templateUrl: './loesch-anforderung-zuruecknehmen-button-container.component.html',
-  styleUrls: ['./loesch-anforderung-zuruecknehmen-button-container.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class LoeschAnforderungZuruecknehmenButtonContainerComponent {
   @Input() showAsIconButton: boolean = false;
 
   loeschAnforderungStateResource$: Observable<StateResource<LoeschAnforderungResource>>;
-  loeschAnforderungZuruecknehmenCommand$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  loeschAnforderungZuruecknehmenCommand$: Observable<StateResource<CommandResource>> =
+    of(createEmptyStateResource<CommandResource>());
 
   readonly loeschAnforderungLinkRel = LoeschAnforderungLinkRel;
 
   constructor(private loeschAnforderungService: LoeschAnforderungService) {}
 
   ngOnInit(): void {
-    this.loeschAnforderungZuruecknehmenCommand$ =
-      this.loeschAnforderungService.getLoschAnforderungZuruecknehmenCommand();
+    this.loeschAnforderungZuruecknehmenCommand$ = this.loeschAnforderungService.getLoschAnforderungZuruecknehmenCommand();
     this.loeschAnforderungStateResource$ = this.loeschAnforderungService.getLoeschAnforderung();
   }
 
-  public loeschAnforderungZuruecknehmen(
-    loeschAnforderungResource: StateResource<LoeschAnforderungResource>,
-  ): void {
+  public loeschAnforderungZuruecknehmen(loeschAnforderungResource: StateResource<LoeschAnforderungResource>): void {
     this.loeschAnforderungService.zuruecknehmen(loeschAnforderungResource.resource);
   }
 }
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.html b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.html
index 9b9a716c4e326aa7b844ea2b8cb4abfa68e832cd..3aee95356bb52e42320e94e2dab3b1ec1c5d9aec 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.html
+++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.html
@@ -23,22 +23,25 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-stroked-button-with-spinner
-  *ngIf="!showAsIconButton"
-  data-test-id="loesch-anforderung-zuruecknehmen-button"
-  text="Löschanforderung zurücknehmen"
-  svgIcon="undo_request_deletion"
-  [stateResource]="loeschAnforderungZuruecknehmenCommand"
-  (clickEmitter)="loeschAnforderungZuruecknehmen.emit()"
->
-</ozgcloud-stroked-button-with-spinner>
-
-<ozgcloud-icon-button-with-spinner
-  *ngIf="showAsIconButton"
-  data-test-id="loesch-anforderung-zuruecknehmen-icon-button"
-  svgIcon="undo_request_deletion"
-  toolTip="Löschanforderung zurücknehmen"
-  [stateResource]="loeschAnforderungZuruecknehmenCommand"
-  (clickEmitter)="loeschAnforderungZuruecknehmen.emit()"
->
-</ozgcloud-icon-button-with-spinner>
+@if (showAsIconButton) {
+  <ods-button-with-spinner
+    [stateResource]="loeschAnforderungZuruecknehmenCommand"
+    data-test-id="loesch-anforderung-zuruecknehmen-icon-button"
+    tooltip="Löschanforderung zurücknehmen"
+    variant="ghost"
+    size="fit"
+    (clickEmitter)="loeschAnforderungZuruecknehmen.emit()"
+  >
+    <ods-undo-request-vorgang-deletion-icon icon class="fill-text" />
+  </ods-button-with-spinner>
+} @else {
+  <ods-button-with-spinner
+    [stateResource]="loeschAnforderungZuruecknehmenCommand"
+    data-test-id="loesch-anforderung-zuruecknehmen-button"
+    text="Löschanforderung zurücknehmen"
+    variant="outline"
+    (clickEmitter)="loeschAnforderungZuruecknehmen.emit()"
+  >
+    <ods-undo-request-vorgang-deletion-icon icon />
+  </ods-button-with-spinner>
+}
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.spec.ts
index 5d009efa5c227b3c43e297f4064ba7bb74066773..f51d85f10159a0572566a4fd917ebc45f36d66f1 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.spec.ts
+++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.spec.ts
@@ -21,12 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { UndoRequestVorgangDeletionIconComponent } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { LoeschAnforderungZuruecknehmenButtonComponent } from './loesch-anforderung-zuruecknehmen-button.component';
@@ -35,19 +33,15 @@ describe('LoeschAnforderungZuruecknehmenButtonComponent', () => {
   let component: LoeschAnforderungZuruecknehmenButtonComponent;
   let fixture: ComponentFixture<LoeschAnforderungZuruecknehmenButtonComponent>;
 
-  const loeschenAnfordernZuruecknehmenButton: string = getDataTestIdOf(
-    'loesch-anforderung-zuruecknehmen-button',
-  );
-  const loeschenAnfordernZuruecknehmenIconButton: string = getDataTestIdOf(
-    'loesch-anforderung-zuruecknehmen-icon-button',
-  );
+  const loeschenAnfordernZuruecknehmenButton: string = getDataTestIdOf('loesch-anforderung-zuruecknehmen-button');
+  const loeschenAnfordernZuruecknehmenIconButton: string = getDataTestIdOf('loesch-anforderung-zuruecknehmen-icon-button');
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [
         LoeschAnforderungZuruecknehmenButtonComponent,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(UndoRequestVorgangDeletionIconComponent),
       ],
     }).compileComponents();
 
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts
index ee7952fbf39cd37ebd04b22d60660cb53b769aad..4841c7b2b27decf170b93076d58369f9aa9d4a58 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts
+++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts
@@ -21,18 +21,25 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
 import { LoeschAnforderungSharedModule } from '@alfa-client/loesch-anforderung-shared';
 import { TechSharedModule } from '@alfa-client/tech-shared';
 import { UiModule } from '@alfa-client/ui';
 import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import {
+  DeleteVorgangFinallyIconComponent,
+  RequestVorgangDeletionIconComponent,
+  TooltipDirective,
+  UndoRequestVorgangDeletionIconComponent,
+} from '@ods/system';
 import { EndgueltigLoeschenButtonContainerComponent } from './endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component';
 import { EndgueltigLoeschenButtonComponent } from './endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component';
+import { LoeschAnforderungZuruecknehmenButtonContainerComponent } from './loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component';
+import { LoeschAnforderungZuruecknehmenButtonComponent } from './loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component';
 import { LoeschenAnfordernButtonContainerComponent } from './loeschen-anfordern-button-container/loeschen-anfordern-button-container.component';
 import { LoeschenAnfordernButtonComponent } from './loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component';
-import { LoeschAnforderungZuruecknehmenButtonComponent } from './loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component';
-import { LoeschAnforderungZuruecknehmenButtonContainerComponent } from './loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component';
 
 @NgModule({
   imports: [
@@ -41,6 +48,11 @@ import { LoeschAnforderungZuruecknehmenButtonContainerComponent } from './loesch
     TechSharedModule,
     UiModule,
     VorgangSharedModule,
+    RequestVorgangDeletionIconComponent,
+    ButtonWithSpinnerComponent,
+    DeleteVorgangFinallyIconComponent,
+    UndoRequestVorgangDeletionIconComponent,
+    TooltipDirective,
   ],
   declarations: [
     LoeschenAnfordernButtonContainerComponent,
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.html b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.html
index 81b61300a526e2b76858b8a20151a16f75bbc7d3..4a7cc9cb40b1f9ed650cb7c5e27723ccb30edbef 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.html
+++ b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.html
@@ -23,22 +23,25 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-stroked-button-with-spinner
-  *ngIf="!showAsIconButton"
-  data-test-id="loeschen-anfordern-button"
-  text="Löschen anfordern"
-  svgIcon="request_deletion"
-  [stateResource]="loeschenAnfordernCommand"
-  (clickEmitter)="loeschenAnfordern.emit()"
->
-</ozgcloud-stroked-button-with-spinner>
-
-<ozgcloud-icon-button-with-spinner
-  *ngIf="showAsIconButton"
-  data-test-id="loeschen-anfordern-icon-button"
-  svgIcon="request_deletion"
-  toolTip="Löschen anfordern"
-  [stateResource]="loeschenAnfordernCommand"
-  (clickEmitter)="loeschenAnfordern.emit()"
->
-</ozgcloud-icon-button-with-spinner>
+@if (showAsIconButton) {
+  <ods-button-with-spinner
+    [stateResource]="loeschenAnfordernCommand"
+    data-test-id="loeschen-anfordern-icon-button"
+    tooltip="Löschen anfordern"
+    variant="ghost"
+    size="fit"
+    (clickEmitter)="loeschenAnfordern.emit()"
+  >
+    <ods-request-vorgang-deletion-icon icon class="fill-text" />
+  </ods-button-with-spinner>
+} @else {
+  <ods-button-with-spinner
+    [stateResource]="loeschenAnfordernCommand"
+    data-test-id="loeschen-anfordern-button"
+    text="Löschen anfordern"
+    variant="outline"
+    (clickEmitter)="loeschenAnfordern.emit()"
+  >
+    <ods-request-vorgang-deletion-icon icon />
+  </ods-button-with-spinner>
+}
diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.spec.ts
index dbf4ba9cad23c72918d3cf040e38054f3c81d2a2..f859031bafc62e2db38e95d53cbfd3c6b2a3634a 100644
--- a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.spec.ts
+++ b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.spec.ts
@@ -21,12 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { RequestVorgangDeletionIconComponent } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { LoeschenAnfordernButtonComponent } from './loeschen-anfordern-button.component';
@@ -42,8 +40,8 @@ describe('LoeschenAnfordernButtonComponent', () => {
     await TestBed.configureTestingModule({
       declarations: [
         LoeschenAnfordernButtonComponent,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(RequestVorgangDeletionIconComponent),
       ],
     }).compileComponents();
 
diff --git a/alfa-client/libs/navigation-shared/test/navigation-test-factory.ts b/alfa-client/libs/navigation-shared/test/navigation-test-factory.ts
index 982c6bc6262047890f5d65c97eef19357a672381..11aba592c38bc7933094e48f45b86ff6841565bc 100644
--- a/alfa-client/libs/navigation-shared/test/navigation-test-factory.ts
+++ b/alfa-client/libs/navigation-shared/test/navigation-test-factory.ts
@@ -21,8 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ParamMap, UrlSegment } from '@angular/router';
+import { faker } from '@faker-js/faker/.';
 import { RouteData } from '../src/lib/+state/navigation.models';
 
 export function createRouteData(): RouteData {
   return { queryParameter: {}, urlSegments: [] };
 }
+
+export function createUrlSegment(): UrlSegment {
+  return {
+    path: faker.lorem.word(),
+    parameterMap: <ParamMap>{},
+    parameters: {},
+  };
+}
diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.html
index 22b79691af9cafb120a6d127f2255a8a168402a7..440eb0b7fee2d2fbf322f3c90295e21e83c7f902 100644
--- a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.html
+++ b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.html
@@ -23,41 +23,41 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container
-  *ngIf="
-    postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL
-  "
->
+@if (postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL) {
   <!-- TODO Aufteilen in 3 einzelne Komponenten -->
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton && text && !toolTip"
-    data-test-id="create-mail-button-with-text"
-    [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE"
-    class="create-button"
-    [text]="text"
-    icon="add"
-    (clickEmitter)="openPostfachNachrichtenDialog.emit()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
-
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton && !text && toolTip"
-    data-test-id="create-mail-button-without-text"
-    [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE"
-    class="create-button"
-    [toolTip]="toolTip"
-    icon="add"
-    (clickEmitter)="openPostfachNachrichtenDialog.emit()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
-
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="send-mail-icon-button"
-    [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE"
-    icon="mail_outline"
-    toolTip="Neue Nachricht erstellen"
-    (clickEmitter)="openPostfachNachrichtenDialog.emit()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+  @if (showAsIconButton) {
+    <ods-button
+      dataTestId="send-mail-icon-button"
+      [isLoading]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE"
+      tooltip="Neue Nachricht erstellen"
+      variant="ghost"
+      size="fit"
+      (clickEmitter)="openPostfachNachrichtenDialog.emit()"
+    >
+      <ods-mailbox-icon icon />
+    </ods-button>
+  }
+  @if (!showAsIconButton && text && !toolTip) {
+    <ods-button
+      dataTestId="create-mail-button-with-text"
+      [isLoading]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE"
+      [text]="text"
+      variant="outline"
+      (clickEmitter)="openPostfachNachrichtenDialog.emit()"
+    >
+      <ods-plus-icon icon />
+    </ods-button>
+  }
+  @if (!showAsIconButton && !text && toolTip) {
+    <ods-button
+      dataTestId="create-mail-button-without-text"
+      [isLoading]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE"
+      [tooltip]="toolTip"
+      variant="ghost"
+      size="fit"
+      (clickEmitter)="openPostfachNachrichtenDialog.emit()"
+    >
+      <ods-plus-icon icon />
+    </ods-button>
+  }
+}
diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.spec.ts
index 3fbf0c1e1144fd48acf31fa8f56e1c3846ff1d64..10a405d1058f6fb7f5321e823b602614b294c5e3 100644
--- a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.spec.ts
+++ b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.spec.ts
@@ -21,35 +21,34 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { faker } from '@faker-js/faker';
 import { PostfachMailListLinkRel } from '@alfa-client/postfach-shared';
 import { EMPTY_STRING, HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { faker } from '@faker-js/faker';
+import { ButtonComponent, MailboxIconComponent, PlusIconComponent, TooltipDirective } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
 import { createPostfachMailListResource } from 'libs/postfach-shared/test/postfach';
-import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
-import { MockComponent } from 'ng-mocks';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
+import { MockComponent, MockDirective } from 'ng-mocks';
 import { PostfachMailButtonComponent } from './postfach-mail-button.component';
 
 describe('PostfachMailButtonComponent', () => {
   let component: PostfachMailButtonComponent;
   let fixture: ComponentFixture<PostfachMailButtonComponent>;
 
-  const sendMailButtonWithText: string = getDataTestIdOf('create-mail-button-with-text');
-  const sendMailButtonWithoutText: string = getDataTestIdOf('create-mail-button-without-text');
-  const sendMailIconButton: string = getDataTestIdOf('send-mail-icon-button');
+  const sendMailButtonWithText: string = getDataTestIdAttributeOf('create-mail-button-with-text');
+  const sendMailButtonWithoutText: string = getDataTestIdAttributeOf('create-mail-button-without-text');
+  const sendMailIconButton: string = getDataTestIdAttributeOf('send-mail-icon-button');
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [
         PostfachMailButtonComponent,
         HasLinkPipe,
-        MockComponent(IconButtonWithSpinnerComponent),
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
+        MockComponent(ButtonComponent),
+        MockComponent(PlusIconComponent),
+        MockComponent(MailboxIconComponent),
+        MockDirective(TooltipDirective),
       ],
     }).compileComponents();
   });
@@ -77,9 +76,7 @@ describe('PostfachMailButtonComponent', () => {
       });
 
       it('should be hidden', () => {
-        component.postfachMailListStateResource = createStateResource(
-          createPostfachMailListResource(),
-        );
+        component.postfachMailListStateResource = createStateResource(createPostfachMailListResource());
 
         fixture.detectChanges();
         const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithText);
@@ -108,9 +105,7 @@ describe('PostfachMailButtonComponent', () => {
       });
 
       it('should be hidden', () => {
-        component.postfachMailListStateResource = createStateResource(
-          createPostfachMailListResource(),
-        );
+        component.postfachMailListStateResource = createStateResource(createPostfachMailListResource());
 
         fixture.detectChanges();
         const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithoutText);
@@ -139,9 +134,7 @@ describe('PostfachMailButtonComponent', () => {
     });
 
     it('should be hidden', () => {
-      component.postfachMailListStateResource = createStateResource(
-        createPostfachMailListResource(),
-      );
+      component.postfachMailListStateResource = createStateResource(createPostfachMailListResource());
 
       fixture.detectChanges();
       const buttonElement = fixture.nativeElement.querySelector(sendMailIconButton);
diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.ts
index 36899806713269d271c8192ec31b836e03cb97e8..f5297ca0367403d086510dd77c9e9b0a8f6ed4fc 100644
--- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.ts
+++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.ts
@@ -25,17 +25,12 @@ import { CommandResource } from '@alfa-client/command-shared';
 import { PostfachService, PostfachSettings } from '@alfa-client/postfach-shared';
 import { AbstractFormService, StateResource } from '@alfa-client/tech-shared';
 import { Injectable } from '@angular/core';
-import {
-  UntypedFormArray,
-  UntypedFormBuilder,
-  UntypedFormControl,
-  UntypedFormGroup,
-} from '@angular/forms';
+import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { ReplyOption } from 'libs/postfach-shared/src/lib/postfach.model';
 import { Observable, first } from 'rxjs';
 
 @Injectable()
-export class PostfachMailFormservice extends AbstractFormService {
+export class PostfachMailFormservice extends AbstractFormService<CommandResource> {
   static readonly FIELD_PATH_PREFIX = 'command.body';
 
   static readonly FIELD_SUBJECT = 'subject';
@@ -70,9 +65,7 @@ export class PostfachMailFormservice extends AbstractFormService {
   }
 
   private patchMailBodyWithSignaturAndNewline(signatur: string) {
-    this.form
-      .get(PostfachMailFormservice.FIELD_MAIL_BODY)
-      .setValue(this.addNewlineAtBeginning(signatur));
+    this.form.get(PostfachMailFormservice.FIELD_MAIL_BODY).setValue(this.addNewlineAtBeginning(signatur));
   }
 
   private addNewlineAtBeginning(value: string): string {
diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts
index 28f1fb5afaa51040ea3792acb1dcf4f0a0f408fc..f2b47f34a70349440a1b12df07830044472fc724 100644
--- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts
+++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts
@@ -21,23 +21,21 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { PostfachService } from '@alfa-client/postfach-shared';
+import { createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { PostfachMailListContainerComponent } from './postfach-mail-list-container.component';
 import { PostfachMailListComponent } from './postfach-mail-list/postfach-mail-list.component';
-import { createStateResource, StateResource } from '@alfa-client/tech-shared';
 
 describe('PostfachMailListContainerComponent', () => {
   let component: PostfachMailListContainerComponent;
   let fixture: ComponentFixture<PostfachMailListContainerComponent>;
 
-  const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(
-    createVorgangWithEingangResource(),
-  );
+  const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(createVorgangWithEingangResource());
 
   const postfachService = mock(PostfachService);
 
@@ -68,9 +66,7 @@ describe('PostfachMailListContainerComponent', () => {
     it('should call postfach service', () => {
       component.ngOnChanges();
 
-      expect(postfachService.getPostfachMailListByGivenVorgang).toHaveBeenCalledWith(
-        vorgangStateResource.resource,
-      );
+      expect(postfachService.getPostfachMailListByGivenVorgang).toHaveBeenCalledWith(vorgangStateResource.resource);
     });
 
     it('should call reloadPostfachMailListOnVorgangReload', () => {
@@ -97,7 +93,7 @@ describe('PostfachMailListContainerComponent', () => {
 
       component.reloadPostfachMailListOnVorgangReload();
 
-      expect(postfachService.setPostfachMailOnReload).toBeCalled();
+      expect(postfachService.setPostfachMailOnReload).toHaveBeenCalled();
     });
 
     it('should not call postfachService', () => {
@@ -108,7 +104,7 @@ describe('PostfachMailListContainerComponent', () => {
 
       component.reloadPostfachMailListOnVorgangReload();
 
-      expect(postfachService.setPostfachMailOnReload).not.toBeCalled();
+      expect(postfachService.setPostfachMailOnReload).not.toHaveBeenCalled();
     });
   });
 });
diff --git a/alfa-client/libs/postfach/src/lib/postfach.module.ts b/alfa-client/libs/postfach/src/lib/postfach.module.ts
index 59217f49b5e1d331267a8e1b785381298c65ed8c..e206c35d6c8efaad6336bf8f3740e1f075f5ada7 100644
--- a/alfa-client/libs/postfach/src/lib/postfach.module.ts
+++ b/alfa-client/libs/postfach/src/lib/postfach.module.ts
@@ -29,6 +29,7 @@ import { VorgangSharedUiModule } from '@alfa-client/vorgang-shared-ui';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
+import { ButtonComponent, MailboxIconComponent, PlusIconComponent, TooltipDirective } from '@ods/system';
 import { PostfachMailButtonContainerComponent } from './postfach-mail-button-container/postfach-mail-button-container.component';
 import { PostfachMailButtonComponent } from './postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component';
 import { PostfachMailFormComponent } from './postfach-mail-form/postfach-mail-form.component';
@@ -67,6 +68,10 @@ const routes: Routes = [
     UserProfileModule,
     VorgangSharedUiModule,
     BinaryFileModule,
+    ButtonComponent,
+    PlusIconComponent,
+    MailboxIconComponent,
+    TooltipDirective,
   ],
   declarations: [
     PostfachMailListContainerComponent,
@@ -90,11 +95,7 @@ const routes: Routes = [
     PostfachNachrichtAttachmentContainerComponent,
     PostfachNachrichtReplyEditorContainerComponent,
   ],
-  exports: [
-    PostfachMailListContainerComponent,
-    PostfachMailButtonContainerComponent,
-    PostfachMailFormComponent,
-  ],
+  exports: [PostfachMailListContainerComponent, PostfachMailButtonContainerComponent, PostfachMailFormComponent],
   providers: [
     {
       provide: ON_PAGE,
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
index 5b331dc5ef8056bb702847a8ec0f2c1c41800254..7a045fa7514ae98cf24c58209a709551fb0def98 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
@@ -285,7 +285,7 @@ describe('ResourceService', () => {
     it('should call isLoadingRequired', () => {
       service.shouldLoadResource(stateResource, configResource);
 
-      expect(isLoadingRequiredSpy).toBeCalledWith(stateResource);
+      expect(isLoadingRequiredSpy).toHaveBeenCalledWith(stateResource);
     });
 
     it('should return false if configresource exists but loading is NOT required', () => {
diff --git a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
index fd288f94912e740993b12cc49e231fac26e4b8a1..47119c7a1b2aba5e369af100593d58569dee002a 100644
--- a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts
@@ -40,7 +40,7 @@ import { AbstractFormService } from './formservice.abstract';
 import * as ValidationUtil from '../validation/tech.validation.util';
 
 describe('AbstractFormService', () => {
-  let formService: AbstractFormService;
+  let formService: AbstractFormService<Resource>;
 
   beforeEach(() => {
     formService = new TestFormService(new UntypedFormBuilder());
@@ -52,7 +52,7 @@ describe('AbstractFormService', () => {
 
   describe('submit', () => {
     describe('with ProblemDetail', () => {
-      const stateResourceWithError: StateResource<ProblemDetail> = createErrorStateResource(createProblemDetail());
+      const stateResourceWithError: StateResource<Resource> = createErrorStateResource(createProblemDetail());
 
       beforeEach(() => {
         TestFormService.SUBMIT_OBSERVABLE = () => of(stateResourceWithError);
@@ -182,11 +182,11 @@ describe('AbstractFormService', () => {
   });
 });
 
-class TestFormService extends AbstractFormService {
+class TestFormService extends AbstractFormService<Resource> {
   public static readonly FIELD: string = 'attribute';
   public static readonly PATH_PREFIX: string = 'path-prefix';
 
-  public static SUBMIT_OBSERVABLE = () => of(createEmptyStateResource());
+  public static SUBMIT_OBSERVABLE = () => of(createEmptyStateResource<Resource>());
 
   constructor(formBuilder: UntypedFormBuilder) {
     super(formBuilder);
@@ -198,7 +198,7 @@ class TestFormService extends AbstractFormService {
     });
   }
 
-  protected doSubmit(): Observable<StateResource<any>> {
+  protected doSubmit(): Observable<StateResource<Resource>> {
     return TestFormService.SUBMIT_OBSERVABLE();
   }
 
diff --git a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts
index 59f82aaf5ade160fccaaebb794f117926b91e148..1ab7589b7ebfdcdfac37b2ce9e11f29f263c2c04 100644
--- a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts
+++ b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts
@@ -21,9 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
-
 import { Injectable } from '@angular/core';
+import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 import { Resource } from '@ngxp/rest';
 import { isNil } from 'lodash-es';
 import { identity, Observable, OperatorFunction } from 'rxjs';
@@ -34,7 +33,7 @@ import { isNotUndefined } from '../tech.util';
 import { setInvalidParamValidationError } from '../validation/tech.validation.util';
 
 @Injectable()
-export abstract class AbstractFormService<T = Resource> {
+export abstract class AbstractFormService<T extends Resource> {
   form: UntypedFormGroup;
   pathPrefix: string;
   source: any;
diff --git a/alfa-client/libs/test-utils/src/lib/jest.helper.ts b/alfa-client/libs/test-utils/src/lib/jest.helper.ts
index 1f05a4791cef9e691a60f6fa2287212357e3d909..60df8592afa840fd2f06b5f967e8f5cb295a9a2c 100644
--- a/alfa-client/libs/test-utils/src/lib/jest.helper.ts
+++ b/alfa-client/libs/test-utils/src/lib/jest.helper.ts
@@ -23,7 +23,8 @@
  */
 import { ComponentFixture } from '@angular/core/testing';
 import { expect } from '@jest/globals';
-import { getElementFromFixture } from './helper';
+import { TooltipDirective } from '@ods/system';
+import { getDebugElementFromFixtureByCss, getElementFromFixture } from './helper';
 
 export function notExistsAsHtmlElement(fixture: ComponentFixture<any>, domElement: string): void {
   expect(getElementFromFixture(fixture, domElement)).not.toBeInstanceOf(HTMLElement);
@@ -32,3 +33,8 @@ export function notExistsAsHtmlElement(fixture: ComponentFixture<any>, domElemen
 export function existsAsHtmlElement(fixture: ComponentFixture<any>, domElement: string): void {
   expect(getElementFromFixture(fixture, domElement)).toBeInstanceOf(HTMLElement);
 }
+
+export function tooltipExistsWithText(fixture: ComponentFixture<any>, domElement: string, tooltipText: string) {
+  const tooltipInstance = getDebugElementFromFixtureByCss(fixture, domElement).injector.get(TooltipDirective);
+  expect(tooltipInstance.componentRef.instance.text).toBe(tooltipText);
+}
diff --git a/alfa-client/libs/test-utils/src/lib/mocking.ts b/alfa-client/libs/test-utils/src/lib/mocking.ts
index 9ca211f02b1142821fcc4ac333217734de8ee652..a5e3137a17d3fed7c81cd72e350599195cd079f7 100644
--- a/alfa-client/libs/test-utils/src/lib/mocking.ts
+++ b/alfa-client/libs/test-utils/src/lib/mocking.ts
@@ -43,3 +43,7 @@ export function useFromMock<T>(mockToUse: Mock<T>): T {
 export function mockClass(clazz: any): Mock<any> {
   return clazz as jest.Mocked<typeof clazz>; //NOSONAR
 }
+
+export function createSpy(clazz: any, functionName: string) {
+  return jest.spyOn(clazz.prototype, functionName);
+}
diff --git a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.html b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.html
index 29c6b91fcdefa4629cae62422ee8b56fe62346b2..24868baff476b7d90f3eb7e44a5133ac4faf59d2 100644
--- a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.html
@@ -23,13 +23,8 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<a
-  [routerLink]="linkTo"
-  mat-icon-button
-  data-test-id="back-button"
-  class="back-button"
-  [tooltip]="label"
-  tooltipAriaType="aria-labelledby"
->
-  <mat-icon>arrow_back</mat-icon>
+<a [routerLink]="linkTo" data-test-id="back-button" [tooltip]="label" tooltipAriaType="aria-labelledby" tabindex="-1">
+  <ods-button variant="ghost" size="fit">
+    <ods-arrow-back-icon icon class="fill-text" />
+  </ods-button>
 </a>
diff --git a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.spec.ts
index 9ca87b6fea4263137d68e5451ad05639cff3666d..1e440ea225b27baa66c63d3d62642d543001068b 100644
--- a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.spec.ts
@@ -23,12 +23,11 @@
  */
 import { getElementFromFixture } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatIcon } from '@angular/material/icon';
 import { RouterTestingModule } from '@angular/router/testing';
 import { faker } from '@faker-js/faker';
-import { TooltipDirective } from '@ods/system';
+import { ArrowBackIconComponent, ButtonComponent, TooltipDirective } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
-import { MockDirective } from 'ng-mocks';
+import { MockComponent, MockDirective } from 'ng-mocks';
 import { BackButtonComponent } from './back-button.component';
 
 describe('BackButtonComponent', () => {
@@ -41,8 +40,13 @@ describe('BackButtonComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [BackButtonComponent, MockDirective(TooltipDirective)],
-      imports: [MatIcon, RouterTestingModule],
+      declarations: [
+        BackButtonComponent,
+        MockComponent(ButtonComponent),
+        MockComponent(ArrowBackIconComponent),
+        MockDirective(TooltipDirective),
+      ],
+      imports: [RouterTestingModule],
     }).compileComponents();
 
     fixture = TestBed.createComponent(BackButtonComponent);
diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts
index e194369bd484ef328aee42181528720d510a38b6..e2000c8388d7734d74f703d0748d531580e7454d 100644
--- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts
+++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { NgControl, ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
 import { MatFormFieldModule } from '@angular/material/form-field';
 import { MatInputModule } from '@angular/material/input';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { MockComponent } from 'ng-mocks';
 import { ValidationErrorComponent } from '../../validation-error/validation-error.component';
 import { TextEditorComponent } from './text-editor.component';
@@ -39,11 +39,7 @@ describe('TextEditorComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
-        TextEditorComponent,
-        ConvertForDataTestPipe,
-        MockComponent(ValidationErrorComponent),
-      ],
+      declarations: [TextEditorComponent, ConvertForDataTestPipe, MockComponent(ValidationErrorComponent)],
       imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule],
       providers: [
         {
@@ -81,7 +77,7 @@ describe('TextEditorComponent', () => {
 
       component.onClear();
 
-      expect(component.writeValue).toBeCalledWith(null);
+      expect(component.writeValue).toHaveBeenCalledWith(null);
     });
   });
 
diff --git a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.html b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.html
index 39ef61cb6485f2d1a8704f729e75f4c13b57fa8d..a23a433b033a3c339ed7d2049cc4a7222a998600 100644
--- a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.html
+++ b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.html
@@ -29,11 +29,11 @@
   [href]="url"
   [target]="targetName"
   [attr.aria-label]="text"
-  [tooltip]="tooltip"
   [color]="'primary'"
   [title]="tooltip"
   class="button"
 >
-  <mat-icon>open_in_new</mat-icon>
   <span class="text-sm">{{ text }}</span>
+  <mat-icon>open_in_new</mat-icon>
+  <span class="sr-only">{{ tooltip }}</span>
 </a>
diff --git a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.scss b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.scss
index 8b0ddf04c2f9ea722d7eb1bedaa6bd8e7adfb87e..142aa51807244ffac6a9de41d169fd69fc77daa7 100644
--- a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.scss
+++ b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.scss
@@ -24,7 +24,7 @@
 @import 'variables';
 
 :host {
-  @apply flex h-12 w-full items-center justify-start pb-1 pl-4 pr-3 pt-1 sm:sticky;
+  @apply flex h-12 w-full items-center justify-start pb-1 pl-3 pr-3 pt-1 sm:sticky;
   top: $header-height;
   z-index: 2;
   box-shadow: $shadow-bottom;
diff --git a/alfa-client/libs/ui/src/lib/ui/ui.module.ts b/alfa-client/libs/ui/src/lib/ui/ui.module.ts
index eeff7417056ee49e49cbe8c4206a2e72aa5dd9a5..e7c19b188d8e38ab7c45f080f52b4b3536550cc4 100644
--- a/alfa-client/libs/ui/src/lib/ui/ui.module.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ui.module.ts
@@ -47,7 +47,13 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
 import { MatSnackBarModule } from '@angular/material/snack-bar';
 import { MatTabsModule } from '@angular/material/tabs';
 import { RouterModule } from '@angular/router';
-import { FileUploadButtonComponent, SpinnerIconComponent, TooltipDirective } from '@ods/system';
+import {
+  ArrowBackIconComponent,
+  ButtonComponent,
+  FileUploadButtonComponent,
+  SpinnerIconComponent,
+  TooltipDirective,
+} from '@ods/system';
 import { de } from 'date-fns/locale';
 import { AppIconComponent } from '../icon/app-icon/app-icon.component';
 import { PostfachIconComponent } from '../icon/postfach-icon/postfach-icon.component';
@@ -162,6 +168,8 @@ import { ValidationErrorComponent } from './validation-error/validation-error.co
     FileUploadButtonComponent,
     SpinnerIconComponent,
     TooltipDirective,
+    ButtonComponent,
+    ArrowBackIconComponent,
   ],
   exports: [
     MatButtonModule,
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html
index bc56dba4cc337d7d6d7f633330173b50797d0187..9ec99cebdafed843b5ded6af4b56c34fb2b04638 100644
--- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html
@@ -23,4 +23,11 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<alfa-open-documentation-button [url]="url"></alfa-open-documentation-button>
+<ods-dropdown-menu-text-item
+  class="border-b border-b-grayborder border-t-grayborder bg-whitetext"
+  title="Benutzerleitfaden"
+  description="Alle Funktionen der Allgemeinen Fachanwendung (Alfa) erklärt."
+>
+  <ods-file-icon icon fileType="pdf" size="large"></ods-file-icon>
+  <alfa-open-documentation-button additionalContent [url]="url" data-test-id="documentations-component" />
+</ods-dropdown-menu-text-item>
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts
index efc735e3cf593002792658acffd7053851e06e54..b7307c4a9f800117718ab72571c87289e011907c 100644
--- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts
@@ -22,6 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { DropdownMenuTextItemComponent, FileIconComponent } from '@ods/system';
 import { MockComponent } from 'ng-mocks';
 import { DocumentationComponent } from './documentation.component';
 import { OpenDocumentationButtonComponent } from './open-documentation-button/open-documentation-button.component';
@@ -32,7 +33,12 @@ describe('DocumentationComponent', () => {
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [DocumentationComponent, MockComponent(OpenDocumentationButtonComponent)],
+      declarations: [
+        DocumentationComponent,
+        MockComponent(OpenDocumentationButtonComponent),
+        MockComponent(DropdownMenuTextItemComponent),
+        MockComponent(FileIconComponent),
+      ],
     }).compileComponents();
 
     fixture = TestBed.createComponent(DocumentationComponent);
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..c2e1745ad17aa6a42614f563d95e15dfa57266e8
--- /dev/null
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.html
@@ -0,0 +1,4 @@
+<div class="flex items-center text-ozggray-800 dark:text-ozggray-300">
+  <ods-help-icon />
+  <div class="ml-1 text-sm font-medium">Hilfe</div>
+</div>
\ No newline at end of file
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4430d6bc1e3b154ae0ec0868fb49504296a1782b
--- /dev/null
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.spec.ts
@@ -0,0 +1,24 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HelpIconComponent } from '@ods/system';
+import { MockComponent } from 'ng-mocks';
+import { HelpButtonComponent } from './help-button.component';
+
+describe('HelpButtonComponent', () => {
+  let component: HelpButtonComponent;
+  let fixture: ComponentFixture<HelpButtonComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [HelpButtonComponent, MockComponent(HelpIconComponent)],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(HelpButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ace8b9adf1443414b53c935ec317ffe96a7df317
--- /dev/null
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-button/help-button.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'alfa-help-button',
+  templateUrl: './help-button.component.html',
+})
+export class HelpButtonComponent {}
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html
index ae214c9fa7b6f83e80e493c5613053f953e931fb..24ee1e914732e11ea00e3dad00a7cffea735b000 100644
--- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html
@@ -26,28 +26,18 @@
 <ods-dropdown-menu
   buttonClass="rounded-lg p-2 hover:bg-neutral-100 focus:bg-neutral-200 focus:outline-none dark:hover:bg-neutral-700 dark:focus:bg-neutral-600"
 >
-  <div
-    button-content
-    *ngIf="enabled"
-    data-test-id="help-menu-button"
-    class="flex items-center text-ozggray-800 dark:text-ozggray-300"
-  >
-    <ods-help-icon />
-    <div class="ml-1 text-sm font-medium">Hilfe</div>
-  </div>
+  @if (enabled) {
+    <alfa-help-button button-content data-test-id="help-menu-button" />
+  }
 
-  <ods-dropdown-menu-text-item
-    *ngIf="apiRootStateResource?.resource | hasLink: apiRootLinkRel.DOCUMENTATIONS"
-    class="border-b border-b-grayborder border-t-grayborder bg-whitetext first:border-t"
-    title="Benutzerleitfaden"
-    description="Alle Funktionen der Allgemeinen Fachanwendung (Alfa) erklärt."
-  >
-    <ods-file-icon icon fileType="pdf" size="large"></ods-file-icon>
+  @if (apiRootStateResource?.resource | hasLink: apiRootLinkRel.DOCUMENTATIONS) {
     <alfa-documentation
-      additionalContent
-      data-test-id="documentations-component"
       [url]="apiRootStateResource.resource | getUrl: apiRootLinkRel.DOCUMENTATIONS"
-    >
-    </alfa-documentation>
-  </ods-dropdown-menu-text-item>
+      data-test-id="documentation"
+    />
+  }
+
+  @if (apiRootStateResource?.resource?.impressumUrl) {
+    <ods-dropdown-menu-link-item [url]="apiRootStateResource.resource.impressumUrl" text="Impressum" data-test-id="impressum" />
+  }
 </ods-dropdown-menu>
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts
index 96f154ac92d70d4dbba6bdd86dcabb4122468d04..ba0e572d4edad3c8e610cd869d31b40b186d8d5d 100644
--- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts
@@ -27,11 +27,18 @@ import { getElementFromDomRoot } from '@alfa-client/test-utils';
 import { UiModule } from '@alfa-client/ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { NoopAnimationsModule } from '@angular/platform-browser/animations';
-import { DropdownMenuComponent, DropdownMenuTextItemComponent, FileIconComponent, HelpIconComponent } from '@ods/system';
+import {
+  DropdownMenuComponent,
+  DropdownMenuLinkItemComponent,
+  DropdownMenuTextItemComponent,
+  FileIconComponent,
+  HelpIconComponent,
+} from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { createApiRootResource } from '../../../../../libs/api-root-shared/test/api-root';
 import { DocumentationComponent } from './documentation/documentation.component';
+import { HelpButtonComponent } from './help-button/help-button.component';
 import { HelpMenuComponent } from './help-menu.component';
 
 describe('HelpMenuComponent', () => {
@@ -39,6 +46,7 @@ describe('HelpMenuComponent', () => {
   let fixture: ComponentFixture<HelpMenuComponent>;
 
   const helpMenuButton: string = getDataTestIdOf('help-menu-button');
+  const impressumLink: string = getDataTestIdOf('impressum');
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -51,6 +59,8 @@ describe('HelpMenuComponent', () => {
         MockComponent(HelpIconComponent),
         MockComponent(DropdownMenuTextItemComponent),
         MockComponent(DropdownMenuComponent),
+        MockComponent(DropdownMenuLinkItemComponent),
+        MockComponent(HelpButtonComponent),
       ],
       imports: [NoopAnimationsModule, UiModule],
     }).compileComponents();
@@ -89,7 +99,7 @@ describe('HelpMenuComponent', () => {
 
   describe('component', () => {
     describe('hasMenuItems', () => {
-      it('should return true if at least 1 menu item exists', () => {
+      it('should return true if documentation Link exists', () => {
         component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS]));
 
         const res: boolean = component.hasMenuItems();
@@ -97,11 +107,20 @@ describe('HelpMenuComponent', () => {
         expect(res).toBeTruthy();
       });
 
-      it('should return false if no menu item exists', () => {
+      it('should return true if impressumUrl exists', () => {
         component.apiRootStateResource = createStateResource(createApiRootResource());
 
         const res: boolean = component.hasMenuItems();
 
+        expect(res).toBeTruthy();
+      });
+
+      it('should return false', () => {
+        component.apiRootStateResource = createStateResource(createApiRootResource());
+        component.apiRootStateResource.resource.impressumUrl = null;
+
+        const res: boolean = component.hasMenuItems();
+
         expect(res).toBeFalsy();
       });
     });
@@ -110,13 +129,16 @@ describe('HelpMenuComponent', () => {
   describe('template', () => {
     describe('help menu button', () => {
       it('should be hidden', () => {
-        const item = getElementFromDomRoot(fixture, helpMenuButton);
+        component.enabled = false;
 
+        fixture.detectChanges();
+
+        const item = getElementFromDomRoot(fixture, helpMenuButton);
         expect(item).not.toBeInstanceOf(HTMLElement);
       });
 
       it('should be shown', () => {
-        component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS]));
+        component.enabled = true;
 
         fixture.detectChanges();
 
@@ -124,5 +146,38 @@ describe('HelpMenuComponent', () => {
         expect(item).toBeInstanceOf(HTMLElement);
       });
     });
+
+    describe('alfa-documentation', () => {
+      it('should be hidden if no documentation link', () => {
+        const documentation = getElementFromDomRoot(fixture, getDataTestIdOf('documentation'));
+
+        expect(documentation).not.toBeInstanceOf(HTMLElement);
+      });
+
+      it('should be shown', () => {
+        component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS]));
+
+        fixture.detectChanges();
+
+        const documentation = getElementFromDomRoot(fixture, getDataTestIdOf('documentation'));
+        expect(documentation).toBeInstanceOf(HTMLElement);
+      });
+    });
+
+    describe('ods-dropdown-menu-link', () => {
+      it('should be hidden if no impressumUrl', () => {
+        component.apiRootStateResource.resource.impressumUrl = null;
+
+        fixture.detectChanges();
+
+        const impressum = getElementFromDomRoot(fixture, impressumLink);
+        expect(impressum).not.toBeInstanceOf(HTMLElement);
+      });
+
+      it('should be shown if impressumUrl', () => {
+        const impressum = getElementFromDomRoot(fixture, impressumLink);
+        expect(impressum).toBeInstanceOf(HTMLElement);
+      });
+    });
   });
 });
diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.ts
index 3b6fbf490e2df7635ec7bed024ea67a2855db3a6..2c8fb3b9e0d656b74f5bbd765b779c35bdaf5a99 100644
--- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.ts
+++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.ts
@@ -25,13 +25,13 @@ import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { Component, Input } from '@angular/core';
 import { hasLink } from '@ngxp/rest';
+import { isNil } from 'lodash-es';
 
 @Component({
   selector: 'alfa-help-menu',
   templateUrl: './help-menu.component.html',
 })
 export class HelpMenuComponent {
-
   @Input() set apiRootStateResource(value: StateResource<ApiRootResource>) {
     this._apiRootStateResource = value;
     this.enabled = this.hasMenuItems();
@@ -48,6 +48,14 @@ export class HelpMenuComponent {
   public readonly apiRootLinkRel = ApiRootLinkRel;
 
   public hasMenuItems(): boolean {
-    return [hasLink(this.apiRootStateResource?.resource, ApiRootLinkRel.DOCUMENTATIONS)].filter((isTrue) => isTrue).length > 0;
+    return this.hasDocumentationLink() || this.hasImpressumUrl();
+  }
+
+  private hasImpressumUrl(): boolean {
+    return !isNil(this.apiRootStateResource?.resource?.impressumUrl);
+  }
+
+  private hasDocumentationLink(): boolean {
+    return hasLink(this.apiRootStateResource?.resource, ApiRootLinkRel.DOCUMENTATIONS);
   }
 }
diff --git a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts
index 70fb69b6d2ae8b0a50142d79ca356b1a7b19fb6e..1eda492b4fe8af82af049e37d1548a419912e98f 100644
--- a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts
+++ b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts
@@ -25,9 +25,16 @@ import { TechSharedModule } from '@alfa-client/tech-shared';
 import { UiModule } from '@alfa-client/ui';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
-import { DropdownMenuComponent, DropdownMenuTextItemComponent, FileIconComponent, HelpIconComponent } from '@ods/system';
+import {
+  DropdownMenuComponent,
+  DropdownMenuLinkItemComponent,
+  DropdownMenuTextItemComponent,
+  FileIconComponent,
+  HelpIconComponent,
+} from '@ods/system';
 import { DocumentationComponent } from './help-menu/documentation/documentation.component';
 import { OpenDocumentationButtonComponent } from './help-menu/documentation/open-documentation-button/open-documentation-button.component';
+import { HelpButtonComponent } from './help-menu/help-button/help-button.component';
 import { HelpMenuComponent } from './help-menu/help-menu.component';
 
 @NgModule({
@@ -39,8 +46,9 @@ import { HelpMenuComponent } from './help-menu/help-menu.component';
     DropdownMenuComponent,
     DropdownMenuTextItemComponent,
     UiModule,
+    DropdownMenuLinkItemComponent,
   ],
-  declarations: [HelpMenuComponent, DocumentationComponent, OpenDocumentationButtonComponent],
+  declarations: [HelpMenuComponent, DocumentationComponent, OpenDocumentationButtonComponent, HelpButtonComponent],
   exports: [HelpMenuComponent],
 })
 export class UserAssistanceModule {}
diff --git a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.html b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.html
index ac709eb5dc988c92b1eb4172e07b5b6928286842..f0e6aa37b1b8932034832aa3beeed0f92b4c4ff4 100644
--- a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.html
+++ b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.html
@@ -23,11 +23,15 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-icon-button-with-spinner
-  *ngIf="vorgang | hasLink: linkRel.ASSIGN"
-  svgIcon="account_outline"
-  toolTip="Bearbeiter zuordnen"
-  (clickEmitter)="showUserProfileSearch()"
-  data-test-id="assign-user-profile-icon-button"
->
-</ozgcloud-icon-button-with-spinner>
+@if (vorgang | hasLink: linkRel.ASSIGN) {
+  <ods-button-with-spinner
+    svgIcon="account_outline"
+    tooltip="Bearbeiter zuordnen"
+    data-test-id="assign-user-profile-icon-button"
+    variant="ghost"
+    size="fit"
+    (clickEmitter)="showUserProfileSearch()"
+  >
+    <ods-account-circle-icon icon class="fill-text" />
+  </ods-button-with-spinner>
+}
diff --git a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.scss b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.spec.ts
index 5f82315849d7119b780f8ad9f6da480c1ec8bd08..531805961b6eef4f0453f69ca5ebb481c096b1aa 100644
--- a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.spec.ts
+++ b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.spec.ts
@@ -21,12 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { HasLinkPipe } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import { IconButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { UserProfileService } from '@alfa-client/user-profile-shared';
 import { VorgangHeaderLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { AccountCircleIconComponent } from '@ods/system';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { AssignUserProfileButtonContainerComponent } from './assign-user-profile-button-container.component';
@@ -44,7 +45,8 @@ describe('AssignUserProfileButtonContainerComponent', () => {
       declarations: [
         AssignUserProfileButtonContainerComponent,
         HasLinkPipe,
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(AccountCircleIconComponent),
       ],
       providers: [
         {
diff --git a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.ts b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.ts
index 1ab24948af637d75dd273801cc4f960f29d81234..41b1d332d55c5802986a544f01dacebc8721633e 100644
--- a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.ts
+++ b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.ts
@@ -21,14 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { UserProfileService } from '@alfa-client/user-profile-shared';
 import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input } from '@angular/core';
 
 @Component({
   selector: 'alfa-assign-user-profile-button-container',
   templateUrl: './assign-user-profile-button-container.component.html',
-  styleUrls: ['./assign-user-profile-button-container.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class AssignUserProfileButtonContainerComponent {
   @Input() vorgang: VorgangWithEingangResource;
diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile.search.formservice.ts b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile.search.formservice.ts
index 200165fbd817bb6f412af2d6e25ee2c39ad1f65c..b460545480ccb635036eb0307b96825d3b4755ca 100644
--- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile.search.formservice.ts
+++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile.search.formservice.ts
@@ -30,7 +30,7 @@ import { Observable, Subscription } from 'rxjs';
 import { ValidationMessageCode } from '../../../../../tech-shared/src/lib/validation/tech.validation.messages';
 
 @Injectable()
-export class UserProfileSearchFormService extends AbstractFormService implements OnDestroy {
+export class UserProfileSearchFormService extends AbstractFormService<UserProfileListResource> implements OnDestroy {
   public static readonly SEARCH_FIELD = 'searchBy';
 
   private FIELD_PATH: string = 'only.fe';
diff --git a/alfa-client/libs/user-profile/src/lib/user-profile.module.ts b/alfa-client/libs/user-profile/src/lib/user-profile.module.ts
index 11ab2e9213281a32febbbd4664fa79d59d4969f4..408ace4cfbf611228fe69933743b717961982f55 100644
--- a/alfa-client/libs/user-profile/src/lib/user-profile.module.ts
+++ b/alfa-client/libs/user-profile/src/lib/user-profile.module.ts
@@ -27,7 +27,9 @@ import { UserProfileSharedModule } from '@alfa-client/user-profile-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
 import { RouterModule } from '@angular/router';
+import { ButtonWithSpinnerComponent } from '@ods/component';
 import {
+  AccountCircleIconComponent,
   DropdownMenuButtonItemComponent,
   DropdownMenuComponent,
   DropdownMenuItemComponent,
@@ -69,6 +71,8 @@ import { UserProfileComponent } from './user-profile/user-profile.component';
     DropdownMenuComponent,
     DropdownMenuItemComponent,
     DropdownMenuButtonItemComponent,
+    ButtonWithSpinnerComponent,
+    AccountCircleIconComponent,
     TooltipDirective,
   ],
   declarations: [
diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-dropdown/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-dropdown/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts
index a48bf0572e2f8850044ea6f0c9bcb00e676511ad..847eb89e25387f795a36720c5ed61e90de627939 100644
--- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-dropdown/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts
+++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-dropdown/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts
@@ -118,8 +118,7 @@ describe('UserSettingsEmailBenachrichtigungComponent', () => {
       });
 
       it('should call return true if notificationsSendFor is ALL', () => {
-        component.userSettings.resource[UserNotificationsTypes.NOTIFICATIONS_SEND_FOR] =
-          NotificationSendForTypes.ALL;
+        component.userSettings.resource[UserNotificationsTypes.NOTIFICATIONS_SEND_FOR] = NotificationSendForTypes.ALL;
 
         const result: boolean = component.isChecked(UserNotificationsTypes.NOTIFICATIONS_SEND_FOR);
 
@@ -127,8 +126,7 @@ describe('UserSettingsEmailBenachrichtigungComponent', () => {
       });
 
       it('should call return false if notificationsSendFor is NONE', () => {
-        component.userSettings.resource[UserNotificationsTypes.NOTIFICATIONS_SEND_FOR] =
-          NotificationSendForTypes.NONE;
+        component.userSettings.resource[UserNotificationsTypes.NOTIFICATIONS_SEND_FOR] = NotificationSendForTypes.NONE;
 
         const result: boolean = component.isChecked(UserNotificationsTypes.NOTIFICATIONS_SEND_FOR);
 
@@ -161,7 +159,7 @@ describe('UserSettingsEmailBenachrichtigungComponent', () => {
 
         component.emitSettingsForVorgangCreated(true);
 
-        expect(valueChangedEmitter.emit).toBeCalledWith({
+        expect(valueChangedEmitter.emit).toHaveBeenCalledWith({
           ...settings,
           [UserNotificationsTypes.VORGANGE_CREATED]: true,
           [UserNotificationsTypes.NOTIFICATIONS_SEND_FOR]: NotificationSendForTypes.ALL,
@@ -174,7 +172,7 @@ describe('UserSettingsEmailBenachrichtigungComponent', () => {
 
         component.emitSettingsForVorgangCreated(false);
 
-        expect(valueChangedEmitter.emit).toBeCalledWith({
+        expect(valueChangedEmitter.emit).toHaveBeenCalledWith({
           ...settings,
           [UserNotificationsTypes.VORGANGE_CREATED]: false,
           [UserNotificationsTypes.NOTIFICATIONS_SEND_FOR]: NotificationSendForTypes.NONE,
@@ -189,7 +187,7 @@ describe('UserSettingsEmailBenachrichtigungComponent', () => {
 
         component.emitSettings(UserNotificationsTypes.WIEDERVORLAGE_DUE_TODAY, true);
 
-        expect(valueChangedEmitter.emit).toBeCalledWith({
+        expect(valueChangedEmitter.emit).toHaveBeenCalledWith({
           ...settings,
           [UserNotificationsTypes.WIEDERVORLAGE_DUE_TODAY]: true,
         });
@@ -201,7 +199,7 @@ describe('UserSettingsEmailBenachrichtigungComponent', () => {
 
         component.emitSettings(UserNotificationsTypes.WIEDERVORLAGE_DUE_TODAY, false);
 
-        expect(valueChangedEmitter.emit).toBeCalledWith({
+        expect(valueChangedEmitter.emit).toHaveBeenCalledWith({
           ...settings,
           [UserNotificationsTypes.WIEDERVORLAGE_DUE_TODAY]: false,
         });
diff --git a/alfa-client/libs/user-settings/src/lib/user-settings.module.ts b/alfa-client/libs/user-settings/src/lib/user-settings.module.ts
index 6dbf5e4ecc89f1ebef3f57dc78b3726a6d642c5b..bafeb748dc5a3c6c145397e031924740372c07be 100644
--- a/alfa-client/libs/user-settings/src/lib/user-settings.module.ts
+++ b/alfa-client/libs/user-settings/src/lib/user-settings.module.ts
@@ -25,8 +25,7 @@ import { UiModule } from '@alfa-client/ui';
 import { UserSettingsSharedModule } from '@alfa-client/user-settings-shared';
 import { CommonModule } from '@angular/common';
 import { NgModule } from '@angular/core';
-import { CloseIconComponent, DropdownMenuComponent } from '@ods/system';
-import { SettingsIconComponent } from '../../../design-system/src/lib/icons/settings-icon/settings-icon.component';
+import { CloseIconComponent, DropdownMenuComponent, SettingsIconComponent } from '@ods/system';
 import { UserSettingsContainerComponent } from './user-settings-container/user-settings-container.component';
 import { UserSettingsDarkmodeContainerComponent } from './user-settings-container/user-settings/user-settings-dropdown/user-settings-darkmode-container/user-settings-darkmode-container.component';
 import { UserSettingsDarkmodeComponent } from './user-settings-container/user-settings/user-settings-dropdown/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component';
@@ -36,14 +35,7 @@ import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-cont
 import { UserSettingsComponent } from './user-settings-container/user-settings/user-settings.component';
 
 @NgModule({
-  imports: [
-    CommonModule,
-    UiModule,
-    UserSettingsSharedModule,
-    DropdownMenuComponent,
-    CloseIconComponent,
-    SettingsIconComponent,
-  ],
+  imports: [CommonModule, UiModule, UserSettingsSharedModule, DropdownMenuComponent, CloseIconComponent, SettingsIconComponent],
   declarations: [
     UserSettingsContainerComponent,
     UserSettingsEmailBenachrichtigungComponent,
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.spec.ts
index 38daf67265460873bf9f585af1fbe5b81bfbf6a0..ebf2fa64f17b56d95828a63bb475020d4178ab76 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.spec.ts
@@ -204,7 +204,7 @@ describe('AktenzeichenEditDialogComponent', () => {
         component.onSubmit();
 
         component.setAktenzeichenPending$.subscribe(() => {
-          expect(component.onResponse).toBeCalledWith(null);
+          expect(component.onResponse).toHaveBeenCalledWith(null);
           done();
         });
       });
@@ -212,9 +212,7 @@ describe('AktenzeichenEditDialogComponent', () => {
       it('should emit state resource', () => {
         component.onSubmit();
 
-        expect(component.setAktenzeichenPending$).toBeObservable(
-          cold('a', { a: { resource: null } }),
-        );
+        expect(component.setAktenzeichenPending$).toBeObservable(cold('a', { a: { resource: null } }));
       });
     });
   });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.spec.ts
index ed1292255cab2935d4ecd06096f9633e08b68545..7a4da00189c7a8b1ae85d52d6b796bfc86311862 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.spec.ts
@@ -71,6 +71,6 @@ describe('doSubmit', () => {
 
     service.submit();
 
-    expect(vorgangService.setAktenzeichen).toBeCalledWith(vorgang, 'aktenzeichen');
+    expect(vorgangService.setAktenzeichen).toHaveBeenCalledWith(vorgang, 'aktenzeichen');
   });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.ts
index ac99bf791805158383c8d5c3131e150480e1f5aa..ca0d36b3c4445a90c7c48aa1f86dc8d3c8390e77 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.ts
@@ -21,16 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { CommandResource } from '@alfa-client/command-shared';
+import { AbstractFormService, StateResource } from '@alfa-client/tech-shared';
+import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Injectable } from '@angular/core';
 import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
-import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { isEmpty } from 'lodash-es';
-import { AbstractFormService, StateResource } from '@alfa-client/tech-shared';
 import { Observable } from 'rxjs';
-import { Resource } from '@ngxp/rest';
 
 @Injectable()
-export class AktenzeichenEditDialogFormservice extends AbstractFormService {
+export class AktenzeichenEditDialogFormservice extends AbstractFormService<CommandResource> {
   static readonly AKTENZEICHEN_FIELD = 'aktenzeichen';
 
   private vorgang: VorgangWithEingangResource;
@@ -48,7 +48,7 @@ export class AktenzeichenEditDialogFormservice extends AbstractFormService {
     });
   }
 
-  protected doSubmit(): Observable<StateResource<Resource>> {
+  protected doSubmit(): Observable<StateResource<CommandResource>> {
     return this.vorgangService.setAktenzeichen(this.vorgang, this.getValue());
   }
 
@@ -78,8 +78,6 @@ export class AktenzeichenEditDialogFormservice extends AbstractFormService {
   }
 
   private getFormControl(): UntypedFormControl {
-    return <UntypedFormControl>(
-      this.form.controls[AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD]
-    );
+    return <UntypedFormControl>this.form.controls[AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD];
   }
 }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.html b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.html
index 3f94a6da451f1731445c8b37487d6dfc03eb0fe6..e56be799f110d811aa849ebd4db4709e7c644307 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.html
@@ -24,13 +24,17 @@
 
 -->
 <div class="flex flex-shrink" alfa-aktenzeichen [vorgang]="vorgang"></div>
-<ng-container *ngIf="vorgang | hasLink: linkRel.SET_AKTENZEICHEN">
-  <div class="relative w-12">
-    <ozgcloud-icon-button-primary
-      svgIcon="edit"
+@if (vorgang | hasLink: linkRel.SET_AKTENZEICHEN) {
+  <div class="relative">
+    <ods-button
+      class="absolute -top-2"
+      variant="ghost"
+      size="fit"
       tooltip="Aktenzeichen bearbeiten"
       data-test-id="aktenzeichen-editieren"
       (clickEmitter)="onEdit()"
-    ></ozgcloud-icon-button-primary>
+    >
+      <ods-edit-icon icon />
+    </ods-button>
   </div>
-</ng-container>
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.spec.ts
index ff9fac80cc66eab370ef4677e805fe24aa697c8e..11982ed18070cf1894cabf09fdf2cb958c9970ff 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.spec.ts
@@ -22,11 +22,13 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { HasLinkPipe } from '@alfa-client/tech-shared';
-import { mock } from '@alfa-client/test-utils';
-import { DialogService, OzgcloudIconButtonPrimaryComponent } from '@alfa-client/ui';
+import { existsAsHtmlElement, mock, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { DialogService } from '@alfa-client/ui';
 import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
 import { AktenzeichenComponent } from '@alfa-client/vorgang-shared-ui';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonComponent, EditIconComponent } from '@ods/system';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { AktenzeichenEditDialogComponent } from '../aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component';
@@ -36,6 +38,8 @@ describe('AktenzeichenComponent', () => {
   let component: AktenzeichenEditableComponent;
   let fixture: ComponentFixture<AktenzeichenEditableComponent>;
 
+  const editButton: string = getDataTestIdOf('aktenzeichen-editieren');
+
   const dialogService = mock(DialogService);
 
   beforeEach(async () => {
@@ -43,7 +47,8 @@ describe('AktenzeichenComponent', () => {
       declarations: [
         HasLinkPipe,
         AktenzeichenEditableComponent,
-        MockComponent(OzgcloudIconButtonPrimaryComponent),
+        MockComponent(ButtonComponent),
+        MockComponent(EditIconComponent),
         MockComponent(AktenzeichenComponent),
       ],
       providers: [
@@ -79,12 +84,8 @@ describe('AktenzeichenComponent', () => {
   });
 
   describe('after render', () => {
-    it('should render edit button', () => {
-      const editIcon = fixture.nativeElement.querySelector('ozgcloud-icon-button-primary');
-
-      fixture.detectChanges();
-
-      expect(editIcon).not.toBeInstanceOf(HTMLElement);
+    it('should NOT render edit button', () => {
+      notExistsAsHtmlElement(fixture, editButton);
     });
 
     it('should render edit button', () => {
@@ -94,8 +95,7 @@ describe('AktenzeichenComponent', () => {
 
       fixture.detectChanges();
 
-      const editIcon = fixture.nativeElement.querySelector('ozgcloud-icon-button-primary');
-      expect(editIcon).toBeInstanceOf(HTMLElement);
+      existsAsHtmlElement(fixture, editButton);
     });
   });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.ts
index 0b7c225ce89af017ffe0f15b00511cd859deb0e8..383891cf573dac67b7462abdc92f4c5650e735d2 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.ts
@@ -21,15 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
-import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { DialogService } from '@alfa-client/ui';
+import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input } from '@angular/core';
 import { AktenzeichenEditDialogComponent } from '../aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component';
 
 @Component({
   selector: 'alfa-aktenzeichen-editable',
   templateUrl: './aktenzeichen-editable.component.html',
-  styleUrls: ['./aktenzeichen-editable.component.scss'],
 })
 export class AktenzeichenEditableComponent {
   @Input() vorgang: VorgangWithEingangResource;
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.html
index c57d7a4c19bb47c890da21d0d099f28f87267e98..758515c53318532c5950c7d61b75fa296137cabc 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.html
@@ -23,24 +23,28 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="isVisible">
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton"
-    data-test-id="abschliessen-button"
-    text="Abschließen"
-    icon="done"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="abschliessen()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
 
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="abschliessen-icon-button"
-    icon="done"
-    toolTip="Vorgang abschließen"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="abschliessen()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+@if (isVisible) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="abschliessen-icon-button"
+      tooltip="Vorgang abschließen"
+      variant="ghost"
+      size="fit"
+      (clickEmitter)="abschliessen()"
+    >
+      <ods-check-icon icon class="fill-text" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="abschliessen-button"
+      text="Abschließen"
+      variant="outline"
+      (clickEmitter)="abschliessen()"
+    >
+      <ods-check-icon icon />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.scss b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.spec.ts
index 195bee49faa4e3b85bc3d7ed09a73964507d4c33..a7334741a042a9d6cbe14d06d190160bd7bda7c5 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.spec.ts
@@ -22,13 +22,14 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { CommandResource } from '@alfa-client/command-shared';
-import { createEmptyStateResource, createStateResource, HasLinkPipe, StateResource, } from '@alfa-client/tech-shared';
+import { createEmptyStateResource, createStateResource, HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent, } from '@alfa-client/ui';
-import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource, } from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { CheckIconComponent } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
-import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { Observable, of } from 'rxjs';
@@ -38,8 +39,8 @@ describe('AbschliessenButtonComponent', () => {
   let component: AbschliessenButtonComponent;
   let fixture: ComponentFixture<AbschliessenButtonComponent>;
 
-  const abschliessenButton: string = getDataTestIdOf('abschliessen-button');
-  const abschliessenIconButton: string = getDataTestIdOf('abschliessen-icon-button');
+  const abschliessenButton: string = getDataTestIdAttributeOf('abschliessen-button');
+  const abschliessenIconButton: string = getDataTestIdAttributeOf('abschliessen-icon-button');
 
   const vorgangCommandService = {
     ...mock(VorgangCommandService),
@@ -50,8 +51,8 @@ describe('AbschliessenButtonComponent', () => {
     await TestBed.configureTestingModule({
       declarations: [
         AbschliessenButtonComponent,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(CheckIconComponent),
         HasLinkPipe,
       ],
       providers: [
@@ -84,9 +85,7 @@ describe('AbschliessenButtonComponent', () => {
 
   describe('abschliessen', () => {
     const command: CommandResource = createCommandResource();
-    const comandStateResource$: Observable<StateResource<CommandResource>> = of(
-      createStateResource(command),
-    );
+    const comandStateResource$: Observable<StateResource<CommandResource>> = of(createStateResource(command));
 
     beforeEach(() => {
       vorgangCommandService.abschliessen.mockReturnValue(comandStateResource$);
@@ -167,9 +166,7 @@ describe('AbschliessenButtonComponent', () => {
     });
 
     it('should set visible to true', () => {
-      const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.ABSCHLIESSEN,
-      ]);
+      const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ABSCHLIESSEN]);
       component.vorgang = vorgang;
 
       const isVisible: boolean = component.isVisible;
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.ts
index 578482c2b8afc80ee4a20e83063eaca2ea28af06..94f843b044b8ab413981972ecdda058a1aedb1cd 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.ts
@@ -23,7 +23,7 @@
  */
 import { CommandResource } from '@alfa-client/command-shared';
 import { createEmptyStateResource, notHasLink, StateResource } from '@alfa-client/tech-shared';
-import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource, } from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Component, Input, OnInit } from '@angular/core';
 import { hasLink } from '@ngxp/rest';
 import { Observable, of } from 'rxjs';
@@ -31,7 +31,7 @@ import { Observable, of } from 'rxjs';
 @Component({
   selector: 'alfa-abschliessen-button',
   templateUrl: './abschliessen-button.component.html',
-  styleUrls: ['./abschliessen-button.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class AbschliessenButtonComponent implements OnInit {
   @Input() set vorgang(vorgang: VorgangWithEingangResource) {
@@ -47,9 +47,7 @@ export class AbschliessenButtonComponent implements OnInit {
   public isVisible: boolean = false;
   vorgangWithEingangResource: VorgangWithEingangResource;
 
-  commandStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   readonly linkRel = VorgangWithEingangLinkRel;
 
@@ -60,8 +58,6 @@ export class AbschliessenButtonComponent implements OnInit {
   }
 
   public abschliessen(): void {
-    this.commandStateResource$ = this.vorgangCommandService.abschliessen(
-      this.vorgangWithEingangResource,
-    );
+    this.commandStateResource$ = this.vorgangCommandService.abschliessen(this.vorgangWithEingangResource);
   }
 }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.html
index 97c685caf75a1115aa2be2c61844b11c1c212c58..7e55b9639e4a09b970c98394ad360cf550f80dcd 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.html
@@ -23,24 +23,27 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="vorgang | hasLink: linkRel.ANNEHMEN">
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton"
-    data-test-id="annehmen-button"
-    text="Annehmen"
-    icon="check_circle_outline"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="annehmen()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
-
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="annehmen-icon-button"
-    icon="check_circle_outline"
-    toolTip="Vorgang annehmen"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="annehmen()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+@if (vorgang | hasLink: linkRel.ANNEHMEN) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      (clickEmitter)="annehmen()"
+      tooltip="Vorgang annehmen"
+      variant="ghost"
+      size="fit"
+      dataTestId="annehmen-icon-button"
+    >
+      <ods-check-circle-icon icon class="fill-text" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      (clickEmitter)="annehmen()"
+      text="Annehmen"
+      variant="outline"
+      dataTestId="annehmen-button"
+    >
+      <ods-check-circle-icon icon />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.scss b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.spec.ts
index 43b5fa53e79d33357af2d71527b5a99310363c0a..0b4059086facce657ae46ba5a1c241afc7eb5122 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.spec.ts
@@ -21,16 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
-import { mock } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
+import { CommandResource } from '@alfa-client/command-shared';
+import { createStateResource, HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
+import { getElementComponentFromFixtureByCss, mock, notExistsAsHtmlElement, triggerEvent } from '@alfa-client/test-utils';
 import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { CheckCircleIconComponent, TooltipDirective } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
-import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
@@ -40,8 +39,8 @@ describe('AnnehmenButtonComponent', () => {
   let component: AnnehmenButtonComponent;
   let fixture: ComponentFixture<AnnehmenButtonComponent>;
 
-  const annehmenButton: string = getDataTestIdOf('annehmen-button');
-  const annehmenIconButton: string = getDataTestIdOf('annehmen-icon-button');
+  const annehmenButton: string = getDataTestIdAttributeOf('annehmen-button');
+  const annehmenIconButton: string = getDataTestIdAttributeOf('annehmen-icon-button');
 
   const vorgangCommandService = {
     ...mock(VorgangCommandService),
@@ -52,9 +51,10 @@ describe('AnnehmenButtonComponent', () => {
     await TestBed.configureTestingModule({
       declarations: [
         AnnehmenButtonComponent,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
         HasLinkPipe,
+        TooltipDirective,
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(CheckCircleIconComponent),
       ],
       providers: [
         {
@@ -75,69 +75,93 @@ describe('AnnehmenButtonComponent', () => {
     expect(component).toBeTruthy();
   });
 
-  describe('ngOnInit', () => {
-    it('should call service', () => {
-      component.ngOnInit();
+  describe('component', () => {
+    describe('ngOnInit', () => {
+      it('should call service', () => {
+        component.ngOnInit();
 
-      expect(vorgangCommandService.getAnnehmenCommand).toHaveBeenCalled();
+        expect(vorgangCommandService.getAnnehmenCommand).toHaveBeenCalled();
+      });
     });
-  });
 
-  describe('annehmen', () => {
-    it('should call vorgang service', () => {
-      component.annehmen();
+    describe('annehmen', () => {
+      it('should call vorgang service', () => {
+        component.annehmen();
 
-      expect(vorgangCommandService.annehmen).toHaveBeenCalled();
+        expect(vorgangCommandService.annehmen).toHaveBeenCalled();
+      });
     });
   });
 
-  describe('annehmen button', () => {
+  describe('template', () => {
+    const state: StateResource<CommandResource> = createStateResource(createCommandResource());
+
     beforeEach(() => {
-      component.showAsIconButton = false;
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ANNEHMEN]);
+      component.commandStateResource$ = of(state);
       fixture.detectChanges();
     });
 
-    it('should be hidden', () => {
-      component.vorgang = createVorgangWithEingangResource();
+    describe('annehmen button', () => {
+      beforeEach(() => {
+        component.showAsIconButton = false;
+        fixture.detectChanges();
+      });
 
-      fixture.detectChanges();
-      const buttonElement = fixture.nativeElement.querySelector(annehmenButton);
+      it('should not exist', () => {
+        component.vorgang = createVorgangWithEingangResource();
 
-      expect(buttonElement).not.toBeInstanceOf(HTMLElement);
-    });
+        fixture.detectChanges();
 
-    it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ANNEHMEN]);
+        notExistsAsHtmlElement(fixture, annehmenButton);
+      });
 
-      fixture.detectChanges();
-      const buttonElement = fixture.nativeElement.querySelector(annehmenButton);
+      it('should exist with input', () => {
+        fixture.detectChanges();
 
-      expect(buttonElement).toBeInstanceOf(HTMLElement);
-    });
-  });
+        const button: ButtonWithSpinnerComponent = getElementComponentFromFixtureByCss(fixture, annehmenButton);
 
-  describe('annehmen icon button', () => {
-    beforeEach(() => {
-      component.showAsIconButton = true;
-      fixture.detectChanges();
-    });
+        expect(button.stateResource).toBe(state);
+      });
 
-    it('should be hidden', () => {
-      component.vorgang = createVorgangWithEingangResource();
+      it('should call annehmen on click', () => {
+        component.annehmen = jest.fn();
 
-      fixture.detectChanges();
-      const buttonElement = fixture.nativeElement.querySelector(annehmenIconButton);
+        triggerEvent({ fixture, name: 'clickEmitter', elementSelector: annehmenButton });
 
-      expect(buttonElement).not.toBeInstanceOf(HTMLElement);
+        expect(component.annehmen).toHaveBeenCalled();
+      });
     });
 
-    it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ANNEHMEN]);
+    describe('annehmen icon button', () => {
+      beforeEach(() => {
+        component.showAsIconButton = true;
+        fixture.detectChanges();
+      });
 
-      fixture.detectChanges();
-      const buttonElement = fixture.nativeElement.querySelector(annehmenIconButton);
+      it('should not exist', () => {
+        component.vorgang = createVorgangWithEingangResource();
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, annehmenIconButton);
+      });
+
+      it('should exist with input', () => {
+        fixture.detectChanges();
+
+        const button: ButtonWithSpinnerComponent = getElementComponentFromFixtureByCss(fixture, annehmenIconButton);
+
+        expect(button.stateResource).toBe(state);
+      });
+
+      it('should call annehmen on click', () => {
+        component.annehmen = jest.fn();
+
+        triggerEvent({ fixture, name: 'clickEmitter', elementSelector: annehmenIconButton });
 
-      expect(buttonElement).toBeInstanceOf(HTMLElement);
+        expect(component.annehmen).toHaveBeenCalled();
+      });
     });
   });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.ts
index 84fd1c5d4ff087c5f50a64075b2ee1f5c02397d9..cdbf5447b68d608d658675cf4e71de6dc4837a60 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.ts
@@ -21,28 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input, OnInit } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
-import {
-  VorgangCommandService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input, OnInit } from '@angular/core';
 import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'alfa-annehmen-button',
   templateUrl: './annehmen-button.component.html',
-  styleUrls: ['./annehmen-button.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class AnnehmenButtonComponent implements OnInit {
   @Input() vorgang: VorgangWithEingangResource;
   @Input() showAsIconButton: boolean = false;
 
-  commandStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   readonly linkRel = VorgangWithEingangLinkRel;
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.html
index 9f2900e1d1adee7a82dac65f4bfc058f839129e9..107e3f67c299d7a6199434ebfc4750ae27008242 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.html
@@ -23,24 +23,28 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="vorgang | hasLink: linkRel.BEARBEITEN">
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton"
-    data-test-id="bearbeiten-button"
-    text="Bearbeiten"
-    icon="edit_icon"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="bearbeiten()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
 
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="bearbeiten-icon-button"
-    svgIcon="edit"
-    toolTip="Vorgang bearbeiten"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="bearbeiten()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+@if (vorgang | hasLink: linkRel.BEARBEITEN) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="bearbeiten-icon-button"
+      tooltip="Vorgang bearbeiten"
+      variant="ghost"
+      size="fit"
+      (clickEmitter)="bearbeiten()"
+    >
+      <ods-edit-icon icon class="fill-text" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="bearbeiten-button"
+      text="Bearbeiten"
+      variant="outline"
+      (clickEmitter)="bearbeiten()"
+    >
+      <ods-edit-icon icon />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.scss b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.spec.ts
index ea8f97fa1ec56067731a5c8f9c543907774fe66b..9691ba2813cd8669f2e959a8d1f412a8ec435b52 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.spec.ts
@@ -21,15 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
 import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { EditIconComponent } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
@@ -39,8 +38,8 @@ describe('BearbeitenButtonComponent', () => {
   let component: BearbeitenButtonComponent;
   let fixture: ComponentFixture<BearbeitenButtonComponent>;
 
-  const bearbeitenButton: string = '[data-test-id="bearbeiten-button"]';
-  const bearbeitenIconButton: string = '[data-test-id="bearbeiten-icon-button"]';
+  const bearbeitenButton: string = getDataTestIdAttributeOf('bearbeiten-button');
+  const bearbeitenIconButton: string = getDataTestIdAttributeOf('bearbeiten-icon-button');
 
   const vorgangCommandService = {
     ...mock(VorgangCommandService),
@@ -51,8 +50,8 @@ describe('BearbeitenButtonComponent', () => {
     await TestBed.configureTestingModule({
       declarations: [
         BearbeitenButtonComponent,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(EditIconComponent),
         HasLinkPipe,
       ],
       providers: [
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.ts
index 9b6b581a8bb342d430f675da314b169854cfdf6c..b1371472ec3e01fa15686ef2e7da9d5e4f5d808c 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.ts
@@ -21,28 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input, OnInit } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
-import {
-  VorgangCommandService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input, OnInit } from '@angular/core';
 import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'alfa-bearbeiten-button',
   templateUrl: './bearbeiten-button.component.html',
-  styleUrls: ['./bearbeiten-button.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class BearbeitenButtonComponent implements OnInit {
   @Input() vorgang: VorgangWithEingangResource;
   @Input() showAsIconButton: boolean = false;
 
-  commandStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   readonly linkRel = VorgangWithEingangLinkRel;
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.html
index fa3f6f038d674b8d2d721b91bf3fbd64f5a47ca9..32924b770f3d204f1476521b4fe36050298bdb9f 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.html
@@ -23,24 +23,27 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="vorgang | hasLink: linkRel.BESCHEIDEN">
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton"
-    data-test-id="bescheiden-button"
-    [text]="buttonText"
-    svgIcon="stamp"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="bescheiden()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
-
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="bescheiden-icon-button"
-    svgIcon="stamp"
-    [toolTip]="toolTipText"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="bescheiden()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+@if (vorgang | hasLink: linkRel.BESCHEIDEN) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      (clickEmitter)="bescheiden()"
+      [tooltip]="toolTipText"
+      variant="ghost"
+      size="fit"
+      data-test-id="bescheiden-icon-button"
+    >
+      <ods-stamp-icon icon class="fill-text" size="medium" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      (clickEmitter)="bescheiden()"
+      [text]="buttonText"
+      variant="outline"
+      data-test-id="bescheiden-button"
+    >
+      <ods-stamp-icon icon size="medium" class="fill-primary" />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.scss b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts
index 01fc62566a093101a70b0c9dfc0fab2aa7cee7d8..1cd92c64d9b07060f04273c6007ac1c8920ca8d4 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts
@@ -24,12 +24,16 @@
 import { BescheidResource, BescheidService, BescheidWizardDialogResult } from '@alfa-client/bescheid-shared';
 import { CommandResource } from '@alfa-client/command-shared';
 import { createEmptyStateResource, createStateResource, HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
-import { Mock, mock } from '@alfa-client/test-utils';
 import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudDialogService,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
+  getElementComponentFromFixtureByCss,
+  getMockComponent,
+  Mock,
+  mock,
+  notExistsAsHtmlElement,
+  tooltipExistsWithText,
+  triggerEvent,
+} from '@alfa-client/test-utils';
+import { OzgcloudDialogService } from '@alfa-client/ui';
 import { BescheidenDialogData } from '@alfa-client/vorgang-detail';
 import {
   VorgangCommandService,
@@ -39,6 +43,8 @@ import {
 } from '@alfa-client/vorgang-shared';
 import { DialogRef } from '@angular/cdk/dialog';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { StampIconComponent, TooltipDirective } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
@@ -74,8 +80,9 @@ describe('BescheidenButtonComponent', () => {
       declarations: [
         BescheidenButtonComponent,
         HasLinkPipe,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        TooltipDirective,
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(StampIconComponent),
       ],
       providers: [
         {
@@ -107,300 +114,316 @@ describe('BescheidenButtonComponent', () => {
     expect(component).toBeTruthy();
   });
 
-  describe('ngOnInit', () => {
-    it('should call service', () => {
-      component.ngOnInit();
+  describe('component', () => {
+    describe('ngOnInit', () => {
+      it('should call service', () => {
+        component.ngOnInit();
 
-      expect(vorgangCommandService.getBeschiedenCommand).toHaveBeenCalled();
+        expect(vorgangCommandService.getBeschiedenCommand).toHaveBeenCalled();
+      });
     });
-  });
 
-  describe('bescheiden button', () => {
-    beforeEach(() => {
-      component.showAsIconButton = false;
-      fixture.detectChanges();
-    });
+    describe('bescheiden', () => {
+      describe('should open bescheid wizard', () => {
+        beforeEach(() => {
+          component.openBescheidenWizard = jest.fn();
+          component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.CREATE_BESCHEID_DRAFT]);
+        });
 
-    it('should be hidden', () => {
-      component.vorgang = createVorgangWithEingangResource();
+        it('should open bescheid wizard when create bescheid draft link exists', () => {
+          component.bescheiden();
 
-      fixture.detectChanges();
-      const buttonElement = fixture.nativeElement.querySelector(bescheidenButton);
+          expect(component.openBescheidenWizard).toHaveBeenCalled();
+        });
 
-      expect(buttonElement).not.toBeInstanceOf(HTMLElement);
-    });
+        it('should open bescheid wizard when bescheid draft exists', () => {
+          component.bescheiden();
 
-    it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]);
+          expect(component.openBescheidenWizard).toHaveBeenCalled();
+        });
+      });
 
-      fixture.detectChanges();
-      const buttonElement = fixture.nativeElement.querySelector(bescheidenButton);
+      describe('should do bescheiden', () => {
+        const command: CommandResource = createCommandResource();
+        const comandStateResource$: Observable<StateResource<CommandResource>> = of(createStateResource(command));
 
-      expect(buttonElement).toBeInstanceOf(HTMLElement);
-    });
+        beforeEach(() => {
+          vorgangCommandService.bescheiden.mockReturnValue(comandStateResource$);
+        });
 
-    it('should get "Bescheid" text', () => {
-      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]);
+        it('should call vorgangCommandService.bescheiden', () => {
+          component.bescheiden();
+
+          expect(vorgangCommandService.bescheiden).toHaveBeenCalled();
+        });
+
+        it('should assign response', () => {
+          component.commandStateResource$ = of(createEmptyStateResource<CommandResource>());
 
-      const buttonText: string = component.buttonText;
+          component.bescheiden();
 
-      expect(buttonText).toBe('Bescheiden');
+          expect(component.commandStateResource$).toBe(comandStateResource$);
+        });
+      });
     });
 
-    it('should get "Bescheiden fortsetzen" text', () => {
-      component.vorgang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.BESCHEIDEN,
-        VorgangWithEingangLinkRel.BESCHEID_DRAFT,
-      ]);
+    // TODO: Use this version after completed Bescheid refactoring and delete the other version below.
+    // describe('openBescheidenWizard', () => {
+    //   let dialogRefMock: DialogRefMock<BescheidWizardDialogResult>;
+    //
+    //   beforeEach(() => {
+    //     dialogRefMock = createDialogRefMock<BescheidWizardDialogResult>();
+    //     ozgcloudDialogService.openWizard.mockReturnValue(dialogRefMock);
+    //   });
+    //
+    //   it('should open wizard dialog', () => {
+    //     const vorgang = createVorgangWithEingangResource();
+    //     component.vorgang = vorgang;
+    //
+    //     component.openBescheidenWizard();
+    //
+    //     expect(ozgcloudDialogService.openWizard).toHaveBeenCalledWith(BescheidWizardContainerComponent, {
+    //       vorgangWithEingangResource: vorgang,
+    //     });
+    //   });
+    //
+    //   it('should handleBescheidWizardClosed', () => {
+    //     component.handleBescheidWizardClosed = jest.fn();
+    //     const dialogResult: BescheidWizardDialogResult = { reloadVorgang: true };
+    //     dialogRefMock.closed = of(dialogResult);
+    //
+    //     component.openBescheidenWizard();
+    //
+    //     expect(component.handleBescheidWizardClosed).toHaveBeenCalledWith(dialogResult);
+    //   });
+    // });
+
+    describe('openBescheidenWizard', () => {
+      it('should init', () => {
+        component.openBescheidenWizard();
+
+        expect(bescheidService.init).toHaveBeenCalled();
+      });
 
-      const buttonText: string = component.buttonText;
+      it('should open bescheiden dialog with existing draft', () => {
+        component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEID_DRAFT]);
+        component.openBescheidenDialogWithExistingDraft = jest.fn();
 
-      expect(buttonText).toBe('Bescheiden fortsetzen');
-    });
-  });
+        component.openBescheidenWizard();
 
-  describe('tool tip', () => {
-    it('should get "Vorgang bescheiden" text', () => {
-      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]);
+        expect(component.openBescheidenDialogWithExistingDraft).toHaveBeenCalled();
+      });
 
-      const toolTipText: string = component.toolTipText;
+      it('should open bescheiden dialog with new draft', () => {
+        component.vorgang = createVorgangWithEingangResource();
+        component.openBescheidDialogWithNewDraft = jest.fn();
 
-      expect(toolTipText).toBe('Vorgang bescheiden');
+        component.openBescheidenWizard();
+
+        expect(component.openBescheidDialogWithNewDraft).toHaveBeenCalled();
+      });
     });
 
-    it('should get "Vorgang bescheiden fortsetzen" text', () => {
-      component.vorgang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.BESCHEIDEN,
-        VorgangWithEingangLinkRel.BESCHEID_DRAFT,
-      ]);
+    describe('openBescheidDialogWithNewDraft', () => {
+      it('should open wizard', () => {
+        component.vorgang = createVorgangWithEingangResource();
+        component.openDialog = jest.fn();
 
-      const toolTipText: string = component.toolTipText;
+        component.openBescheidDialogWithNewDraft();
 
-      expect(toolTipText).toBe('Vorgang bescheiden fortsetzen');
+        expect(component.openDialog).toHaveBeenCalledWith({
+          vorgangWithEingangResource: component.vorgang,
+          bescheidDraftResource: null,
+        });
+      });
     });
-  });
 
-  describe('bescheiden', () => {
-    describe('should open bescheid wizard', () => {
+    describe('openBescheidenDialogWithExistingDraft', () => {
+      const bescheidDraftResource: BescheidResource = createBescheidResource();
+      const bescheidDraftStateResource: StateResource<BescheidResource> = createStateResource(bescheidDraftResource);
+      const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource([
+        VorgangWithEingangLinkRel.BESCHEID_DRAFT,
+      ]);
+
       beforeEach(() => {
-        component.openBescheidenWizard = jest.fn();
-        component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.CREATE_BESCHEID_DRAFT]);
+        component.vorgang = vorgangWithEingangResource;
+        bescheidService.getBescheidDraftIfExists.mockReturnValue(of(bescheidDraftStateResource));
       });
 
-      it('should open bescheid wizard when create bescheid draft link exists', () => {
-        component.bescheiden();
+      it('should open wizard if bescheid draft loaded', () => {
+        component.openBescheidenDialogWithExistingDraft();
 
-        expect(component.openBescheidenWizard).toHaveBeenCalled();
+        expect(ozgcloudDialogService.openWizard).toHaveBeenCalledWith(VorgangDetailBescheidenComponent, {
+          bescheidDraftResource,
+          vorgangWithEingangResource,
+        });
       });
 
-      it('should open bescheid wizard when bescheid draft exists', () => {
-        component.bescheiden();
-
-        expect(component.openBescheidenWizard).toHaveBeenCalled();
-      });
-    });
+      it('should not open wizard if bescheid draft not loaded', () => {
+        bescheidService.getBescheidDraftIfExists.mockReturnValue(of(createEmptyStateResource()));
 
-    describe('should do bescheiden', () => {
-      const command: CommandResource = createCommandResource();
-      const comandStateResource$: Observable<StateResource<CommandResource>> = of(createStateResource(command));
+        component.openBescheidenDialogWithExistingDraft();
 
-      beforeEach(() => {
-        vorgangCommandService.bescheiden.mockReturnValue(comandStateResource$);
+        expect(ozgcloudDialogService.openWizard).not.toHaveBeenCalled();
       });
 
-      it('should call vorgangCommandService.bescheiden', () => {
-        component.bescheiden();
+      it('should not open wizard on loading bescheid draft', () => {
+        bescheidService.getBescheidDraftIfExists.mockReturnValue(
+          of({ ...createStateResource(createBescheidResource()), loading: true }),
+        );
+
+        component.openBescheidenDialogWithExistingDraft();
 
-        expect(vorgangCommandService.bescheiden).toHaveBeenCalled();
+        expect(ozgcloudDialogService.openWizard).not.toHaveBeenCalled();
       });
+    });
 
-      it('should assign response', () => {
-        component.commandStateResource$ = of(createEmptyStateResource<CommandResource>());
+    describe('openDialog', () => {
+      const bescheidDraftResource: BescheidResource = createBescheidResource();
+      const bescheidDraftStateResource: StateResource<BescheidResource> = createStateResource(bescheidDraftResource);
+      const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource([
+        VorgangWithEingangLinkRel.BESCHEID_DRAFT,
+      ]);
 
-        component.bescheiden();
+      const dialogData: BescheidenDialogData = {
+        bescheidDraftResource: bescheidDraftResource,
+        vorgangWithEingangResource: vorgangWithEingangResource,
+      };
 
-        expect(component.commandStateResource$).toBe(comandStateResource$);
+      beforeEach(() => {
+        component.vorgang = vorgangWithEingangResource;
+        bescheidService.getBescheidDraftIfExists.mockReturnValue(of(bescheidDraftStateResource));
       });
-    });
-  });
 
-  describe('bescheiden icon button', () => {
-    beforeEach(() => {
-      component.showAsIconButton = true;
-      fixture.detectChanges();
+      it('should call ozgcloudDialogService.openWizard', () => {
+        component.openDialog(dialogData);
+
+        expect(ozgcloudDialogService.openWizard).toHaveBeenCalledWith(VorgangDetailBescheidenComponent, dialogData);
+      });
     });
 
-    it('should be hidden', () => {
-      component.vorgang = createVorgangWithEingangResource();
+    describe('handleBescheidWizardClosed', () => {
+      it('should reload current vorgang', () => {
+        component.handleBescheidWizardClosed({ reloadVorgang: true });
 
-      fixture.detectChanges();
-      const buttonElement = fixture.nativeElement.querySelector(bescheidenIconButton);
+        expect(vorgangService.reloadCurrentVorgang).toHaveBeenCalled();
+      });
 
-      expect(buttonElement).not.toBeInstanceOf(HTMLElement);
-    });
+      it('should not reload current vorgang', () => {
+        component.handleBescheidWizardClosed({ reloadVorgang: false });
 
-    it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]);
+        expect(vorgangService.reloadCurrentVorgang).not.toHaveBeenCalled();
+      });
 
-      fixture.detectChanges();
-      const buttonElement = fixture.nativeElement.querySelector(bescheidenIconButton);
+      it.each([null, undefined])(
+        'should not reload current vorgang if result nil',
+        (dialogResult: BescheidWizardDialogResult) => {
+          component.handleBescheidWizardClosed(dialogResult);
 
-      expect(buttonElement).toBeInstanceOf(HTMLElement);
+          expect(vorgangService.reloadCurrentVorgang).not.toHaveBeenCalled();
+        },
+      );
     });
   });
 
-  // TODO: Use this version after completed Bescheid refactoring and delete the other version below.
-  // describe('openBescheidenWizard', () => {
-  //   let dialogRefMock: DialogRefMock<BescheidWizardDialogResult>;
-  //
-  //   beforeEach(() => {
-  //     dialogRefMock = createDialogRefMock<BescheidWizardDialogResult>();
-  //     ozgcloudDialogService.openWizard.mockReturnValue(dialogRefMock);
-  //   });
-  //
-  //   it('should open wizard dialog', () => {
-  //     const vorgang = createVorgangWithEingangResource();
-  //     component.vorgang = vorgang;
-  //
-  //     component.openBescheidenWizard();
-  //
-  //     expect(ozgcloudDialogService.openWizard).toHaveBeenCalledWith(BescheidWizardContainerComponent, {
-  //       vorgangWithEingangResource: vorgang,
-  //     });
-  //   });
-  //
-  //   it('should handleBescheidWizardClosed', () => {
-  //     component.handleBescheidWizardClosed = jest.fn();
-  //     const dialogResult: BescheidWizardDialogResult = { reloadVorgang: true };
-  //     dialogRefMock.closed = of(dialogResult);
-  //
-  //     component.openBescheidenWizard();
-  //
-  //     expect(component.handleBescheidWizardClosed).toHaveBeenCalledWith(dialogResult);
-  //   });
-  // });
-
-  describe('openBescheidenWizard', () => {
-    it('should init', () => {
-      component.openBescheidenWizard();
-
-      expect(bescheidService.init).toBeCalled();
-    });
-
-    it('should open bescheiden dialog with existing draft', () => {
-      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEID_DRAFT]);
-      component.openBescheidenDialogWithExistingDraft = jest.fn();
+  describe('template', () => {
+    const state: StateResource<CommandResource> = createStateResource(createCommandResource());
 
-      component.openBescheidenWizard();
+    beforeEach(() => {
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]);
+      component.commandStateResource$ = of(state);
 
-      expect(component.openBescheidenDialogWithExistingDraft).toHaveBeenCalled();
+      fixture.detectChanges();
     });
 
-    it('should open bescheiden dialog with new draft', () => {
-      component.vorgang = createVorgangWithEingangResource();
-      component.openBescheidDialogWithNewDraft = jest.fn();
+    describe('bescheiden button', () => {
+      beforeEach(() => {
+        component.showAsIconButton = false;
+        fixture.detectChanges();
+      });
 
-      component.openBescheidenWizard();
+      it('should not exits', () => {
+        component.vorgang = createVorgangWithEingangResource();
 
-      expect(component.openBescheidDialogWithNewDraft).toHaveBeenCalled();
-    });
-  });
+        fixture.detectChanges();
 
-  describe('openBescheidDialogWithNewDraft', () => {
-    it('should open wizard', () => {
-      component.vorgang = createVorgangWithEingangResource();
-      component.openDialog = jest.fn();
+        notExistsAsHtmlElement(fixture, bescheidenButton);
+      });
 
-      component.openBescheidDialogWithNewDraft();
+      it('should exist with input', () => {
+        const button: ButtonWithSpinnerComponent = getElementComponentFromFixtureByCss(fixture, bescheidenButton);
 
-      expect(component.openDialog).toHaveBeenCalledWith({
-        vorgangWithEingangResource: component.vorgang,
-        bescheidDraftResource: null,
+        expect(button.stateResource).toBe(state);
       });
-    });
-  });
 
-  describe('openBescheidenDialogWithExistingDraft', () => {
-    const bescheidDraftResource: BescheidResource = createBescheidResource();
-    const bescheidDraftStateResource: StateResource<BescheidResource> = createStateResource(bescheidDraftResource);
-    const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource([
-      VorgangWithEingangLinkRel.BESCHEID_DRAFT,
-    ]);
+      it('should get "Bescheid" text', () => {
+        const button: ButtonWithSpinnerComponent = getMockComponent(fixture, ButtonWithSpinnerComponent);
+        expect(button.text).toBe('Bescheiden');
+      });
 
-    beforeEach(() => {
-      component.vorgang = vorgangWithEingangResource;
-      bescheidService.getBescheidDraftIfExists.mockReturnValue(of(bescheidDraftStateResource));
-    });
+      it('should get "Bescheiden fortsetzen" text', () => {
+        component.vorgang = createVorgangWithEingangResource([
+          VorgangWithEingangLinkRel.BESCHEIDEN,
+          VorgangWithEingangLinkRel.BESCHEID_DRAFT,
+        ]);
 
-    it('should open wizard if bescheid draft loaded', () => {
-      component.openBescheidenDialogWithExistingDraft();
+        fixture.detectChanges();
 
-      expect(ozgcloudDialogService.openWizard).toHaveBeenCalledWith(VorgangDetailBescheidenComponent, {
-        bescheidDraftResource,
-        vorgangWithEingangResource,
+        const button: ButtonWithSpinnerComponent = getMockComponent(fixture, ButtonWithSpinnerComponent);
+        expect(button.text).toBe('Bescheiden fortsetzen');
       });
-    });
 
-    it('should not open wizard if bescheid draft not loaded', () => {
-      bescheidService.getBescheidDraftIfExists.mockReturnValue(of(createEmptyStateResource()));
+      it('should call bescheiden on click', () => {
+        component.bescheiden = jest.fn();
 
-      component.openBescheidenDialogWithExistingDraft();
+        triggerEvent({ fixture, name: 'clickEmitter', elementSelector: bescheidenButton });
 
-      expect(ozgcloudDialogService.openWizard).not.toHaveBeenCalled();
+        expect(component.bescheiden).toHaveBeenCalled();
+      });
     });
 
-    it('should not open wizard on loading bescheid draft', () => {
-      bescheidService.getBescheidDraftIfExists.mockReturnValue(
-        of({ ...createStateResource(createBescheidResource()), loading: true }),
-      );
-
-      component.openBescheidenDialogWithExistingDraft();
+    describe('bescheiden icon button', () => {
+      beforeEach(() => {
+        component.showAsIconButton = true;
+        fixture.detectChanges();
+      });
 
-      expect(ozgcloudDialogService.openWizard).not.toHaveBeenCalled();
-    });
-  });
+      it('should not exist', () => {
+        component.vorgang = createVorgangWithEingangResource();
 
-  describe('openDialog', () => {
-    const bescheidDraftResource: BescheidResource = createBescheidResource();
-    const bescheidDraftStateResource: StateResource<BescheidResource> = createStateResource(bescheidDraftResource);
-    const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource([
-      VorgangWithEingangLinkRel.BESCHEID_DRAFT,
-    ]);
+        fixture.detectChanges();
 
-    const dialogData: BescheidenDialogData = {
-      bescheidDraftResource: bescheidDraftResource,
-      vorgangWithEingangResource: vorgangWithEingangResource,
-    };
+        notExistsAsHtmlElement(fixture, bescheidenIconButton);
+      });
 
-    beforeEach(() => {
-      component.vorgang = vorgangWithEingangResource;
-      bescheidService.getBescheidDraftIfExists.mockReturnValue(of(bescheidDraftStateResource));
-    });
+      it('should exist with input', () => {
+        const button: ButtonWithSpinnerComponent = getElementComponentFromFixtureByCss(fixture, bescheidenIconButton);
 
-    it('should call ozgcloudDialogService.openWizard', () => {
-      component.openDialog(dialogData);
+        expect(button.stateResource).toBe(state);
+      });
 
-      expect(ozgcloudDialogService.openWizard).toHaveBeenCalledWith(VorgangDetailBescheidenComponent, dialogData);
-    });
-  });
+      it('should have "Vorgang bescheiden" tooltip', () => {
+        tooltipExistsWithText(fixture, bescheidenIconButton, 'Vorgang bescheiden');
+      });
 
-  describe('handleBescheidWizardClosed', () => {
-    it('should reload current vorgang', () => {
-      component.handleBescheidWizardClosed({ reloadVorgang: true });
+      it('should have "Vorgang bescheiden fortsetzen" tooltip', () => {
+        component.vorgang = createVorgangWithEingangResource([
+          VorgangWithEingangLinkRel.BESCHEIDEN,
+          VorgangWithEingangLinkRel.BESCHEID_DRAFT,
+        ]);
 
-      expect(vorgangService.reloadCurrentVorgang).toHaveBeenCalled();
-    });
+        fixture.detectChanges();
 
-    it('should not reload current vorgang', () => {
-      component.handleBescheidWizardClosed({ reloadVorgang: false });
+        tooltipExistsWithText(fixture, bescheidenIconButton, 'Vorgang bescheiden fortsetzen');
+      });
 
-      expect(vorgangService.reloadCurrentVorgang).not.toHaveBeenCalled();
-    });
+      it('should call bescheiden on click', () => {
+        component.bescheiden = jest.fn();
 
-    it.each([null, undefined])('should not reload current vorgang if result nil', (dialogResult: BescheidWizardDialogResult) => {
-      component.handleBescheidWizardClosed(dialogResult);
+        triggerEvent({ fixture, name: 'clickEmitter', elementSelector: bescheidenIconButton });
 
-      expect(vorgangService.reloadCurrentVorgang).not.toHaveBeenCalled();
+        expect(component.bescheiden).toHaveBeenCalled();
+      });
     });
   });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts
index da2e171f7dc750cca571735eb186474249cb8722..de431e7c593b4e719514f917e3325e41fab3c644 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts
@@ -40,7 +40,7 @@ import { VorgangDetailBescheidenComponent } from '../../vorgang-detail-page/vorg
 @Component({
   selector: 'alfa-bescheiden-button',
   templateUrl: './bescheiden-button.component.html',
-  styleUrls: ['./bescheiden-button.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class BescheidenButtonComponent implements OnInit {
   @Input() vorgang: VorgangWithEingangResource;
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.html
index dc55d5bb092594f4a3b653b9d14844b1f78ff6cc..784ddfbbf353822e8bd5fc423d63a1f86f9f607e 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.html
@@ -23,24 +23,27 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="vorgang | hasLink: linkRel.VERWERFEN">
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton"
-    data-test-id="verwerfen-button"
-    text="Verwerfen"
-    svgIcon="discard_document"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="verwerfen()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
-
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="verwerfen-icon-button"
-    svgIcon="discard_document"
-    toolTip="Vorgang verwerfen"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="verwerfen()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+@if (vorgang | hasLink: linkRel.VERWERFEN) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="verwerfen-icon-button"
+      tooltip="Vorgang verwerfen"
+      variant="ghost"
+      size="fit"
+      (clickEmitter)="verwerfen()"
+    >
+      <ods-discard-vorgang-icon icon class="fill-text" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="verwerfen-button"
+      text="Verwerfen"
+      variant="outline"
+      (clickEmitter)="verwerfen()"
+    >
+      <ods-discard-vorgang-icon icon />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.scss b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.spec.ts
index 31872b928978aa47af6c9fbdfcb9ee8e6edd916d..75b739a2301a0447895e66b8f026c494bd0fb49e 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.spec.ts
@@ -21,16 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
 import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { DiscardVorgangIconComponent } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
-import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
@@ -40,8 +38,8 @@ describe('VerwerfenButtonComponent', () => {
   let component: VerwerfenButtonComponent;
   let fixture: ComponentFixture<VerwerfenButtonComponent>;
 
-  const verwerfenButton: string = getDataTestIdOf('verwerfen-button');
-  const verwerfenIconButton: string = getDataTestIdOf('verwerfen-icon-button');
+  const verwerfenButton: string = getDataTestIdAttributeOf('verwerfen-button');
+  const verwerfenIconButton: string = getDataTestIdAttributeOf('verwerfen-icon-button');
 
   const vorgangCommandService = {
     ...mock(VorgangCommandService),
@@ -52,8 +50,8 @@ describe('VerwerfenButtonComponent', () => {
     await TestBed.configureTestingModule({
       declarations: [
         VerwerfenButtonComponent,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(DiscardVorgangIconComponent),
         HasLinkPipe,
       ],
       providers: [
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.ts
index ee468e5fb43efc53a703a566b85d67f9240a2150..6ec2487983098833e987522de19fd48f31fe5526 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.ts
@@ -21,28 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input, OnInit } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
-import {
-  VorgangCommandService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input, OnInit } from '@angular/core';
 import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'alfa-verwerfen-button',
   templateUrl: './verwerfen-button.component.html',
-  styleUrls: ['./verwerfen-button.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class VerwerfenButtonComponent implements OnInit {
   @Input() vorgang: VorgangWithEingangResource;
   @Input() showAsIconButton: boolean = false;
 
-  commandStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   readonly linkRel = VorgangWithEingangLinkRel;
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.html
index eb63ab7bc9a4a8729db650becda2de09be66447c..0e3bba543bfdd8404c10c1589b32b1a245e746ed 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.html
@@ -23,24 +23,27 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="vorgang | hasLink: linkRel.WIEDEREROEFFNEN">
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton"
-    data-test-id="wiedereroeffnen-button"
-    text="Wiedereröffnen"
-    icon="undo"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="wiedereroeffnen()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
-
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="wiedereroeffnen-icon-button"
-    icon="undo"
-    toolTip="Vorgang wiedereröffnen"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="wiedereroeffnen()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+@if (vorgang | hasLink: linkRel.WIEDEREROEFFNEN) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="wiedereroeffnen-icon-button"
+      tooltip="Vorgang wiedereröffnen"
+      variant="ghost"
+      size="fit"
+      (clickEmitter)="wiedereroeffnen()"
+    >
+      <ods-undo-icon icon class="fill-text" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="wiedereroeffnen-button"
+      text="Wiedereröffnen"
+      variant="outline"
+      (clickEmitter)="wiedereroeffnen()"
+    >
+      <ods-undo-icon icon />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.scss b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.spec.ts
index a03ee7234ef005811d682881d886b2db15a5e1e9..a52280005233c965f956010d03a99c87be471fd3 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.spec.ts
@@ -21,16 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
 import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { UndoIconComponent } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
-import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
@@ -39,8 +37,8 @@ import { WiedereroeffnenButtonComponent } from './wiedereroeffnen-button.compone
 describe('WiedereroeffnenButtonComponent', () => {
   let component: WiedereroeffnenButtonComponent;
   let fixture: ComponentFixture<WiedereroeffnenButtonComponent>;
-  const wiedereroeffnenButton: string = getDataTestIdOf('wiedereroeffnen-button');
-  const wiedereroeffnenIconButton: string = getDataTestIdOf('wiedereroeffnen-icon-button');
+  const wiedereroeffnenButton: string = getDataTestIdAttributeOf('wiedereroeffnen-button');
+  const wiedereroeffnenIconButton: string = getDataTestIdAttributeOf('wiedereroeffnen-icon-button');
 
   const vorgangCommandService = {
     ...mock(VorgangCommandService),
@@ -52,8 +50,8 @@ describe('WiedereroeffnenButtonComponent', () => {
       declarations: [
         WiedereroeffnenButtonComponent,
         HasLinkPipe,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(UndoIconComponent),
       ],
       providers: [
         {
@@ -106,9 +104,7 @@ describe('WiedereroeffnenButtonComponent', () => {
     });
 
     it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.WIEDEREROEFFNEN,
-      ]);
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.WIEDEREROEFFNEN]);
 
       fixture.detectChanges();
       const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenButton);
@@ -133,9 +129,7 @@ describe('WiedereroeffnenButtonComponent', () => {
     });
 
     it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.WIEDEREROEFFNEN,
-      ]);
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.WIEDEREROEFFNEN]);
 
       fixture.detectChanges();
       const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenIconButton);
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.ts
index 4887a53a3df75179586f7237664567fd567f62fa..4300791a17b4503b988abf4bda1f88839aaaea90 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.ts
@@ -21,28 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input, OnInit } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
-import {
-  VorgangCommandService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input, OnInit } from '@angular/core';
 import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'alfa-wiedereroeffnen-button',
   templateUrl: './wiedereroeffnen-button.component.html',
-  styleUrls: ['./wiedereroeffnen-button.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class WiedereroeffnenButtonComponent implements OnInit {
   @Input() vorgang: VorgangWithEingangResource;
   @Input() showAsIconButton: boolean = false;
 
-  commandStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   readonly linkRel = VorgangWithEingangLinkRel;
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.html
index fde254e2a246f1447dce121a6d832434f5d9f005..d2ac600887aa0ea31937090134e620cdc2c92b0b 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.html
@@ -23,24 +23,27 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="vorgang | hasLink: linkRel.ZURUECKHOLEN">
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton"
-    data-test-id="zurueckholen-button"
-    text="Zurückholen"
-    icon="undo"
-    [stateResource]="commandStateResource$ | async"
-    (click)="zurueckholen()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
-
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="zurueckholen-icon-button"
-    icon="undo"
-    toolTip="Vorgang zurückholen"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="zurueckholen()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+@if (vorgang | hasLink: linkRel.ZURUECKHOLEN) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="zurueckholen-icon-button"
+      variant="ghost"
+      size="fit"
+      tooltip="Vorgang zurückholen"
+      (clickEmitter)="zurueckholen()"
+    >
+      <ods-undo-icon icon class="fill-text" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="zurueckholen-button"
+      text="Zurückholen"
+      variant="outline"
+      (clickEmitter)="zurueckholen()"
+    >
+      <ods-undo-icon icon />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.scss b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.spec.ts
index 8d11e65b2d0745cfe546bcdef7254a2da3952b1e..f91b5423f7f409c523592849dacc6c52126e5c92 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.spec.ts
@@ -21,16 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
 import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { UndoIconComponent } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
-import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
@@ -40,8 +38,8 @@ describe('ZurueckholenButtonComponent', () => {
   let component: ZurueckholenButtonComponent;
   let fixture: ComponentFixture<ZurueckholenButtonComponent>;
 
-  const zurueckholenButton: string = getDataTestIdOf('zurueckholen-button');
-  const zurueckholenIconButton: string = getDataTestIdOf('zurueckholen-icon-button');
+  const zurueckholenButton: string = getDataTestIdAttributeOf('zurueckholen-button');
+  const zurueckholenIconButton: string = getDataTestIdAttributeOf('zurueckholen-icon-button');
 
   const vorgangCommandService = {
     ...mock(VorgangCommandService),
@@ -53,8 +51,8 @@ describe('ZurueckholenButtonComponent', () => {
       declarations: [
         ZurueckholenButtonComponent,
         HasLinkPipe,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(UndoIconComponent),
       ],
       providers: [
         {
@@ -107,9 +105,7 @@ describe('ZurueckholenButtonComponent', () => {
     });
 
     it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.ZURUECKHOLEN,
-      ]);
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ZURUECKHOLEN]);
 
       fixture.detectChanges();
       const buttonElement = fixture.nativeElement.querySelector(zurueckholenButton);
@@ -134,9 +130,7 @@ describe('ZurueckholenButtonComponent', () => {
     });
 
     it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.ZURUECKHOLEN,
-      ]);
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ZURUECKHOLEN]);
 
       fixture.detectChanges();
       const buttonElement = fixture.nativeElement.querySelector(zurueckholenIconButton);
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.ts
index e32881b215ed1677c0bf79d5c9a8782f0944f102..37eeb40bb4c221515a712993c0c899f68243a717 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.ts
@@ -21,28 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input, OnInit } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
-import {
-  VorgangCommandService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input, OnInit } from '@angular/core';
 import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'alfa-zurueckholen-button',
   templateUrl: './zurueckholen-button.component.html',
-  styleUrls: ['./zurueckholen-button.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class ZurueckholenButtonComponent implements OnInit {
   @Input() vorgang: VorgangWithEingangResource;
   @Input() showAsIconButton: boolean = false;
 
-  commandStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   readonly linkRel = VorgangWithEingangLinkRel;
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.html
index 0461b518cd1c340e61d6a679a771bad43ee9bffa..843b20963ed5baf2cf596165d889f9d4b405e232 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.html
@@ -23,24 +23,28 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="vorgang | hasLink: linkRel.ZURUECKSTELLEN">
-  <ozgcloud-stroked-button-with-spinner
-    *ngIf="!showAsIconButton"
-    data-test-id="zurueckstellen-button"
-    text="Zurückstellen"
-    icon="undo"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="zurueckstellen()"
-  >
-  </ozgcloud-stroked-button-with-spinner>
 
-  <ozgcloud-icon-button-with-spinner
-    *ngIf="showAsIconButton"
-    data-test-id="zurueckstellen-icon-button"
-    icon="undo"
-    toolTip="Vorgang zurückstellen"
-    [stateResource]="commandStateResource$ | async"
-    (clickEmitter)="zurueckstellen()"
-  >
-  </ozgcloud-icon-button-with-spinner>
-</ng-container>
+@if (vorgang | hasLink: linkRel.ZURUECKSTELLEN) {
+  @if (showAsIconButton) {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="zurueckstellen-icon-button"
+      tooltip="Vorgang zurückstellen"
+      variant="ghost"
+      size="fit"
+      (clickEmitter)="zurueckstellen()"
+    >
+      <ods-undo-icon icon class="fill-text" />
+    </ods-button-with-spinner>
+  } @else {
+    <ods-button-with-spinner
+      [stateResource]="commandStateResource$ | async"
+      dataTestId="zurueckstellen-button"
+      text="Zurückstellen"
+      variant="outline"
+      (clickEmitter)="zurueckstellen()"
+    >
+      <ods-undo-icon icon />
+    </ods-button-with-spinner>
+  }
+}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.scss b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.spec.ts
index 1b18ad639390f3b10c12c9ed964299a51edaa7cb..4f9a74edc4eff2593b3cea73015e57f11e0f18a9 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.spec.ts
@@ -21,16 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
 import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { UndoIconComponent } from '@ods/system';
 import { createCommandResource } from 'libs/command-shared/test/command';
-import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
@@ -40,8 +38,8 @@ describe('ZurueckstellenButtonComponent', () => {
   let component: ZurueckstellenButtonComponent;
   let fixture: ComponentFixture<ZurueckstellenButtonComponent>;
 
-  const zurueckstellenButton: string = getDataTestIdOf('zurueckstellen-button');
-  const zurueckstellenIconButton: string = getDataTestIdOf('zurueckstellen-icon-button');
+  const zurueckstellenButton: string = getDataTestIdAttributeOf('zurueckstellen-button');
+  const zurueckstellenIconButton: string = getDataTestIdAttributeOf('zurueckstellen-icon-button');
 
   const vorgangCommandService = {
     ...mock(VorgangCommandService),
@@ -53,8 +51,8 @@ describe('ZurueckstellenButtonComponent', () => {
       declarations: [
         ZurueckstellenButtonComponent,
         HasLinkPipe,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(UndoIconComponent),
       ],
       providers: [
         {
@@ -107,9 +105,7 @@ describe('ZurueckstellenButtonComponent', () => {
     });
 
     it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.ZURUECKSTELLEN,
-      ]);
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ZURUECKSTELLEN]);
 
       fixture.detectChanges();
       const buttonElement = fixture.nativeElement.querySelector(zurueckstellenButton);
@@ -134,9 +130,7 @@ describe('ZurueckstellenButtonComponent', () => {
     });
 
     it('should be visible', () => {
-      component.vorgang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.ZURUECKSTELLEN,
-      ]);
+      component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ZURUECKSTELLEN]);
 
       fixture.detectChanges();
       const buttonElement = fixture.nativeElement.querySelector(zurueckstellenIconButton);
diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.ts
index 5ee0685b2df000c923589f6550790a82f2ff0739..3c0393503ce0b44a9c83a14b3339a13f2e600671 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.ts
@@ -21,28 +21,22 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input, OnInit } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
-import {
-  VorgangCommandService,
-  VorgangWithEingangLinkRel,
-  VorgangWithEingangResource,
-} from '@alfa-client/vorgang-shared';
+import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input, OnInit } from '@angular/core';
 import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'alfa-zurueckstellen-button',
   templateUrl: './zurueckstellen-button.component.html',
-  styleUrls: ['./zurueckstellen-button.component.scss'],
+  styles: [':host {@apply empty:hidden}'],
 })
 export class ZurueckstellenButtonComponent implements OnInit {
   @Input() vorgang: VorgangWithEingangResource;
   @Input() showAsIconButton: boolean = false;
 
-  commandStateResource$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   readonly linkRel = VorgangWithEingangLinkRel;
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.html
index 2505c2406ef82222f83d015924f65bc53cdfe922..7170a1ee9d6a52391ff3841614a4dff0a9cb4171 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.html
@@ -23,62 +23,26 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<alfa-annehmen-button
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-annehmen-button>
-<alfa-zurueckholen-button
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-zurueckholen-button>
-<alfa-bearbeiten-button
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-bearbeiten-button>
-<alfa-bescheiden-button
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-bescheiden-button>
-<alfa-zurueckstellen-button
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-zurueckstellen-button>
-<alfa-abschliessen-button
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-abschliessen-button>
-<alfa-verwerfen-button
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-verwerfen-button>
-<alfa-wiedereroeffnen-button
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-wiedereroeffnen-button>
+<alfa-annehmen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-zurueckholen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-bearbeiten-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-bescheiden-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-zurueckstellen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-abschliessen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-verwerfen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-wiedereroeffnen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
 <!-- TODO Anhand des Links Library dynamisch laden -->
-<alfa-loeschen-anfordern-button-container
-  *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.LOESCHEN_ANFORDERN"
-  data-test-id="loeschen-anfordern-icon-button-container"
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
->
-</alfa-loeschen-anfordern-button-container>
-<alfa-endgueltig-loeschen-button-container
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-endgueltig-loeschen-button-container>
-<alfa-loesch-anforderung-zuruecknehmen-button-container
-  [showAsIconButton]="showAsIconButton"
-></alfa-loesch-anforderung-zuruecknehmen-button-container>
+@if (vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.LOESCHEN_ANFORDERN) {
+  <alfa-loeschen-anfordern-button-container
+    data-test-id="loeschen-anfordern-icon-button-container"
+    [showAsIconButton]="showAsIconButton"
+    [vorgang]="vorgangWithEingang"
+  />
+}
+<alfa-endgueltig-loeschen-button-container [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-loesch-anforderung-zuruecknehmen-button-container [showAsIconButton]="showAsIconButton" />
 <!--  -->
-<alfa-create-wiedervorlage-button-container
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-create-wiedervorlage-button-container>
-<alfa-assign-user-profile-button-container
-  [vorgang]="vorgangWithEingang"
-></alfa-assign-user-profile-button-container>
-<alfa-postfach-mail-button-container
-  [showAsIconButton]="showAsIconButton"
-  [vorgang]="vorgangWithEingang"
-></alfa-postfach-mail-button-container>
+<alfa-create-wiedervorlage-button-container [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-assign-user-profile-button-container [vorgang]="vorgangWithEingang" />
+<alfa-postfach-mail-button-container [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang" />
+<alfa-forward-by-ozgcloud-button-container [vorgangWithEingang]="vorgangWithEingang" [showAsIconButton]="showAsIconButton" />
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.spec.ts
index e5e841336b1f6469c1c6014cfe777975dc339bec..b8c3aed662cf6e6034a2a80d3eb99bd13472e235 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.spec.ts
@@ -21,13 +21,18 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { EndgueltigLoeschenButtonContainerComponent, LoeschAnforderungZuruecknehmenButtonContainerComponent, LoeschenAnfordernButtonContainerComponent } from '@alfa-client/loesch-anforderung';
+import { ForwardByOzgcloudButtonContainerComponent } from '@alfa-client/forwarding';
+import {
+  EndgueltigLoeschenButtonContainerComponent,
+  LoeschAnforderungZuruecknehmenButtonContainerComponent,
+  LoeschenAnfordernButtonContainerComponent,
+} from '@alfa-client/loesch-anforderung';
 import { PostfachMailButtonContainerComponent } from '@alfa-client/postfach';
 import { HasLinkPipe } from '@alfa-client/tech-shared';
-import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { existsAsHtmlElement, getMockComponent, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { IconButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { AssignUserProfileButtonContainerComponent } from '@alfa-client/user-profile';
-import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { CreateWiedervorlageButtonContainerComponent } from '@alfa-client/wiedervorlage';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
@@ -47,11 +52,11 @@ describe('VorgangDetailActionButtonsComponent', () => {
   let component: VorgangDetailActionButtonsComponent;
   let fixture: ComponentFixture<VorgangDetailActionButtonsComponent>;
 
-  const loeschenAnfordernIconButtonContainer: string = getDataTestIdOf(
-    'loeschen-anfordern-icon-button-container',
-  );
+  const loeschenAnfordernIconButtonContainer: string = getDataTestIdOf('loeschen-anfordern-icon-button-container');
   const createBescheidButtonContainer: string = getDataTestIdOf('create-bescheid-button-container');
 
+  const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource();
+
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [
@@ -72,6 +77,7 @@ describe('VorgangDetailActionButtonsComponent', () => {
         MockComponent(LoeschenAnfordernButtonContainerComponent),
         MockComponent(EndgueltigLoeschenButtonContainerComponent),
         MockComponent(LoeschAnforderungZuruecknehmenButtonContainerComponent),
+        MockComponent(ForwardByOzgcloudButtonContainerComponent),
       ],
     });
   });
@@ -88,16 +94,14 @@ describe('VorgangDetailActionButtonsComponent', () => {
 
   describe('loeschenAnfordernIconButtonContainer', () => {
     it('should show if link is present', () => {
-      component.vorgangWithEingang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN,
-      ]);
+      component.vorgangWithEingang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN]);
       fixture.detectChanges();
 
       existsAsHtmlElement(fixture, loeschenAnfordernIconButtonContainer);
     });
 
     it('should hide if link is not present', () => {
-      component.vorgangWithEingang = createVorgangWithEingangResource();
+      component.vorgangWithEingang = vorgangWithEingang;
       fixture.detectChanges();
 
       notExistsAsHtmlElement(fixture, loeschenAnfordernIconButtonContainer);
@@ -106,11 +110,24 @@ describe('VorgangDetailActionButtonsComponent', () => {
 
   describe('create bescheid button', () => {
     it('should hide if link not exists', () => {
-      component.vorgangWithEingang = createVorgangWithEingangResource();
+      component.vorgangWithEingang = vorgangWithEingang;
 
       fixture.detectChanges();
 
       notExistsAsHtmlElement(fixture, createBescheidButtonContainer);
     });
   });
+
+  it('forward button should be called', () => {
+    component.vorgangWithEingang = vorgangWithEingang;
+
+    fixture.detectChanges();
+
+    const button: ForwardByOzgcloudButtonContainerComponent = getMockComponent(
+      fixture,
+      ForwardByOzgcloudButtonContainerComponent,
+    );
+    expect(button.vorgangWithEingang).toBe(vorgangWithEingang);
+    expect(button.showAsIconButton).toBeTruthy();
+  });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.ts
index 1d37f1a177fc1f508ef9fdaf3730c6d3173577b0..d6eabde2e9b9ddc75bcea31cdde52062abf8e114 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.ts
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input } from '@angular/core';
 
 @Component({
   selector: 'alfa-vorgang-detail-action-buttons',
   templateUrl: './vorgang-detail-action-buttons.component.html',
-  styleUrls: ['./vorgang-detail-action-buttons.component.scss'],
+  styles: [':host {@apply flex grow gap-0.5}'],
 })
 export class VorgangDetailActionButtonsComponent {
   @Input() vorgangWithEingang: VorgangWithEingangResource;
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.html
index 9c2c2212dcb045afb9125480829cbcf2615b6418..772fdbd05969b74f6fe626e05d5b74123f595f02 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.html
@@ -35,8 +35,11 @@
         data-test-id="vorgang-detail-header"
       ></alfa-vorgang-detail-header>
 
+
       <div class="section one-column">
-        <alfa-vorgang-detail-formular-daten [vorgangWithEingang]="vorgangResource"></alfa-vorgang-detail-formular-daten>
+        <alfa-vorgang-detail-formular-buttons [vorgangWithEingang]="vorgangResource" />
+
+        <alfa-vorgang-detail-formular-daten [vorgangWithEingang]="vorgangResource" />
 
         <div *ngIf="vorgangResource | hasLink: vorgangWithEingangLinkRel.BESCHEIDE">
           <ozgcloud-expansion-panel headline="Bescheid" data-test-id="bescheid-expansion-panel">
@@ -44,8 +47,6 @@
             </alfa-bescheid-list-in-vorgang-container>
           </ozgcloud-expansion-panel>
         </div>
-
-        <alfa-vorgang-detail-formular-buttons [vorgangWithEingang]="vorgangResource"></alfa-vorgang-detail-formular-buttons>
       </div>
 
       <div class="section one-column" *ngIf="vorgangResource | hasLink: vorgangWithEingangLinkRel.COLLABORATIONS">
@@ -58,7 +59,7 @@
       </div>
 
       <div class="two-column">
-        <div class="section" *ngIf="vorgangResource | hasLink: vorgangWithEingangLinkRel.FORWARDING">
+        <div class="section" *ngIf="vorgangResource | hasLink: vorgangWithEingangLinkRel.FORWARD_BY_EMAIL">
           <alfa-vorgang-forwarding-container
             [vorgang]="vorgangResource"
             data-test-id="forwarding-container-in-vorgang"
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.spec.ts
index 523eb42b38c26693b767b3641926bb9e7f214fcd..79d55a0dd7c4b095933d59e78923e8e786ae86a2 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.spec.ts
@@ -192,7 +192,7 @@ describe('VorgangDetailAreaComponent', () => {
   describe('forwarding', () => {
     it('should be visible', () => {
       component.vorgangStateResource = createStateResource(
-        createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARDING]),
+        createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD_BY_EMAIL]),
       );
       fixture.detectChanges();
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.html
index 5da29c28cff8a38e689d9367ea2600bba70ec1aa..742a81193c28b8f3a3b199604b2ab1f36d8f5785 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.html
@@ -23,23 +23,18 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<alfa-annehmen-button [vorgang]="vorgangWithEingang"></alfa-annehmen-button>
-<alfa-zurueckholen-button [vorgang]="vorgangWithEingang"></alfa-zurueckholen-button>
-<alfa-verwerfen-button [vorgang]="vorgangWithEingang"></alfa-verwerfen-button>
-<alfa-bearbeiten-button [vorgang]="vorgangWithEingang"></alfa-bearbeiten-button>
-<alfa-bescheiden-button [vorgang]="vorgangWithEingang"></alfa-bescheiden-button>
-<alfa-zurueckstellen-button [vorgang]="vorgangWithEingang"></alfa-zurueckstellen-button>
-<alfa-abschliessen-button [vorgang]="vorgangWithEingang"></alfa-abschliessen-button>
-<alfa-wiedereroeffnen-button [vorgang]="vorgangWithEingang"></alfa-wiedereroeffnen-button>
+<alfa-annehmen-button [vorgang]="vorgangWithEingang" />
+<alfa-zurueckholen-button [vorgang]="vorgangWithEingang" />
+<alfa-verwerfen-button [vorgang]="vorgangWithEingang" />
+<alfa-bearbeiten-button [vorgang]="vorgangWithEingang" />
+<alfa-bescheiden-button [vorgang]="vorgangWithEingang" />
+<alfa-zurueckstellen-button [vorgang]="vorgangWithEingang" />
+<alfa-abschliessen-button [vorgang]="vorgangWithEingang" />
+<alfa-wiedereroeffnen-button [vorgang]="vorgangWithEingang" />
 <!-- TODO LoeschAnforderung dynamisch laden, wenn Link vorhanden -->
-<alfa-loeschen-anfordern-button-container
-  *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.LOESCHEN_ANFORDERN"
-  data-test-id="loeschen-anfordern-button-container"
-  [vorgang]="vorgangWithEingang"
->
-</alfa-loeschen-anfordern-button-container>
-<alfa-endgueltig-loeschen-button-container
-  [vorgang]="vorgangWithEingang"
-></alfa-endgueltig-loeschen-button-container>
-<alfa-loesch-anforderung-zuruecknehmen-button-container></alfa-loesch-anforderung-zuruecknehmen-button-container>
-<!--  -->
+@if (vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.LOESCHEN_ANFORDERN) {
+  <alfa-loeschen-anfordern-button-container data-test-id="loeschen-anfordern-button-container" [vorgang]="vorgangWithEingang" />
+}
+<alfa-endgueltig-loeschen-button-container [vorgang]="vorgangWithEingang" />
+<alfa-loesch-anforderung-zuruecknehmen-button-container />
+<alfa-forward-by-ozgcloud-button-container [vorgangWithEingang]="vorgangWithEingang" />
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.scss
deleted file mode 100644
index 9cd0cfd7b7d386af1ba5be1db18e12c240c9aa6d..0000000000000000000000000000000000000000
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
-:host {
-  margin-left: 48px;
-
-  ::ng-deep {
-    ozgcloud-stroked-button-with-spinner {
-      margin: 0 8px;
-    }
-  }
-}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.spec.ts
index b1060931119464b8bd531cee3d0728cb9d79eef1..4b16a16ee53c7fda49274e3002b8e111b8f93d30 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.spec.ts
@@ -21,16 +21,17 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ForwardByOzgcloudButtonContainerComponent } from '@alfa-client/forwarding';
 import {
   EndgueltigLoeschenButtonContainerComponent,
   LoeschAnforderungZuruecknehmenButtonContainerComponent,
   LoeschenAnfordernButtonContainerComponent,
 } from '@alfa-client/loesch-anforderung';
 import { HasLinkPipe } from '@alfa-client/tech-shared';
-import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { existsAsHtmlElement, getMockComponent, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
-import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared';
+import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
@@ -48,9 +49,9 @@ describe('VorgangDetailFormularButtonsComponent', () => {
   let component: VorgangDetailFormularButtonsComponent;
   let fixture: ComponentFixture<VorgangDetailFormularButtonsComponent>;
 
-  const loeschenAnfordernButtonContainer: string = getDataTestIdOf(
-    'loeschen-anfordern-button-container',
-  );
+  const loeschenAnfordernButtonContainer: string = getDataTestIdOf('loeschen-anfordern-button-container');
+
+  const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource();
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -69,6 +70,7 @@ describe('VorgangDetailFormularButtonsComponent', () => {
         MockComponent(LoeschenAnfordernButtonContainerComponent),
         MockComponent(EndgueltigLoeschenButtonContainerComponent),
         MockComponent(LoeschAnforderungZuruecknehmenButtonContainerComponent),
+        MockComponent(ForwardByOzgcloudButtonContainerComponent),
       ],
     });
   });
@@ -76,6 +78,7 @@ describe('VorgangDetailFormularButtonsComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(VorgangDetailFormularButtonsComponent);
     component = fixture.componentInstance;
+    component.vorgangWithEingang = vorgangWithEingang;
     fixture.detectChanges();
   });
 
@@ -85,19 +88,28 @@ describe('VorgangDetailFormularButtonsComponent', () => {
 
   describe('loeschenAnfordernButtonContainer', () => {
     it('should show if link is present', () => {
-      component.vorgangWithEingang = createVorgangWithEingangResource([
-        VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN,
-      ]);
+      component.vorgangWithEingang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN]);
       fixture.detectChanges();
 
       existsAsHtmlElement(fixture, loeschenAnfordernButtonContainer);
     });
 
     it('should hide if link is not present', () => {
-      component.vorgangWithEingang = createVorgangWithEingangResource();
+      component.vorgangWithEingang = vorgangWithEingang;
       fixture.detectChanges();
 
       notExistsAsHtmlElement(fixture, loeschenAnfordernButtonContainer);
     });
   });
+
+  it('forwarding button should be called', () => {
+    component.vorgangWithEingang = vorgangWithEingang;
+    fixture.detectChanges();
+
+    const button: ForwardByOzgcloudButtonContainerComponent = getMockComponent(
+      fixture,
+      ForwardByOzgcloudButtonContainerComponent,
+    );
+    expect(button.vorgangWithEingang).toBe(vorgangWithEingang);
+  });
 });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.ts
index af2afbb3748fd678239e158e63a672d63a88a63d..462a97addb4bde5e6017eaa58bc7a8b800d832a7 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.ts
@@ -21,13 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { Component, Input } from '@angular/core';
 
 @Component({
   selector: 'alfa-vorgang-detail-formular-buttons',
   templateUrl: './vorgang-detail-formular-buttons.component.html',
-  styleUrls: ['./vorgang-detail-formular-buttons.component.scss'],
+  styles: [':host {@apply mt-4 mb-6 ml-14 flex gap-4}'],
 })
 export class VorgangDetailFormularButtonsComponent {
   @Input() vorgangWithEingang: VorgangWithEingangResource;
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.html
index 86f3e7c9a0014a5b079b345cab3f07eeaa7c51ea..06d40e9f4dac876238cb2e0d262fc0502b34a3e2 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.html
@@ -48,7 +48,7 @@
       {{ vorgang.name }}
     </h2>
     <alfa-vorgang-nummer class="vorgang-nummer" [vorgang]="vorgang"></alfa-vorgang-nummer>
-    <div class="flex flex-1 flex-row gap-1">
+    <div class="flex flex-1 flex-row items-center gap-1">
       <div class="flex flex-shrink-0" [class.text-gray-400]="!hasAktenzeichen">
         <mat-icon svgIcon="az" style="width: 1.5rem; height: 1.5rem"></mat-icon>
       </div>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
index 1bb2d28821e61949927c8b436530a4743ab43323..27dd25492855e410c1ce03221a1b97da8fd67a77 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.formservice.ts
@@ -43,29 +43,13 @@ import {
 } from '@alfa-client/tech-shared';
 import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Injectable, OnDestroy } from '@angular/core';
-import {
-  FormControl,
-  UntypedFormArray,
-  UntypedFormBuilder,
-  UntypedFormControl,
-  UntypedFormGroup,
-} from '@angular/forms';
+import { FormControl, UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { Resource, ResourceUri, getUrl, hasLink } from '@ngxp/rest';
 import { isEmpty, isNil, isUndefined } from 'lodash-es';
-import {
-  BehaviorSubject,
-  Observable,
-  Subject,
-  Subscription,
-  combineLatest,
-  filter,
-  first,
-  map,
-  startWith,
-} from 'rxjs';
+import { BehaviorSubject, Observable, Subject, Subscription, combineLatest, filter, first, map, startWith } from 'rxjs';
 
 @Injectable()
-export class BescheidenFormService extends AbstractFormService implements OnDestroy {
+export class BescheidenFormService extends AbstractFormService<CommandResource> implements OnDestroy {
   static readonly FIELD_BESCHIEDEN_AM = 'beschiedenAm';
   static readonly FIELD_BEWILLIGT = 'bewilligt';
   static readonly FIELD_BESCHEID_DOCUMENT = 'bescheidDocument';
@@ -80,8 +64,7 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
 
   private readonly bescheidChanges$: BehaviorSubject<Bescheid>;
   private readonly fileDelete$: Subject<BinaryFileResource>;
-  private readonly showMissingBescheidDocumentError$: BehaviorSubject<boolean> =
-    new BehaviorSubject<boolean>(false);
+  private readonly showMissingBescheidDocumentError$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
 
   private readonly activeStep$: BehaviorSubject<number> = new BehaviorSubject(1);
   readonly sendByManual: BehaviorSubject<boolean> = new BehaviorSubject(false);
@@ -108,8 +91,8 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
   }
 
   subscribeToSendBy(): Subscription {
-    return this.form.controls[BescheidenFormService.FIELD_SEND_BY].valueChanges.subscribe(
-      (sendBy: BescheidSendBy) => this.updateSendByManual(sendBy),
+    return this.form.controls[BescheidenFormService.FIELD_SEND_BY].valueChanges.subscribe((sendBy: BescheidSendBy) =>
+      this.updateSendByManual(sendBy),
     );
   }
 
@@ -148,8 +131,7 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
       [BescheidenFormService.FIELD_BESCHIEDEN_AM]: bescheid.beschiedenAm,
       [BescheidenFormService.FIELD_BEWILLIGT]: String(bescheid.bewilligt),
       [BescheidenFormService.FIELD_BESCHEID_DOCUMENT]: bescheidDocumentUri,
-      [BescheidenFormService.FIELD_SEND_BY]:
-        isUndefined(bescheid.sendBy) ? BescheidSendBy.NACHRICHT : bescheid.sendBy,
+      [BescheidenFormService.FIELD_SEND_BY]: isUndefined(bescheid.sendBy) ? BescheidSendBy.NACHRICHT : bescheid.sendBy,
       [BescheidenFormService.FIELD_NACHRICHT_SUBJECT]: bescheid.nachrichtSubject,
       [BescheidenFormService.FIELD_NACHRICHT_TEXT]: bescheid.nachrichtText,
     });
@@ -183,7 +165,7 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
     return BescheidenFormService.FIELD_PATH_PREFIX;
   }
 
-  protected doSubmit(): Observable<StateResource<Resource>> {
+  protected doSubmit(): Observable<StateResource<CommandResource>> {
     if (this.isPatch() || this.bescheidService.existsBescheidDraft()) {
       return this.bescheidService.updateBescheid(this.getValue());
     } else {
@@ -193,9 +175,7 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
     }
   }
 
-  updateNachrichtOnSuccess(): (
-    source: Observable<StateResource<CommandResource>>,
-  ) => Observable<StateResource<CommandResource>> {
+  updateNachrichtOnSuccess(): (source: Observable<StateResource<CommandResource>>) => Observable<StateResource<CommandResource>> {
     return tapOnCommandSuccessfullyDone(() => {
       this.bescheidService
         .getBescheidDraft()
@@ -208,9 +188,7 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
   }
 
   public submitDraft(): Observable<StateResource<Resource>> {
-    return this.submit().pipe(
-      tapOnCommandSuccessfullyDone(() => this.bescheidService.reloadCurrentVorgang()),
-    );
+    return this.submit().pipe(tapOnCommandSuccessfullyDone(() => this.bescheidService.reloadCurrentVorgang()));
   }
 
   public getValue(): Bescheid {
@@ -234,9 +212,7 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
     return this.bescheidChanges$.asObservable();
   }
 
-  public setVorgangWithEingangResource(
-    vorgangWithEingangResource: VorgangWithEingangResource,
-  ): void {
+  public setVorgangWithEingangResource(vorgangWithEingangResource: VorgangWithEingangResource): void {
     this.vorgangWithEingangResource = vorgangWithEingangResource;
   }
 
@@ -309,13 +285,9 @@ export class BescheidenFormService extends AbstractFormService implements OnDest
   }
 
   public getShowMissingBescheidDocumentError(): Observable<boolean> {
-    return combineLatest([
-      this.showMissingBescheidDocumentError$.asObservable(),
-      this.getBescheidChanges(),
-    ]).pipe(
+    return combineLatest([this.showMissingBescheidDocumentError$.asObservable(), this.getBescheidChanges()]).pipe(
       map(
-        ([showMissingBescheidDocumentError, bescheid]) =>
-          showMissingBescheidDocumentError && isEmpty(bescheid.bescheidDocument),
+        ([showMissingBescheidDocumentError, bescheid]) => showMissingBescheidDocumentError && isEmpty(bescheid.bescheidDocument),
       ),
     );
   }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
index a492ccf47c93617fa147e745c33a50569ba51641..5b77ac192ea34a4479534bef624a6ba3e24bb3ac 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-result/vorgang-detail-bescheiden-result.component.ts
@@ -38,13 +38,11 @@ import {
 } from '@alfa-client/command-shared';
 import { createEmptyStateResource, isLoaded, StateResource } from '@alfa-client/tech-shared';
 import { Component, EventEmitter, OnInit, Output } from '@angular/core';
-import { hasLink, Resource } from '@ngxp/rest';
+import { hasLink } from '@ngxp/rest';
 import { BehaviorSubject, filter, map, Observable, of, OperatorFunction, tap } from 'rxjs';
 import { BescheidenFormService } from '../bescheiden.formservice';
 
-type sendBescheid = (
-  BescheidResource: BescheidResource,
-) => Observable<StateResource<CommandResource>>;
+type sendBescheid = (BescheidResource: BescheidResource) => Observable<StateResource<CommandResource>>;
 
 @Component({
   selector: 'alfa-vorgang-detail-bescheiden-result',
@@ -60,26 +58,19 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
   public bescheid$: Observable<Bescheid>;
   public sendByManual$: Observable<boolean>;
 
-  public bescheidDraftStateResource$: Observable<StateResource<BescheidResource>> = of(
-    createEmptyStateResource<BescheidResource>(),
-  );
-  public bescheidDocumentFile$: Observable<StateResource<BinaryFileResource>> = of(
-    createEmptyStateResource<BinaryFileResource>(),
-  );
-  public bescheidDocument$: Observable<StateResource<DocumentResource>> = of(
-    createEmptyStateResource<DocumentResource>(),
-  );
-  public saveAndSendInProgress$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  public bescheidDraftStateResource$: Observable<StateResource<BescheidResource>> =
+    of(createEmptyStateResource<BescheidResource>());
+  public bescheidDocumentFile$: Observable<StateResource<BinaryFileResource>> =
+    of(createEmptyStateResource<BinaryFileResource>());
+  public bescheidDocument$: Observable<StateResource<DocumentResource>> = of(createEmptyStateResource<DocumentResource>());
+  public saveAndSendInProgress$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
 
   public uploadBescheidDocumentInProgress$: Observable<UploadFileInProgress> = of({
     loading: false,
   });
 
-  public createBescheidDocumentInProgress$: Observable<StateResource<CommandResource>> = of(
-    createEmptyStateResource<CommandResource>(),
-  );
+  public createBescheidDocumentInProgress$: Observable<StateResource<CommandResource>> =
+    of(createEmptyStateResource<CommandResource>());
 
   public sendWithNachricht$: BehaviorSubject<StateResource<CommandResource>> = new BehaviorSubject(
     createEmptyStateResource<CommandResource>(),
@@ -99,10 +90,8 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
   ngOnInit(): void {
     this.bescheidDraftStateResource$ = this.bescheidService.getBescheidDraft();
     this.bescheidDocumentFile$ = this.bescheidService.getBescheidDocumentFile();
-    this.uploadBescheidDocumentInProgress$ =
-      this.bescheidService.getUploadBescheidDocumentInProgress();
-    this.createBescheidDocumentInProgress$ =
-      this.bescheidService.getCreateBescheidDocumentInProgress();
+    this.uploadBescheidDocumentInProgress$ = this.bescheidService.getUploadBescheidDocumentInProgress();
+    this.createBescheidDocumentInProgress$ = this.bescheidService.getCreateBescheidDocumentInProgress();
     this.bescheidDocument$ = this.bescheidService.getBescheidDocument();
 
     this.activeStep$ = this.getActiveStep();
@@ -111,9 +100,7 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
 
     this.canSave$ = this.bescheidDraftStateResource$.pipe(
       filter(isLoaded),
-      map((stateResource: StateResource<BescheidResource>) =>
-        hasLink(stateResource.resource, BescheidLinkRel.BESCHEIDEN),
-      ),
+      map((stateResource: StateResource<BescheidResource>) => hasLink(stateResource.resource, BescheidLinkRel.BESCHEIDEN)),
     );
     this.canSend$ = this.bescheidDraftStateResource$.pipe(
       filter(isLoaded),
@@ -125,9 +112,7 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
   }
 
   getActiveStep(): Observable<number> {
-    return this.formService
-      .getActiveStep()
-      .pipe(tap((step: number) => this.resetStateOnStepChange(step)));
+    return this.formService.getActiveStep().pipe(tap((step: number) => this.resetStateOnStepChange(step)));
   }
 
   getIsSendManually(): Observable<boolean> {
@@ -176,10 +161,7 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
     );
   }
 
-  doUpdateAndSend(
-    bescheidDraft: BescheidResource,
-    send: sendBescheid,
-  ): Observable<StateResource<CommandResource>> {
+  doUpdateAndSend(bescheidDraft: BescheidResource, send: sendBescheid): Observable<StateResource<CommandResource>> {
     return this.formService.submit(this.doSendAfterSuccessfullyUpdate(bescheidDraft, send)).pipe(
       tapOnCommandSuccessfullyDone((commandStateResource: StateResource<CommandResource>) => {
         if (this.isSendBescheidCommand(commandStateResource)) {
@@ -192,7 +174,7 @@ export class VorgangDetailBescheidenResultComponent implements OnInit {
   doSendAfterSuccessfullyUpdate(
     bescheidDraft: BescheidResource,
     send: sendBescheid,
-  ): OperatorFunction<StateResource<Resource>, StateResource<Resource>> {
+  ): OperatorFunction<StateResource<CommandResource>, StateResource<CommandResource>> {
     return switchMapCommandSuccessfullyDone(() => send(bescheidDraft));
   }
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.spec.ts
index c0c50286c433c3f46979dde35495922f968f0ecd..b976d702d642721c317985fad672a8fe7b94fd48 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden.component.spec.ts
@@ -130,7 +130,7 @@ describe('VorgangDetailBescheidenComponent', () => {
 
       component.ngOnInit();
 
-      expect(setVorgangWithEingangResource).toBeCalledWith(vorgangWithEingangResource);
+      expect(setVorgangWithEingangResource).toHaveBeenCalledWith(vorgangWithEingangResource);
     });
 
     it('should patch values', () => {
@@ -138,7 +138,7 @@ describe('VorgangDetailBescheidenComponent', () => {
 
       component.ngOnInit();
 
-      expect(patchValues).toBeCalledWith(bescheidDraftResource);
+      expect(patchValues).toHaveBeenCalledWith(bescheidDraftResource);
     });
 
     it('should call handleEscapeKey', () => {
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html
index e85d31cb74a4f5dec0cf658f42112affb3fa9a7a..adc18566dffdcfc1bed5d98bbf703be5b9d4ada9 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html
@@ -25,7 +25,7 @@
 -->
 <main *ngIf="vorgangStateResource$ | async as vorgangStateResource">
   <h1 class="sr-only">Details zum Vorgang</h1>
-  <ozgcloud-subnavigation class="mat-typography mat-app-background" data-test-id="subnavigation">
+  <ozgcloud-subnavigation class="flex gap-0.5 bg-background-100" data-test-id="subnavigation">
     <alfa-vorgang-detail-back-button-container></alfa-vorgang-detail-back-button-container>
     <ng-container *ngIf="vorgangStateResource.resource">
       <alfa-vorgang-detail-action-buttons
@@ -39,9 +39,7 @@
     </ng-container>
   </ozgcloud-subnavigation>
 
-  <div
-    class="l-scroll-area--full flex border-l border-r border-grayborder/30 dark:border-transparent"
-  >
+  <div class="l-scroll-area--full flex border-l border-r border-grayborder/30 dark:border-transparent">
     <alfa-vorgang-detail-area
       *ngIf="vorgangStateResource"
       [vorgangStateResource]="vorgangStateResource"
@@ -50,9 +48,5 @@
   </div>
 </main>
 
-<ozgcloud-progress-bar
-  [stateResource]="revokeCommandStateResource$ | async"
-></ozgcloud-progress-bar>
-<ozgcloud-spinner-transparency
-  [stateResource]="vorgangLoeschenCommandStateResource$ | async"
-></ozgcloud-spinner-transparency>
+<ozgcloud-progress-bar [stateResource]="revokeCommandStateResource$ | async"></ozgcloud-progress-bar>
+<ozgcloud-spinner-transparency [stateResource]="vorgangLoeschenCommandStateResource$ | async"></ozgcloud-spinner-transparency>
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
index 9c968357921c8978b4aa3441a22bc3434f98c732..32aba2314074dfd4c1db59679594e9cd00767f4e 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts
@@ -24,7 +24,7 @@
 import { BescheidModule } from '@alfa-client/bescheid';
 import { BinaryFileModule } from '@alfa-client/binary-file';
 import { CollaborationModule } from '@alfa-client/collaboration';
-import { ForwardingModule } from '@alfa-client/forwarding';
+import { ForwardByOzgcloudButtonContainerComponent, ForwardingModule } from '@alfa-client/forwarding';
 import { HistorieModule } from '@alfa-client/historie';
 import { KommentarModule } from '@alfa-client/kommentar';
 import { LoeschAnforderungModule } from '@alfa-client/loesch-anforderung';
@@ -57,10 +57,13 @@ import {
   BescheidUploadIconComponent,
   ButtonCardComponent,
   ButtonComponent,
+  CheckCircleIconComponent,
   CheckIconComponent,
   CloseIconComponent,
+  DiscardVorgangIconComponent,
   DropdownMenuComponent,
   DropdownMenuTextItemComponent,
+  EditIconComponent,
   ErrorMessageComponent,
   ExclamationIconComponent,
   FileIconComponent,
@@ -70,6 +73,8 @@ import {
   SendIconComponent,
   SpinnerIconComponent,
   StampIconComponent,
+  TooltipDirective,
+  UndoIconComponent,
 } from '@ods/system';
 import { AktenzeichenEditDialogComponent } from './aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component';
 import { AktenzeichenEditableComponent } from './aktenzeichen-editable/aktenzeichen-editable.component';
@@ -154,7 +159,9 @@ const routes: Routes = [
     RadioButtonCardComponent,
     ButtonComponent,
     ButtonCardComponent,
+    UndoIconComponent,
     CloseIconComponent,
+    EditIconComponent,
     ExclamationIconComponent,
     SaveIconComponent,
     SendIconComponent,
@@ -173,11 +180,16 @@ const routes: Routes = [
     ErrorMessageComponent,
     CollaborationModule,
     ArchiveIconComponent,
+    CheckCircleIconComponent,
     CheckIconComponent,
     DropdownMenuComponent,
     DropdownMenuTextItemComponent,
     MoreIconComponent,
     FileIconComponent,
+    ForwardByOzgcloudButtonContainerComponent,
+    TooltipDirective,
+    EditIconComponent,
+    DiscardVorgangIconComponent,
   ],
   declarations: [
     VorgangDetailPageComponent,
diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts
index 0d1bc4a5bceb917e806223ba1d7e986c9c9a6135..dc36503b5bfad9cf24da093b76846f480b92bac2 100644
--- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts
+++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts
@@ -195,7 +195,7 @@ describe('VorgangSearchComponent', () => {
 
       component.vorgangSearchPreviewList = vorgangList;
 
-      expect(component.buildSearchResultPreviewLabel).toBeCalledWith(vorgangList);
+      expect(component.buildSearchResultPreviewLabel).toHaveBeenCalledWith(vorgangList);
     });
 
     it('should set previewLabel', () => {
diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
index ed59d9c3e4d04166dab03b8d34d12510769f148e..81efa35cbd2e10c10c1b794af84518a289648e86 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts
@@ -49,7 +49,8 @@ export enum VorgangWithEingangLinkRel {
 
   ATTACHMENTS = 'attachments',
   FORWARD = 'forward',
-  FORWARDING = 'forwarding',
+  FORWARD_BY_EMAIL = 'forwardByEmail',
+  FORWARD_BY_OZGCLOUD = 'forwardByOzgCloud',
   PENDING_COMMANDS = 'pending-commands',
   ASSIGN = 'assign',
   REPRESENTATIONS = 'representations',
diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts
index ab918999111af08299caac6135e57299bea939b7..0aa3ead988609bc5416e593f13cfdf6e44bd8a6e 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts
@@ -84,13 +84,13 @@ describe('VorgangService', () => {
     it('should get vorgangWithEingang', () => {
       service.getVorgangWithEingang();
 
-      expect(facade.getVorgangWithEingang).toBeCalled();
+      expect(facade.getVorgangWithEingang).toHaveBeenCalled();
     });
 
     it('should get getApiRoot', () => {
       service.getVorgangWithEingang();
 
-      expect(apiRootService.getApiRoot).toBeCalled();
+      expect(apiRootService.getApiRoot).toHaveBeenCalled();
     });
 
     describe('initial', () => {
diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-archive-status/vorgang-archive-status.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-archive-status/vorgang-archive-status.component.html
index 8da0edfd4e7c0cce005e53e94a060b699dd6436f..4f426425898e3a46ad5e1735476cae2975baef1c 100644
--- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-archive-status/vorgang-archive-status.component.html
+++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-archive-status/vorgang-archive-status.component.html
@@ -1,4 +1,4 @@
-<div class="flex gap-1 items-center">
-  <ods-archive-icon class="fill-black"/>
+<div class="flex items-center gap-1">
+  <ods-archive-icon class="fill-text" />
   <span>in Archivierung</span>
 </div>
diff --git a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.html
index 6d922ec39dd485dd0b6a17332bbb9e54bb56e42e..71fb146636883062d7fc3759a4cd120df047aa2e 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.html
+++ b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.html
@@ -23,12 +23,15 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-icon-button-with-spinner
-  *ngIf="wiedervorlage | hasLink: linkRel.ERLEDIGEN"
-  data-test-id="erledigen-icon-button"
-  [stateResource]="erledigenCommand$ | async"
-  icon="check_circle_outline"
-  toolTip="Als erledigt markieren"
-  (clickEmitter)="erledigen()"
->
-</ozgcloud-icon-button-with-spinner>
+@if (wiedervorlage | hasLink: linkRel.ERLEDIGEN) {
+  <ods-button-with-spinner
+    dataTestId="erledigen-icon-button"
+    [stateResource]="erledigenCommand$ | async"
+    tooltip="Als erledigt markieren"
+    variant="ghost"
+    size="fit"
+    (clickEmitter)="erledigen()"
+  >
+    <ods-check-circle-icon icon class="fill-text" />
+  </ods-button-with-spinner>
+}
diff --git a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.scss b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.spec.ts
index f188bcdca8841e41ceedc80a94e90f486dde12bd..81eec1106509121cb069b014fe64ac1077d5e96e 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.spec.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.spec.ts
@@ -21,11 +21,13 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { HasLinkPipe } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import { IconButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { WiedervorlageLinkRel, WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { CheckCircleIconComponent } from '@ods/system';
+import { getDataTestIdAttributeOf } from 'libs/tech-shared/test/data-test';
 import { createWiedervorlageResource } from 'libs/wiedervorlage-shared/test/wiedervorlage';
 import { MockComponent } from 'ng-mocks';
 import { ErledigenButtonContainerComponent } from './erledigen-button-container.component';
@@ -34,7 +36,7 @@ describe('ErledigenButtonContainerComponent', () => {
   let component: ErledigenButtonContainerComponent;
   let fixture: ComponentFixture<ErledigenButtonContainerComponent>;
 
-  const erledigenIconButton = '[data-test-id="erledigen-icon-button"]';
+  const erledigenIconButton = getDataTestIdAttributeOf('erledigen-icon-button');
 
   const wiedervorlageService = mock(WiedervorlageService);
 
@@ -43,7 +45,8 @@ describe('ErledigenButtonContainerComponent', () => {
       declarations: [
         ErledigenButtonContainerComponent,
         HasLinkPipe,
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(CheckCircleIconComponent),
       ],
       providers: [
         {
diff --git a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.ts
index dbdb25d29bbe68859c054f7edb9feba3808094ca..bf8239542fac0e3343d4339104f67362265c94e0 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.ts
@@ -21,20 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource } from '@alfa-client/tech-shared';
-import {
-  WiedervorlageLinkRel,
-  WiedervorlageResource,
-  WiedervorlageService,
-} from '@alfa-client/wiedervorlage-shared';
+import { WiedervorlageLinkRel, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
+import { Component, Input } from '@angular/core';
 import { Observable } from 'rxjs';
 
 @Component({
   selector: 'alfa-erledigen-button-container',
   templateUrl: './erledigen-button-container.component.html',
-  styleUrls: ['./erledigen-button-container.component.scss'],
 })
 export class ErledigenButtonContainerComponent {
   @Input() wiedervorlage: WiedervorlageResource;
diff --git a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html
index a7dc7bca94b40caf7fd1b22d2eaa22251f9a491f..322b8313078161b76335fcbb5936987686522411 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html
+++ b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html
@@ -23,21 +23,24 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-stroked-button-with-spinner
-  *ngIf="!showAsIconButton"
-  text="Speichern"
-  data-test-id="speichern-button"
-  icon="save_alt"
-  [stateResource]="submitInProgress$ | async"
-  (clickEmitter)="submit()"
->
-</ozgcloud-stroked-button-with-spinner>
-
-<ozgcloud-icon-button-with-spinner
-  *ngIf="showAsIconButton"
-  icon="save_alt"
-  toolTip="Wiedervorlage speichern"
-  [stateResource]="submitInProgress$ | async"
-  (clickEmitter)="submit()"
->
-</ozgcloud-icon-button-with-spinner>
+@if (showAsIconButton) {
+  <ods-button-with-spinner
+    [stateResource]="submitInProgress$ | async"
+    tooltip="Wiedervorlage speichern"
+    variant="ghost"
+    size="fit"
+    (clickEmitter)="submit()"
+  >
+    <ods-save-icon icon class="fill-text" />
+  </ods-button-with-spinner>
+} @else {
+  <ods-button-with-spinner
+    data-test-id="speichern-button"
+    [stateResource]="submitInProgress$ | async"
+    text="Speichern"
+    variant="outline"
+    (clickEmitter)="submit()"
+  >
+    <ods-save-icon icon />
+  </ods-button-with-spinner>
+}
diff --git a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.scss b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.spec.ts
index 7b82b4c1d0ac9be2b4c4f83c6daf73babb28e779..5dfb7fa67a2f94ba32302be9866c2c8c5d0af972 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.spec.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.spec.ts
@@ -21,17 +21,16 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { ActivatedRoute } from '@angular/router';
 import { CommandResource } from '@alfa-client/command-shared';
 import { NavigationService } from '@alfa-client/navigation-shared';
 import { StateResource, createStateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
+import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ActivatedRoute } from '@angular/router';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { SaveIconComponent } from '@ods/system';
 import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel';
 import { createCommandResource } from 'libs/command-shared/test/command';
 import { MockComponent } from 'ng-mocks';
@@ -56,7 +55,8 @@ describe('SubmitWiedervorlageButtonComponent', () => {
       declarations: [
         SubmitWiedervorlageButtonComponent,
         MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(SaveIconComponent),
       ],
       providers: [
         {
diff --git a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.ts b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.ts
index c52f566030b0a72817104bf6ec2e932b2461b3ae..788e3229c23f99a1fe11f4d0b2c257e0bde00350 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.ts
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
-import { ActivatedRoute } from '@angular/router';
 import { CommandResource, isDone } from '@alfa-client/command-shared';
 import { NavigationService } from '@alfa-client/navigation-shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
+import { Component, Input } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
 import { Observable } from 'rxjs';
 import { filter, tap } from 'rxjs/operators';
 import { WiedervorlageFormService } from '../wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice';
@@ -34,7 +34,6 @@ import { WiedervorlageFormService } from '../wiedervorlage-page-container/wieder
 @Component({
   selector: 'alfa-submit-wiedervorlage-button',
   templateUrl: './submit-wiedervorlage-button.component.html',
-  styleUrls: ['./submit-wiedervorlage-button.component.scss'],
 })
 export class SubmitWiedervorlageButtonComponent {
   @Input() showAsIconButton: boolean = false;
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.html
index 06193fefe6ff8d95a7cf0963849af308238f29c6..12ccae7d16777c95b80eff8e1d266316f462e35f 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.html
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.html
@@ -23,12 +23,15 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ozgcloud-icon-button-with-spinner
-  *ngIf="wiedervorlage | hasLink: linkRel.WIEDEREROEFFNEN"
-  data-test-id="wiedereroeffnen-icon-button"
-  [stateResource]="wiedereroeffnenCommand$ | async"
-  icon="check_circle_outline"
-  toolTip="Als offen markieren"
-  (clickEmitter)="wiedereroeffnen()"
->
-</ozgcloud-icon-button-with-spinner>
+@if (wiedervorlage | hasLink: linkRel.WIEDEREROEFFNEN) {
+  <ods-button-with-spinner
+    data-test-id="wiedereroeffnen-icon-button"
+    [stateResource]="wiedereroeffnenCommand$ | async"
+    tooltip="Als offen markieren"
+    variant="ghost"
+    size="fit"
+    (clickEmitter)="wiedereroeffnen()"
+  >
+    <ods-check-circle-icon icon class="fill-text" />
+  </ods-button-with-spinner>
+}
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.scss
deleted file mode 100644
index 54c4f3eb8c92af93694c03cdf577fed23cf9f86b..0000000000000000000000000000000000000000
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
- * Ministerpräsidenten des Landes Schleswig-Holstein
- * Staatskanzlei
- * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
- *
- * Lizenziert unter der EUPL, Version 1.2 oder - sobald
- * diese von der Europäischen Kommission genehmigt wurden -
- * Folgeversionen der EUPL ("Lizenz");
- * Sie dürfen dieses Werk ausschließlich gemäß
- * dieser Lizenz nutzen.
- * Eine Kopie der Lizenz finden Sie hier:
- *
- * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Sofern nicht durch anwendbare Rechtsvorschriften
- * gefordert oder in schriftlicher Form vereinbart, wird
- * die unter der Lizenz verbreitete Software "so wie sie
- * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
- * ausdrücklich oder stillschweigend - verbreitet.
- * Die sprachspezifischen Genehmigungen und Beschränkungen
- * unter der Lizenz sind dem Lizenztext zu entnehmen.
- */
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.spec.ts
index efe689d7337ab4246faad52ac2e37a2b120f03d8..af8e1281a01dfdefb228d6011700b5cecd64f35b 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.spec.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.spec.ts
@@ -21,11 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { HasLinkPipe } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
-import { IconButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { WiedervorlageLinkRel, WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { CheckCircleIconComponent } from '@ods/system';
 import { createWiedervorlageResource } from 'libs/wiedervorlage-shared/test/wiedervorlage';
 import { MockComponent } from 'ng-mocks';
 import { WiedereroeffnenButtonContainerComponent } from './wiedereroeffnen-button-container.component';
@@ -43,7 +44,8 @@ describe('WiedereroeffnenButtonContainerComponent', () => {
       declarations: [
         WiedereroeffnenButtonContainerComponent,
         HasLinkPipe,
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(CheckCircleIconComponent),
       ],
       providers: [
         {
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.ts
index 0dd4c216a89a623bcf36493a243775c699fcd349..6c125a5636215c3120436e6d0cbabdf2e27aee41 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.ts
@@ -21,20 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { CommandResource } from '@alfa-client/command-shared';
 import { StateResource } from '@alfa-client/tech-shared';
-import {
-  WiedervorlageLinkRel,
-  WiedervorlageResource,
-  WiedervorlageService,
-} from '@alfa-client/wiedervorlage-shared';
+import { WiedervorlageLinkRel, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
+import { Component, Input } from '@angular/core';
 import { Observable } from 'rxjs';
 
 @Component({
   selector: 'alfa-wiedereroeffnen-button-container',
   templateUrl: './wiedereroeffnen-button-container.component.html',
-  styleUrls: ['./wiedereroeffnen-button-container.component.scss'],
 })
 export class WiedereroeffnenButtonContainerComponent {
   @Input() wiedervorlage: WiedervorlageResource;
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts
index b9593d70d1dd13e81b06f1d1d30855eb164bccd4..305ae85a3562debef815c485cc0820e6971e9139 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts
@@ -21,19 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { createStateResource, HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
 import { mock } from '@alfa-client/test-utils';
 import { VorgangResource } from '@alfa-client/vorgang-shared';
 import { WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
-import {
-  createVorgangResource,
-  createVorgangWithEingangResource,
-} from 'libs/vorgang-shared/test/vorgang';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang';
 import { MockComponent } from 'ng-mocks';
 import { WiedervorlageListInVorgangContainerComponent } from './wiedervorlage-list-in-vorgang-container.component';
 import { WiedervorlageListInVorgangComponent } from './wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component';
-import { KommentarListInVorgangContainerComponent } from '@alfa-client/kommentar';
 
 describe('WiedervorlageListInVorgangContainerComponent', () => {
   let component: WiedervorlageListInVorgangContainerComponent;
@@ -41,8 +37,7 @@ describe('WiedervorlageListInVorgangContainerComponent', () => {
 
   const wiedervorlageService = mock(WiedervorlageService);
 
-  const vorgangStateResource: StateResource<VorgangResource> =
-    createStateResource(createVorgangResource());
+  const vorgangStateResource: StateResource<VorgangResource> = createStateResource(createVorgangResource());
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -75,9 +70,7 @@ describe('WiedervorlageListInVorgangContainerComponent', () => {
     it('should call wiedervorlageService to get wiedervorlageList', () => {
       component.ngOnChanges();
 
-      expect(wiedervorlageService.getWiedervorlageListByGivenVorgang).toHaveBeenCalledWith(
-        vorgangStateResource.resource,
-      );
+      expect(wiedervorlageService.getWiedervorlageListByGivenVorgang).toHaveBeenCalledWith(vorgangStateResource.resource);
     });
 
     it('should call reloadWiedervorlageListOnVorgangReload', () => {
@@ -104,7 +97,7 @@ describe('WiedervorlageListInVorgangContainerComponent', () => {
 
       component.reloadWiedervorlageListOnVorgangReload();
 
-      expect(wiedervorlageService.setWiedervorlageListReload).toBeCalled();
+      expect(wiedervorlageService.setWiedervorlageListReload).toHaveBeenCalled();
     });
 
     it('should not call wiedervorlageService', () => {
@@ -115,7 +108,7 @@ describe('WiedervorlageListInVorgangContainerComponent', () => {
 
       component.reloadWiedervorlageListOnVorgangReload();
 
-      expect(wiedervorlageService.setWiedervorlageListReload).not.toBeCalled();
+      expect(wiedervorlageService.setWiedervorlageListReload).not.toHaveBeenCalled();
     });
   });
 });
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.html
index 0b30324ca0f9f0036d001b9b9fa6ac5cee062172..c37de121c882aeb26bbdb25b36ae69bc0ed11c37 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.html
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.html
@@ -23,28 +23,24 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ng-container *ngIf="wiedervorlageListStateResource?.resource as wiedervorlageListResource">
-  <div
-    class="create-button"
-    *ngIf="wiedervorlageListResource | hasLink: wiedervorlageListLinkRel.CREATE_WIEDERVORLAGE"
-  >
-    <a [routerLink]="'wiedervorlage/' + wiedervorlageRoute.NEW" tabindex="-1">
-      <ozgcloud-stroked-button-with-spinner
-        *ngIf="!showAsIconButton"
-        data-test-id="create-wiedervorlage"
-        class="create-button"
-        text="Wiedervorlage"
-        icon="add"
-      >
-      </ozgcloud-stroked-button-with-spinner>
 
-      <ozgcloud-icon-button-with-spinner
-        *ngIf="showAsIconButton"
-        data-test-id="create-wiedervorlage-icon-button"
-        icon="update"
-        toolTip="Wiedervorlage erstellen"
-      >
-      </ozgcloud-icon-button-with-spinner>
+@if (wiedervorlageListStateResource?.resource; as wiedervorlageListResource) {
+  @if (wiedervorlageListResource | hasLink: wiedervorlageListLinkRel.CREATE_WIEDERVORLAGE) {
+    <a [routerLink]="'wiedervorlage/' + wiedervorlageRoute.NEW" tabindex="-1">
+      @if (showAsIconButton) {
+        <ods-button-with-spinner
+          data-test-id="create-wiedervorlage-icon-button"
+          variant="ghost"
+          size="fit"
+          tooltip="Wiedervorlage erstellen"
+        >
+          <ods-update-icon icon class="fill-text" />
+        </ods-button-with-spinner>
+      } @else {
+        <ods-button-with-spinner data-test-id="create-wiedervorlage" text="Wiedervorlage" variant="outline">
+          <ods-plus-icon icon />
+        </ods-button-with-spinner>
+      }
     </a>
-  </div>
-</ng-container>
+  }
+}
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.spec.ts
index da0fc0842a61f704ba7569edf304fa5857313c0e..5060ed010141168e658dd40bbfde3dd6092bdbda 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.spec.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.spec.ts
@@ -21,14 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { RouterTestingModule } from '@angular/router/testing';
 import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared';
-import {
-  IconButtonWithSpinnerComponent,
-  OzgcloudStrokedButtonWithSpinnerComponent,
-} from '@alfa-client/ui';
 import { WiedervorlageListLinkRel } from '@alfa-client/wiedervorlage-shared';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { RouterTestingModule } from '@angular/router/testing';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import { PlusIconComponent, UpdateIconComponent } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { createWiedervorlageListResource } from 'libs/wiedervorlage-shared/test/wiedervorlage';
 import { MockComponent } from 'ng-mocks';
@@ -45,8 +43,9 @@ describe('WiedervorlageCreateButtonComponent', () => {
       declarations: [
         WiedervorlageCreateButtonComponent,
         HasLinkPipe,
-        MockComponent(OzgcloudStrokedButtonWithSpinnerComponent),
-        MockComponent(IconButtonWithSpinnerComponent),
+        MockComponent(ButtonWithSpinnerComponent),
+        MockComponent(PlusIconComponent),
+        MockComponent(UpdateIconComponent),
       ],
       imports: [RouterTestingModule],
     }).compileComponents();
@@ -55,9 +54,7 @@ describe('WiedervorlageCreateButtonComponent', () => {
   beforeEach(() => {
     fixture = TestBed.createComponent(WiedervorlageCreateButtonComponent);
     component = fixture.componentInstance;
-    component.wiedervorlageListStateResource = createStateResource(
-      createWiedervorlageListResource(),
-    );
+    component.wiedervorlageListStateResource = createStateResource(createWiedervorlageListResource());
     fixture.detectChanges();
   });
 
@@ -78,9 +75,7 @@ describe('WiedervorlageCreateButtonComponent', () => {
     });
 
     it('should be hidden', () => {
-      component.wiedervorlageListStateResource = createStateResource(
-        createWiedervorlageListResource(),
-      );
+      component.wiedervorlageListStateResource = createStateResource(createWiedervorlageListResource());
 
       fixture.detectChanges();
       const button = fixture.nativeElement.querySelector(wiedervorlageButton);
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.html
index fff741c94ebb789f2ef6e87190136fb5bd4cb4d3..4c97aef84295ae40f48c2f2d9b95a72ca7968c7a 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.html
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.html
@@ -24,8 +24,6 @@
 
 -->
 <ozgcloud-back-button linkTo="../.." label="zurück zur Detailseite"></ozgcloud-back-button>
-<alfa-erledigen-button-container [wiedervorlage]="wiedervorlage"></alfa-erledigen-button-container>
-<alfa-wiedereroeffnen-button-container
-  [wiedervorlage]="wiedervorlage"
-></alfa-wiedereroeffnen-button-container>
-<alfa-submit-wiedervorlage-button [showAsIconButton]="true"></alfa-submit-wiedervorlage-button>
+<alfa-erledigen-button-container [wiedervorlage]="wiedervorlage" />
+<alfa-wiedereroeffnen-button-container [wiedervorlage]="wiedervorlage" />
+<alfa-submit-wiedervorlage-button [showAsIconButton]="true" />
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.ts
index 27a6875dc4d5ef2dc967052ef48a7ab0a531ba16..e00cfcdeadedb3758bbafeede904f5e3a08c82c5 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.ts
@@ -21,13 +21,14 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Component, Input } from '@angular/core';
 import { WiedervorlageResource } from '@alfa-client/wiedervorlage-shared';
+import { Component, Input } from '@angular/core';
 
 @Component({
   selector: 'alfa-wiedervorlage-action-buttons',
   templateUrl: './wiedervorlage-action-buttons.component.html',
   styleUrls: ['./wiedervorlage-action-buttons.component.scss'],
+  styles: [':host {@apply flex}'],
 })
 export class WiedervorlageActionButtonsComponent {
   @Input() wiedervorlage: WiedervorlageResource;
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
index db163e29a62bcefcc36cbfb194216d82cdaaafe0..cd6824367cd32680c5f875f238a23ed0e135bd1e 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
@@ -21,24 +21,15 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable } from '@angular/core';
-import {
-  UntypedFormArray,
-  UntypedFormBuilder,
-  UntypedFormControl,
-  UntypedFormGroup,
-} from '@angular/forms';
-import {
-  AbstractFormService,
-  createFutureDate,
-  formatForDatabase,
-  StateResource,
-} from '@alfa-client/tech-shared';
+import { CommandResource } from '@alfa-client/command-shared';
+import { AbstractFormService, createFutureDate, formatForDatabase, StateResource } from '@alfa-client/tech-shared';
 import { Wiedervorlage, WiedervorlageService } from '@alfa-client/wiedervorlage-shared';
+import { Injectable } from '@angular/core';
+import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 import { Observable } from 'rxjs';
 
 @Injectable()
-export class WiedervorlageFormService extends AbstractFormService {
+export class WiedervorlageFormService extends AbstractFormService<CommandResource> {
   static readonly FIELD_BETREFF = 'betreff';
   static readonly FIELD_BESCHREIBUNG = 'beschreibung';
   static readonly FIELD_FRIST = 'frist';
@@ -66,7 +57,7 @@ export class WiedervorlageFormService extends AbstractFormService {
     return WiedervorlageFormService.FIELD_PATH_PREFIX;
   }
 
-  protected doSubmit(): Observable<StateResource<any>> {
+  protected doSubmit(): Observable<StateResource<CommandResource>> {
     if (this.isPatch()) {
       return this.wiedervorlageService.saveWiedervorlage(this.getSourceValue(), this.getValue());
     } else {
diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts
index fec88f242f4f485bf156ef60e5fe897c210b0f59..7729ab5f2f68770e3b6e2e850fc9279f3a731406 100644
--- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts
+++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts
@@ -30,7 +30,14 @@ import { VorgangSharedUiModule } from '@alfa-client/vorgang-shared-ui';
 import { CommonModule, DatePipe } from '@angular/common';
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
-import { TooltipDirective } from '@ods/system';
+import { ButtonWithSpinnerComponent } from '@ods/component';
+import {
+  CheckCircleIconComponent,
+  PlusIconComponent,
+  SaveIconComponent,
+  TooltipDirective,
+  UpdateIconComponent,
+} from '@ods/system';
 import { CreateWiedervorlageButtonContainerComponent } from './create-wiedervorlage-button-container/create-wiedervorlage-button-container.component';
 import { ErledigenButtonContainerComponent } from './erledigen-button-container/erledigen-button-container.component';
 import { SubmitWiedervorlageButtonComponent } from './submit-wiedervorlage-button/submit-wiedervorlage-button.component';
@@ -70,7 +77,12 @@ const routes: Routes = [
     VorgangSharedUiModule,
     BinaryFileModule,
     UserProfileModule,
+    ButtonWithSpinnerComponent,
     TooltipDirective,
+    UpdateIconComponent,
+    PlusIconComponent,
+    CheckCircleIconComponent,
+    SaveIconComponent,
   ],
   declarations: [
     WiedervorlagePageComponent,
diff --git a/alfa-client/libs/zustaendige-stelle/src/lib/edit-zustaendige-stelle-button/edit-zustaendige-stelle-button.component.html b/alfa-client/libs/zustaendige-stelle/src/lib/edit-zustaendige-stelle-button/edit-zustaendige-stelle-button.component.html
index 0a991598992c48445df08be0db057f9900287eb8..d2d7f16b240bcf42a5abff1d242e40fb8ed4bf87 100644
--- a/alfa-client/libs/zustaendige-stelle/src/lib/edit-zustaendige-stelle-button/edit-zustaendige-stelle-button.component.html
+++ b/alfa-client/libs/zustaendige-stelle/src/lib/edit-zustaendige-stelle-button/edit-zustaendige-stelle-button.component.html
@@ -24,7 +24,7 @@
 
 -->
 <ods-button
-  variant="icon"
+  variant="ghost"
   size="fit"
   data-test-class="edit-zustaendige-stelle-button"
   [dataTestId]="dataTestId"
diff --git a/alfa-client/libs/zustaendige-stelle/src/lib/search-zustaendige-stelle-dialog/search-zustaendige-stelle-dialog.component.html b/alfa-client/libs/zustaendige-stelle/src/lib/search-zustaendige-stelle-dialog/search-zustaendige-stelle-dialog.component.html
index 96d90529db796367253ac7e19dd3b6a8e23e4920..9ff703cfa41d11c22550814030a0f6f2ce5a230f 100644
--- a/alfa-client/libs/zustaendige-stelle/src/lib/search-zustaendige-stelle-dialog/search-zustaendige-stelle-dialog.component.html
+++ b/alfa-client/libs/zustaendige-stelle/src/lib/search-zustaendige-stelle-dialog/search-zustaendige-stelle-dialog.component.html
@@ -26,7 +26,7 @@
 <div class="my-32 flex h-screen flex-col gap-2">
   <div class="flex gap-48 py-6 lg:gap-96">
     <h1 class="text-xl font-bold text-primary">{{ title }}</h1>
-    <ods-button variant="icon" size="fit" (clickEmitter)="closeDialog()" dataTestId="close-search-dialog">
+    <ods-button variant="ghost" size="fit" (clickEmitter)="closeDialog()" dataTestId="close-search-dialog">
       <ods-close-icon class="fill-primary" icon />
     </ods-button>
   </div>
@@ -37,4 +37,4 @@
     (selectSearchResult)="selectSearchResult($event)"
     (clearSearchResult)="clearSearchResult()"
   ></alfa-search-zustaendige-stelle-form>
-</div>
\ No newline at end of file
+</div>
diff --git a/alfa-client/libs/zustaendige-stelle/src/lib/zustaendige-stelle.module.ts b/alfa-client/libs/zustaendige-stelle/src/lib/zustaendige-stelle.module.ts
index 098801b4da5d708dd7e7472e74d256a01a32773f..0ca329814a60a3bcc0ef1724dd6e82e3cd93b162 100644
--- a/alfa-client/libs/zustaendige-stelle/src/lib/zustaendige-stelle.module.ts
+++ b/alfa-client/libs/zustaendige-stelle/src/lib/zustaendige-stelle.module.ts
@@ -28,14 +28,14 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import {
   ButtonComponent,
   CloseIconComponent,
+  EditIconComponent,
   ExternalUnitIconComponent,
   InstantSearchComponent,
   OfficeIconComponent,
+  PublicAdministrationIconComponent,
   SearchIconComponent,
 } from '@ods/system';
 import { ZustaendigeStelleSharedModule } from 'libs/zustaendige-stelle-shared/src/lib/zustaendige-stelle-shared.module';
-import { EditIconComponent } from '../../../design-system/src/lib/icons/edit-icon/edit-icon.component';
-import { PublicAdministrationIconComponent } from '../../../design-system/src/lib/icons/public-administration-icon/public-administration-icon.component';
 import { EditZustaendigeStelleButtonComponent } from './edit-zustaendige-stelle-button/edit-zustaendige-stelle-button.component';
 import { SearchExterneFachstelleContainerComponent } from './search-externe-fachstelle-container/search-externe-fachstelle-container.component';
 import { OrganisationsEinheitComponent } from './search-organisations-einheit-container/organisations-einheit/organisations-einheit.component';
diff --git a/alfa-client/tsconfig.base.json b/alfa-client/tsconfig.base.json
index 645b71e1ced60632f86bbe1484b8d0ba45b27c84..6850f74e4eb7c031308a264a51e8a4782fa9613b 100644
--- a/alfa-client/tsconfig.base.json
+++ b/alfa-client/tsconfig.base.json
@@ -18,7 +18,6 @@
     "paths": {
       "@admin-client/configuration": ["libs/admin/configuration/src/index.ts"],
       "@admin-client/configuration-shared": ["libs/admin/configuration-shared/src/index.ts"],
-      "@admin/keycloak-shared": ["libs/admin/keycloak-shared/src/index.ts"],
       "@admin-client/organisations-einheit": ["libs/admin/organisations-einheit/src/index.ts"],
       "@admin-client/organisations-einheit-shared": ["libs/admin/organisations-einheit-shared/src/index.ts"],
       "@admin-client/postfach": ["libs/admin/postfach/src/index.ts"],
@@ -28,6 +27,7 @@
       "@admin-client/statistik": ["libs/admin/statistik/src/index.ts"],
       "@admin-client/user": ["libs/admin/user/src/index.ts"],
       "@admin-client/user-shared": ["libs/admin/user-shared/src/index.ts"],
+      "@admin/keycloak-shared": ["libs/admin/keycloak-shared/src/index.ts"],
       "@alfa-client/api-root-shared": ["libs/api-root-shared/src/index.ts"],
       "@alfa-client/app-shared": ["libs/app-shared/src/index.ts"],
       "@alfa-client/bescheid": ["libs/bescheid/src/index.ts"],
@@ -77,7 +77,7 @@
       "@alfa-client/zustaendige-stelle-shared": ["libs/zustaendige-stelle-shared/src/index.ts"],
       "@authentication": ["libs/authentication/src/index.ts"],
       "@ods/component": ["libs/design-component/src/index.ts"],
-      "@ods/system": ["libs/design-system/src/index.ts"],
+      "@ods/system": ["libs/design-system/src/index.ts"]
     }
   },
   "exclude": ["node_modules", "tmp"]