wiki/implementation/Saas Multi Tenant Mandate/mandate_implementation_analysis.md
ValueOn AG b0ffd52556 upd
2026-01-20 08:39:25 +01:00

25 KiB

Multi-Tenant Implementation Analysis - Frontend Nyla

Version: 1.1
Datum: 20. Januar 2026
Basis: mandate_implementation_ui_myla.md (Konzept) & mandate_implementation_gateway.md (Backend)


1. Zusammenfassung

Dieses Dokument analysiert den Implementierungsstand des Multi-Tenant-Systems im Frontend Nyla und vergleicht es mit dem Konzeptdokument. Es enthält:

  • Was implementiert ist
  • Was teilweise implementiert ist ⚠️
  • Was noch fehlt
  • Strukturempfehlungen für die Integration

2. Implementierungsstand - Übersicht

Komponente Status Details
Core Types Implementiert types/mandate.ts - vollständig
Feature Store Implementiert stores/featureStore.tsx - React Context-basiert
useCurrentInstance Hook Implementiert URL-basierte Instanz-Auflösung
Instance Permission Hooks Implementiert useInstancePermissions.tsx
Permission Gate Component Implementiert Conditional Rendering
Mandate Navigation Implementiert Hierarchische Tree-Navigation
Features API Implementiert featuresApi.ts mit /api/features/my
URL-Struktur Implementiert /mandates/:mandateId/:featureCode/:instanceId/*
Invitation Flow Implementiert InvitePage.tsx + useInvitations.ts
Admin: Mandates Implementiert AdminMandatesPage.tsx
Admin: Users Implementiert AdminUsersPage.tsx
Admin: Roles Implementiert AdminRolesPage.tsx
Admin: Mandate Roles Implementiert AdminMandateRolesPage.tsx
Admin: Invitations Implementiert AdminInvitationsPage.tsx
Admin: Feature Access Implementiert AdminFeatureAccessPage.tsx
Admin: User Mandates Implementiert AdminUserMandatesPage.tsx
AccessRules Editor Implementiert components/AccessRules/AccessRulesEditor.tsx
RBAC Export/Import Implementiert components/RbacExportImport/RbacExportImport.tsx
Mandate-Admin Section per Mandate ⚠️ Teilweise Nur global, nicht pro Mandant

3. Detaillierte Analyse

3.1 Core Architecture

Types (src/types/mandate.ts)

Status: Vollständig implementiert

// Implementiert gemäss Konzept:
- I18nLabel
- AccessLevel ('n' | 'm' | 'g' | 'a')
- TablePermission
- FieldPermission
- InstancePermissions
- FeatureInstance
- MandateFeature
- Mandate
- FeaturesMyResponse
- User (ohne mandateId!)
- FEATURE_REGISTRY

Korrekte Umsetzung der Konzept-Prinzipien:

  • User hat KEINE mandateId mehr
  • Permissions sind summarisch pro Instanz
  • Hierarchie: Mandate → Feature → Instance → Views

3.2 Feature Store

Datei: src/stores/featureStore.tsx

Status: Vollständig implementiert als React Context

Konzept-Anforderung Implementiert
loadFeatures() Lädt von /api/features/my
setFeatures() Direktes Setzen nach Login
getMandateById()
getFeatureByCode()
getInstanceById() Mit Cache-Map für Performance
getAllInstances()
hasAnyInstance()
reset() Für Logout

Abweichung vom Konzept:

  • Konzept: Zustand-basiert (Zustand Library)
  • Implementiert: React Context + useState + useRef für Cache

Bewertung: Funktional äquivalent, React Context ist für die Anwendungsgrösse angemessen.


3.3 useCurrentInstance Hook

Datei: src/hooks/useCurrentInstance.ts

Status: Vollständig implementiert

// Exportierte Hooks:
- useCurrentInstance()  // Vollständiger Kontext
- useInstance()         // Nur Instanz
- useInstanceId()       // Nur ID
- useFeatureCode()      // Nur Feature-Code
- useMandateId()        // Nur Mandate-ID
- useIsInFeatureContext() // Boolean Check

Korrekte Umsetzung:

  • Liest Parameter aus URL (useParams)
  • Validiert Konsistenz (Instanz gehört zu Mandate/Feature)
  • Keine Speicherung im globalen State

3.4 Permission System

Dateien:

  • src/hooks/useInstancePermissions.tsx
  • src/hooks/usePermissions.ts

Instance-basierte Permissions

Hook Status Verwendung
useTablePermission(tableName) CRUD-Checks auf Tabellen
useCanViewTable(tableName) View-Check
useCanViewFeatureView(viewCode) Navigation-Filterung
useViewPermissions(viewCodes[]) Bulk View-Checks
useFieldPermission(table, field) Feld-Level Checks
useInstancePermissions() Raw Permissions-Objekt
useCanEditRecord() Record-basierte Prüfung
useCanDeleteRecord() Record-basierte Prüfung

PermissionGate Component

<PermissionGate table="TrusteeContract" action="create">
  <Button>Neuer Vertrag</Button>
</PermissionGate>

<PermissionGate view="trustee-admin" fallback={<AccessDenied />}>
  <AdminPanel />
</PermissionGate>

Implementiert gemäss Konzept - Conditional Rendering basierend auf Permissions.


3.5 Navigation

Datei: src/components/Navigation/MandateNavigation.tsx

Status: Vollständig implementiert

Struktur wie im Konzept:

SYSTEM (immer)
  ○ Übersicht
  ○ Einstellungen

▼ Mandant: Soha Treuhand
  ├─▼ Feature: Trustee
  │   ├─▼ Instanz: PamoCreate AG (mit Views)
  │   └─▼ Instanz: ValueOn AG (mit Views)
  └─▼ Feature: Workflow
      └─▼ Instanz: Beratung Dynamic

─────────────────────────────
ADMINISTRATION (nur SysAdmin)
  ○ Mandanten
  ○ Benutzer
  ○ Globale Rollen
  ...

Implementierte Features:

  • Hierarchische Tree-Navigation (TreeNavigation)
  • Dynamische Icon-Zuordnung pro Feature
  • Automatisches Filtern von Views basierend auf Permissions
  • Admin-Sektion nur für isSysAdmin
  • Empty State wenn keine Instanzen

3.6 URL-Struktur

Datei: src/App.tsx

Implementierte Routen:

/                                              → Dashboard
/settings                                      → Benutzer-Einstellungen
/mandates/:mandateId/:featureCode/:instanceId  → Feature Layout
  /dashboard                                   → Feature Dashboard
  /contracts                                   → Verträge
  /documents                                   → Dokumente
  /positions                                   → Positionen
  /organisations                               → Organisationen
  /roles                                       → Rollen
  /access                                      → Zugriffe
  /runs                                        → Workflow Runs
  /files                                       → Dateien
  /conversations                               → Chat

/admin/mandates                                → Admin: Mandanten
/admin/users                                   → Admin: Benutzer
/admin/roles                                   → Admin: Globale Rollen
/admin/user-mandates                           → Admin: Mandanten-Mitglieder
/admin/feature-instances                       → Admin: Feature-Instanzen
/admin/invitations                             → Admin: Einladungen
/admin/mandate-roles                           → Admin: Mandanten-Rollen

/invite/:token                                 → Einladungs-Annahme
/login, /register, /password-reset-request, /reset → Auth

Korrekte Umsetzung der Konzept-URL-Struktur.


3.7 Invitation Flow

Dateien:

  • src/pages/InvitePage.tsx
  • src/hooks/useInvitations.ts

Implementierte Funktionen:

Feature Status
Token-Validierung validateInvitation(token)
Einladung annehmen (auth) acceptInvitation(token)
Registrieren + Annehmen registerAndAccept(data)
Einladungen erstellen createInvitation()
Einladungen widerrufen revokeInvitation()
Einladungen auflisten fetchInvitations()

InvitePage Features:

  • Token-Validierung beim Mount
  • Unterscheidung: Eingeloggt vs. Nicht eingeloggt
  • Registrierungsformular für neue User
  • Login-Redirect für bestehende User
  • Fehlerbehandlung für ungültige/abgelaufene Tokens

3.8 Admin Pages

Alle Admin-Seiten verwenden FormGeneratorTable und FormGeneratorForm.

Seite Status Funktionen
AdminMandatesPage CRUD Mandanten, Table mit Pagination
AdminUsersPage CRUD Benutzer
AdminRolesPage CRUD Globale Rollen
AdminMandateRolesPage Rollen pro Mandant, Filter (global/mandate)
AdminUserMandatesPage User-Mandate-Zuordnungen
AdminFeatureAccessPage Feature-Instanz-Zugriffe
AdminInvitationsPage Einladungsverwaltung

4. Neu Implementierte RBAC-Komponenten

4.1 AccessRules Editor

Datei: src/components/AccessRules/AccessRulesEditor.tsx

Status: Vollständig implementiert

Die Komponente ermöglicht die Bearbeitung von RBAC-Regeln pro Rolle mit Tabs für verschiedene Regel-Kontexte.

Komponenten-Struktur

src/components/AccessRules/
  ├── AccessRulesEditor.tsx        // Hauptkomponente mit Tabs
  ├── AccessRules.module.css       // Styles
  ├── AccessLevelSelect.tsx        // Dropdown für n/m/g/a
  └── index.ts

Verwendung

import { AccessRulesEditor } from '../components/AccessRules';

// In einer Admin-Seite:
<AccessRulesEditor
  roleId={selectedRole.id}
  roleName={selectedRole.roleLabel}
  isTemplate={true}              // Optional: Template-Badge anzeigen
  readOnly={false}               // Optional: Nur-Lesen-Modus
  onSave={() => refetchRoles()}  // Optional: Callback nach Speichern
/>

Features

Feature Status
Tabs: DATA, UI, RESOURCE, JSON
AccessLevel Dropdown (n/m/g/a)
Regel hinzufügen
Regel löschen
Permissions-Grid (view, read, create, update, delete)
JSON-Editor für Raw-Bearbeitung
Speichern & Zurücksetzen
Änderungstracking
Read-Only Modus

API-Hook

import { useAccessRules } from '../hooks/useAccessRules';

const {
  rules,              // Alle Regeln für die Rolle
  loading,            // Lade-Status
  saving,             // Speicher-Status
  error,              // Fehler-Nachricht
  fetchRules,         // Regeln laden
  saveRules,          // Regeln speichern (Bulk)
  createRule,         // Einzelne Regel erstellen
  updateRule,         // Einzelne Regel aktualisieren
  deleteRule,         // Einzelne Regel löschen
  getGroupedRules,    // Regeln nach Kontext gruppiert
} = useAccessRules(roleId);

4.2 RBAC Export/Import

Datei: src/components/RbacExportImport/RbacExportImport.tsx

Status: Vollständig implementiert

Die Komponente ermöglicht Export und Import von RBAC-Konfigurationen.

Komponenten-Struktur

src/components/RbacExportImport/
  ├── RbacExportImport.tsx         // Hauptkomponente
  ├── RbacExportImport.module.css  // Styles
  └── index.ts

Verwendung

import { RbacExportImport } from '../components/RbacExportImport';

// Für Mandant:
<RbacExportImport
  mandateId="mand-123"
  mandateName="Soha Treuhand"
  featureCode="trustee"  // Optional: Nur für Feature
/>

// Für globale Templates (SysAdmin):
<RbacExportImport
  isGlobal={true}
  featureCode="trustee"  // Optional
/>

Features

Feature Status
Export als JSON-Download
Import via File-Upload
Import-Modi: merge, replace, add_only
Datei-Vorschau vor Import
Import-Ergebnis-Anzeige
Warnung bei Replace-Modus
Fehlerbehandlung

Import-Modi

Modus Beschreibung
merge Bestehende aktualisieren, neue hinzufügen
add_only Nur neue hinzufügen, bestehende unverändert
replace Alle bestehenden löschen und ersetzen

API-Hook

import { useRbacExportImport } from '../hooks/useRbacExportImport';

const {
  exporting,           // Export läuft
  importing,           // Import läuft
  error,               // Fehler-Nachricht
  lastExport,          // Letzter Export
  lastImportResult,    // Letztes Import-Ergebnis
  exportMandateRbac,   // Export für Mandant
  exportGlobalRbac,    // Export für Templates
  importMandateRbac,   // Import in Mandant
  importGlobalRbac,    // Import in Templates
  downloadExport,      // JSON-Download auslösen
  parseImportFile,     // Datei parsen
} = useRbacExportImport();

4.3 Mandate-Admin Section pro Mandant ⚠️

Konzept:

▼ Mandant: Soha Treuhand
  ├─▼ Feature: Trustee
  │   └─▼ Instanzen...
  │
  └─▼ ADMINISTRATION (nur Mandate-Admin)
       ○ Benutzer
       ○ Rollen
       ○ Berechtigungen
       ○ Feature-Instanzen
       ○ Einladungen
       ○ RBAC Export/Import

Aktueller Stand:

  • Admin-Sektion existiert nur global unter /admin/*
  • Kein Mandate-spezifischer Admin-Bereich in der Navigation

Empfehlung: Die Navigation sollte pro Mandant einen Admin-Bereich anzeigen wenn der User Mandate-Admin Rolle hat.


5. FormGenerator Komponenten (statt GenericForm)

Hinweis: Es gibt keine GenericForm Komponente im Codebase. Die generische Form-Funktionalität wird durch die FormGenerator-Komponenten bereitgestellt.

5.1 Verfügbare Komponenten

Komponente Pfad Verwendung
FormGeneratorForm components/FormGenerator/FormGeneratorForm/ Backend-driven Forms
FormGeneratorTable components/FormGenerator/FormGeneratorTable/ Data Tables mit CRUD
FormGeneratorList components/FormGenerator/FormGeneratorList/ Listen-Ansichten
FormGeneratorControls components/FormGenerator/FormGeneratorControls/ Filter/Search UI

5.2 FormGeneratorForm - Verwendung

import { FormGeneratorForm, type AttributeDefinition } from '../components/FormGenerator/FormGeneratorForm';

// 1. Mit expliziten Attributen
const fields: AttributeDefinition[] = [
  { name: 'name', label: 'Name', type: 'string', required: true },
  { name: 'description', label: 'Beschreibung', type: 'textarea' },
  { name: 'enabled', label: 'Aktiv', type: 'boolean' },
  { name: 'role', label: 'Rolle', type: 'enum', options: [...] },
];

<FormGeneratorForm
  attributes={fields}
  data={initialData}           // Optional: Für Edit-Mode
  mode="create"                // 'create' | 'edit' | 'display'
  onSubmit={handleSubmit}
  onCancel={handleCancel}
  submitButtonText="Erstellen"
  cancelButtonText="Abbrechen"
/>

// 2. Mit Backend-getriebenen Attributen (fetcht von /api/attributes/{entityType})
<FormGeneratorForm
  entityType="TrusteeContract"
  data={contract}
  mode="edit"
  onSubmit={handleUpdate}
/>

5.3 FormGeneratorTable - Verwendung

import { FormGeneratorTable } from '../components/FormGenerator/FormGeneratorTable';

<FormGeneratorTable
  data={contracts}
  columns={[
    { key: 'name', label: 'Name', type: 'string', sortable: true },
    { key: 'status', label: 'Status', type: 'enum' },
  ]}
  loading={isLoading}
  pagination={true}
  pageSize={25}
  searchable={true}
  filterable={true}
  sortable={true}
  actionButtons={[
    { type: 'edit', onAction: handleEdit },
    { type: 'delete', title: 'Löschen' },
  ]}
  onDelete={handleDelete}
  hookData={{
    refetch,
    permissions,
    handleInlineUpdate,
  }}
/>

5.4 Unterstützte Feld-Typen

Type Beschreibung Input
string Text <input type="text">
textarea Mehrzeiliger Text <textarea>
integer Ganzzahl <input type="number">
float Dezimalzahl <input type="number">
boolean Ja/Nein <input type="checkbox">
enum Auswahl <select>
multiselect Mehrfachauswahl Checkboxes
date Datum <input type="date">
datetime Datum+Zeit <input type="datetime-local">
email E-Mail <input type="email">
url URL <input type="url">
file Datei <input type="file">
textmultilingual Mehrsprachig Inputs pro Sprache

6. Integrations-Empfehlungen

6.1 Neue Feature-View hinzufügen

Schritt 1: View-Komponente erstellen

// src/pages/views/trustee/TrusteeNewView.tsx

import React from 'react';
import { useCurrentInstance } from '../../../hooks/useCurrentInstance';
import { useTablePermission } from '../../../hooks/useInstancePermissions';
import { FormGeneratorTable } from '../../../components/FormGenerator/FormGeneratorTable';

export const TrusteeNewView: React.FC = () => {
  const { instance } = useCurrentInstance();
  const { canCreate, canUpdate, canDelete } = useTablePermission('TrusteeNewTable');
  
  // Daten laden...
  
  return (
    <div>
      <h2>Neue View</h2>
      <FormGeneratorTable ... />
    </div>
  );
};

Schritt 2: In FEATURE_REGISTRY registrieren

// src/types/mandate.ts

export const FEATURE_REGISTRY: Record<string, FeatureConfig> = {
  trustee: {
    // ...
    views: [
      // Bestehende Views...
      { code: 'newview', label: { de: 'Neue View', en: 'New View' }, path: 'newview' },
    ]
  },
};

Schritt 3: In VIEW_COMPONENTS registrieren

// src/pages/FeatureView.tsx

import { TrusteeNewView } from './views/trustee/TrusteeNewView';

const VIEW_COMPONENTS: Record<string, Record<string, ViewComponent>> = {
  trustee: {
    // Bestehende Views...
    newview: TrusteeNewView,
  },
};

Schritt 4: Route hinzufügen

// src/App.tsx

<Route path="newview" element={<FeatureViewPage view="newview" />} />

6.2 AccessRulesEditor in Admin-Seiten integrieren

Beispiel: Integration in AdminRolesPage

// src/pages/admin/AdminRolesPage.tsx

import { useState } from 'react';
import { AccessRulesEditor } from '../../components/AccessRules';

export const AdminRolesPage: React.FC = () => {
  const [selectedRole, setSelectedRole] = useState<Role | null>(null);
  
  return (
    <div className={styles.twoColumnLayout}>
      {/* Linke Spalte: Rollen-Liste */}
      <div className={styles.roleList}>
        <FormGeneratorTable
          data={roles}
          columns={columns}
          actionButtons={[
            { type: 'view', onAction: setSelectedRole },
          ]}
        />
      </div>
      
      {/* Rechte Spalte: AccessRules Editor */}
      {selectedRole && (
        <AccessRulesEditor
          roleId={selectedRole.id}
          roleName={selectedRole.roleLabel}
          isTemplate={!selectedRole.mandateId}
          onSave={() => refetch()}
        />
      )}
    </div>
  );
};

6.3 RBAC Export/Import in Admin-Seiten integrieren

Beispiel: Standalone-Seite oder Modal

// src/pages/admin/AdminRbacExportImportPage.tsx

import { RbacExportImport } from '../../components/RbacExportImport';

export const AdminRbacExportImportPage: React.FC = () => {
  const [selectedMandateId, setSelectedMandateId] = useState<string>('');
  const { user } = useCurrentUser();
  
  return (
    <div className={styles.adminPage}>
      <h1>RBAC Export/Import</h1>
      
      {/* Mandant-Auswahl */}
      <select
        value={selectedMandateId}
        onChange={(e) => setSelectedMandateId(e.target.value)}
      >
        <option value="">-- Mandant wählen --</option>
        {mandates.map(m => (
          <option key={m.id} value={m.id}>{m.name}</option>
        ))}
      </select>
      
      {/* Export/Import für gewählten Mandant */}
      {selectedMandateId && (
        <RbacExportImport
          mandateId={selectedMandateId}
          mandateName={mandates.find(m => m.id === selectedMandateId)?.name}
        />
      )}
      
      {/* Globale Templates (nur SysAdmin) */}
      {user?.isSysAdmin && (
        <div style={{ marginTop: '2rem' }}>
          <h2>Globale Templates</h2>
          <RbacExportImport isGlobal={true} />
        </div>
      )}
    </div>
  );
};

6.4 Mandate-Admin Navigation hinzufügen (Empfehlung)

In MandateNavigation.tsx erweitern:

// Nach den Feature-Nodes pro Mandant:

function mandateToTreeNode(mandate: Mandate, userId: string): TreeNodeItem | null {
  // ... bestehender Code ...
  
  // Admin-Sektion für Mandate-Admins hinzufügen
  const isMandateAdmin = checkMandateAdminRole(userId, mandate.id);
  
  if (isMandateAdmin) {
    children.push({
      id: `${mandate.id}-admin`,
      label: 'Administration',
      icon: <FaCog />,
      children: [
        { id: `${mandate.id}-admin-users`, label: 'Benutzer', path: `/mandates/${mandate.id}/admin/users` },
        { id: `${mandate.id}-admin-roles`, label: 'Rollen', path: `/mandates/${mandate.id}/admin/roles` },
        { id: `${mandate.id}-admin-instances`, label: 'Feature-Instanzen', path: `/mandates/${mandate.id}/admin/instances` },
        { id: `${mandate.id}-admin-rbac`, label: 'RBAC Export/Import', path: `/mandates/${mandate.id}/admin/rbac` },
      ],
    });
  }
  
  return { /* ... */ };
}

7. API-Anbindung

7.1 Implementierte Endpoints

Endpoint Frontend-Verwendung
GET /api/features/my featuresApi.fetchMyFeatures()
GET /api/features/available featuresApi.fetchAvailableFeatures()
GET /api/invitations/validate/:token useInvitations().validateInvitation()
POST /api/invitations/accept/:token useInvitations().acceptInvitation()
POST /api/invitations/register-and-accept useInvitations().registerAndAccept()
GET /api/invitations/ useInvitations().fetchInvitations()
POST /api/invitations/ useInvitations().createInvitation()
DELETE /api/invitations/:id useInvitations().revokeInvitation()

7.2 Neu implementierte Endpoint-Anbindungen

Endpoint UI-Komponente Hook
GET /api/rbac/roles/:id/rules AccessRulesEditor useAccessRules
PUT /api/rbac/roles/:id/rules AccessRulesEditor useAccessRules
POST /api/rbac/roles/:id/rules AccessRulesEditor useAccessRules
PATCH /api/rbac/rules/:id AccessRulesEditor useAccessRules
DELETE /api/rbac/rules/:id AccessRulesEditor useAccessRules
GET /api/mandates/:id/rbac/export RbacExportImport useRbacExportImport
POST /api/mandates/:id/rbac/import RbacExportImport useRbacExportImport
GET /api/admin/rbac/global/export RbacExportImport useRbacExportImport
POST /api/admin/rbac/global/import RbacExportImport useRbacExportImport
GET /api/features/instances/:id/rbac/export RbacExportImport useRbacExportImport

7.3 Noch zu implementieren

Endpoint Fehlende UI-Komponente
POST /api/features/instances/:id/sync-roles Sync-Button in Admin

8. Zusammenfassung der Empfehlungen

Abgeschlossen

  1. AccessRulesEditor - Vollständig implementiert
  2. RBAC Export/Import UI - Vollständig implementiert

Priorität 1 (Hoch)

  1. Mandate-Admin Navigation - Pro Mandant Admin-Bereich für Mandate-Admins
  2. Integration der neuen Komponenten in bestehende Admin-Seiten

Priorität 2 (Mittel)

  1. Template-Sync UI - Button für Rollen-Synchronisation von Templates
  2. Admin-Route für RBAC Export/Import hinzufügen

Priorität 3 (Niedrig)

  1. Chatworkflow Views - Aktuell nur Placeholder
  2. Chatbot Views - Aktuell nur Placeholder

9. Checkliste für Feature-Entwickler

9.1 Beim Hinzufügen neuer Features

  • Types in types/mandate.ts ergänzen
  • View in FEATURE_REGISTRY registrieren
  • Komponente in VIEW_COMPONENTS registrieren
  • Route in App.tsx hinzufügen
  • Permissions im Backend definieren (trustee-newview)
  • API-Hook erstellen wenn nötig
  • FormGeneratorForm für CRUD-Formulare nutzen
  • FormGeneratorTable für Listen nutzen
  • PermissionGate für bedingte UI-Elemente
  • useTablePermission für Record-basierte Checks

9.2 Beim Arbeiten mit RBAC

  • AccessRulesEditor für Rollen-Berechtigungen nutzen
  • RbacExportImport für Backup/Migration nutzen
  • useAccessRules Hook für programmatische RBAC-Verwaltung
  • useRbacExportImport Hook für Export/Import-Logik

10. Neue Komponenten - Dateiübersicht

10.1 AccessRules

src/
├── hooks/
│   └── useAccessRules.ts              // RBAC-Regeln Hook
└── components/
    └── AccessRules/
        ├── AccessRulesEditor.tsx      // Hauptkomponente
        ├── AccessLevelSelect.tsx      // Dropdown für n/m/g/a
        ├── AccessRules.module.css     // Styles
        └── index.ts                   // Exports

10.2 RBAC Export/Import

src/
├── hooks/
│   └── useRbacExportImport.ts         // Export/Import Hook
└── components/
    └── RbacExportImport/
        ├── RbacExportImport.tsx       // Hauptkomponente
        ├── RbacExportImport.module.css // Styles
        └── index.ts                   // Exports