# Enterprise Architecture Audit — TenantPilot / TenantAtlas **Date:** 2026-03-09 **Auditor role:** Senior Enterprise SaaS Architect, UX/IA Auditor, Security/RBAC Reviewer **Stack:** Laravel 12, Filament v5, Livewire v4, PostgreSQL, Tailwind v4 **Scope:** Panel Architecture, Navigation, Scope Enforcement, RBAC, Routing, IA --- ## 1. Executive Assessment ### Gesamturteil: **Teilweise enterprise-tauglich — strukturell problematisch in Scope-Modell und Panelarchitektur** Die Anwendung hat ein starkes RBAC-Fundament (Capability-first, role-to-capability maps, resolver services, policies) und ein funktionierendes Multi-Tenant-Modell. Die Kernfunktionen (Inventory, Backups, Governance, Monitoring) sind fachlich sinnvoll aufgebaut. **Jedoch:** Die Panel-Architektur, Navigation und Scope-Trennung weisen strukturelle Defizite auf, die in einem Enterprise-Kontext zu Verwirrung, Scope-Leaks und Sicherheitslücken führen können. ### Die 5 schwersten strukturellen Probleme | # | Problem | Severity | |---|---------|----------| | **S1** | **Kein Workspace-Home/Overview-Einstieg.** `/admin` redirected sofort zu `/admin/t/{uuid}` (Tenant-Dashboard). Es gibt keinen eigenständigen Workspace-Kontext mit eigener Landing, eigenem Dashboard, eigener Sidebar. Der Workspace ist nur eine Session-Variable, kein eigenständiger UI-Kontext. | P0 | | **S2** | **Cross-Scope-Navigation im Tenant-Panel.** Die Monitoring-Gruppe (Runs → `/admin/operations`, Alerts → `/admin/alerts`, Audit Log → `/admin/audit-log`) verlinkt im Tenant-Panel auf Admin-Panel-Routen. User verlassen den Tenant-Kontext ohne expliziten Hinweis. Dashboard-KPIs verlinken ebenfalls nach `/admin/operations`. | P0 | | **S3** | **Doppelte Resource-Discovery und panelübergreifende Registrierung.** Beide Panels (Admin + Tenant) rufen `discoverResources(in: app_path('Filament/Resources'))` auf. Die Admin-Panel-Provider registriert zusätzlich explizit Ressourcen wie `PolicyResource`, `InventoryItemResource` — die tenant-scoped sind und im Admin-Panel nichts zu suchen haben. AlertsCluster steuert Registrierung über `shouldRegisterNavigation()` nur per Panel-ID-Check, nicht per Scope-Check. | P1 | | **S4** | **Fehlende `canAccess()`-Guards auf kritischen Seiten.** `AuditLog`, `Operations` und andere Seiten haben keine `canAccess()`-Methode. Sie sind über URL direkt erreichbar, auch wenn `shouldRegisterNavigation = false` die Navigation versteckt. Navigation ist nicht die Sicherheitsgrenze — aber hier wird es so behandelt. | P1 | | **S5** | **Middleware kompensiert fehlende Panelarchitektur.** `EnsureFilamentTenantSelected` (270+ LOC) baut dynamisch Navigation, löst Scope auf, und erstellt eine "Workspace-Level"-Navigation inline per `NavigationBuilder`. Das ist Sonderlogik, die eine fehlende saubere Workspace-Panel-Architektur kompensiert. | P1 | ### Die 5 wichtigsten Korrekturen | # | Korrektur | Priorität | Aufwand | |---|-----------|-----------|---------| | **K1** | Workspace-Panel als eigenständiges Panel mit eigenem Home/Dashboard einführen | P0 | Groß | | **K2** | Cross-Scope-Links im Tenant-Panel eliminieren oder als Scope-Wechsel kenntlich machen | P0 | Mittel | | **K3** | Resource-Discovery per Panel isolieren (Tenant-Resources nur im Tenant-Panel, Workspace-Resources nur im Workspace-Panel) | P1 | Mittel | | **K4** | `canAccess()` auf allen Seiten implementieren (Zero-Trust-Regel) | P1 | Klein | | **K5** | `EnsureFilamentTenantSelected`-Middleware refactoren: Navigation-Build-Logik in Panel-Konfiguration verlagern | P1 | Mittel | --- ## 2. Current State Map ### 2.1 Panel Architecture (3 Panels) ``` ┌──────────────────────────────────────────────────────────┐ │ System Panel (path: /system) │ │ Guard: platform | Auth: PlatformCapabilities │ │ Home: System Dashboard (Control Tower) │ │ Scope: Platform-wide operations, break-glass, directory │ │ Isolation: ✅ Separate session cookie, separate guard │ └──────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────┐ │ Admin Panel (path: /admin) — DEFAULT PANEL │ │ Guard: web | Tenancy: NONE │ │ Home: Redirect to Tenant Dashboard or ChooseWorkspace │ │ Scope: Hybrid (workspace + monitoring + settings + some │ │ tenant resources registered here too) │ │ Resources: 10 explicit + auto-discovered = ~17 total │ │ Problem: No stable workspace-level home or sidebar │ └──────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────┐ │ Tenant Panel (path: /admin/t) │ │ Guard: web | Tenancy: Tenant::class (slugAttribute: │ │ external_id) │ │ Home: TenantDashboard │ │ Scope: Tenant-scoped operations (inventory, backups, │ │ compliance, drift, restore, review packs) │ │ Problem: Monitoring nav links to /admin/* routes │ │ Discovery: discoverResources + discoverPages + widgets │ └──────────────────────────────────────────────────────────┘ ``` ### 2.2 Navigation Map #### Tenant Panel Sidebar (current state in browser) ``` Dashboard → /admin/t/{uuid} ✅ Tenant-scoped ───────────────── Inventory Items → /admin/t/{uuid}/inventory ✅ Tenant-scoped Policies → /admin/t/{uuid}/policies ✅ Tenant-scoped Policy Versions → /admin/t/{uuid}/policy-versions ✅ ───────────────── Backups & Restore Backup Schedules → /admin/t/{uuid}/backup-schedules ✅ Backup Sets → /admin/t/{uuid}/backup-sets ✅ Restore Runs → /admin/t/{uuid}/restore-runs ✅ ───────────────── Directory Groups → /admin/t/{uuid}/entra-groups ✅ ───────────────── Governance Findings → /admin/t/{uuid}/findings ✅ Baseline Compare → /admin/t/{uuid}/baseline-compare-landing ✅ ───────────────── Monitoring ⚠️ CROSS-SCOPE GROUP Runs → /admin/operations ❌ Admin-Panel-Route! Alerts → /admin/alerts ❌ Admin-Panel-Route! Audit Log → /admin/audit-log ❌ Admin-Panel-Route! ───────────────── Reporting Review Packs → /admin/t/{uuid}/review-packs ✅ ``` #### Admin Panel Navigation (when no tenant selected — built by middleware) ``` Settings Manage workspaces → /admin/workspaces Monitoring Operations → /admin/operations Alert targets → /admin/alert-destinations Alert rules → /admin/alert-rules Alert deliveries → /admin/alert-deliveries Alerts → /admin/alerts Audit Log → /admin/audit-log ``` #### Admin Panel Navigation (when tenant IS selected — full navigation includes both) ``` (Full tenant resources + workspace resources mixed together) Settings Manage workspaces → /admin/workspaces Integrations → /admin/provider-connections Settings → /admin/settings/workspace (+ TenantResource, etc.) Monitoring Operations → /admin/operations Audit Log → /admin/audit-log Tenant-scoped resources (Policies, Inventory, etc.) also visible ``` ### 2.3 Scope-Wechsel und Rückwege ``` Login → EnsureWorkspaceSelected middleware: ├─ 1 Workspace → auto-select → WorkspaceRedirectResolver: │ ├─ 0 Tenants → ManagedTenantsLanding (/admin/w/{ws}/managed-tenants) │ ├─ 1 Tenant → TenantDashboard (/admin/t/{uuid}) │ └─ N Tenants → ChooseTenant (/admin/choose-tenant) └─ N Workspaces → ChooseWorkspace (/admin/choose-workspace) Workspace wechseln: Context-Bar → Workspace dropdown → "Switch workspace" → ChooseWorkspace?choose=1 ✅ Expliziter Wechsel Tenant wechseln: Context-Bar → Tenant dropdown → Select tenant (POST) Context-Bar → "Clear tenant context" Filament tenant menu (in Tenant Panel) → Searchable tenant menu ✅ Expliziter Wechsel Rückweg Tenant → Workspace: ❌ Kein direkter "Back to Workspace" Button ⚠️ Nur indirekt: Context-Bar → Switch workspace ⚠️ Oder: Monitoring-Links → navigieren implizit zum Admin-Panel ⚠️ Brand-Logo auf Tenant-Panel führt zum Tenant-Dashboard, nicht zum Workspace-Home ``` --- ## 3. Findings Table | ID | Kategorie | Severity | Ort / Screen | Datei / Klasse / Route | Symptom | Technische Ursache | Risiko | Empfohlene Korrektur | |----|-----------|----------|--------------|------------------------|---------|---------------------|--------|---------------------| | F01 | Scope-Modell | Critical | `/admin` (Home) | `routes/web.php` L43-66, `WorkspaceRedirectResolver` | `/admin` hat keine eigene Seite, redirected immer auf Tenant-Dashboard oder ChooseWorkspace | Admin-Panel hat kein Dashboard/Home. Route-Handler ist ein Redirect-Closure. | Kein Workspace-Level-Einstieg. Admin-Nutzer sehen nie einen Workspace-Überblick. | Workspace-Home-Page mit KPIs (Tenants, Operations, Health) einführen | | F02 | IA/Navigation | Critical | Tenant-Panel Sidebar → Monitoring | `TenantPanelProvider` L51-63 | "Runs", "Alerts", "Audit Log" verlinken auf `/admin/operations`, `/admin/alerts`, `/admin/audit-log` | `NavigationItem::make()` im TenantPanelProvider nutzt Admin-Panel-Routen + hardcoded URLs | Stiller Scope-Wechsel. User verlässt Tenant-Kontext ohne Warnung. URL ändert sich von `/admin/t/{uuid}/...` zu `/admin/...`. | Monitoring-Links entweder tenant-scoped machen oder als Cross-Scope-Links kennzeichnen + auf Workspace-Panel verlagern | | F03 | Scope-Modell | Critical | Tenant Dashboard KPIs | Dashboard Widgets | "Active operations" + "Inventory active" verlinken auf `/admin/operations` (Admin-Panel) | Dashboard-Widget-Links nutzen Admin-Routen | Scope-Falle: User klickt im Tenant-Dashboard und landet auf workspace-weiter Operations-Seite ohne Kontext | KPI-Links auf tenant-gefilterte Views lenken | | F04 | Security | High | `/admin/audit-log` | `AuditLog.php` | Seite hat kein `canAccess()`, nur `shouldRegisterNavigation = false` | Kein Authorization-Guard auf Page-Ebene | Jeder authentifizierte User kann Audit-Log über URL aufrufen — Verletzung des Least-Privilege-Prinzips | `canAccess()` mit `AUDIT_VIEW` Capability implementieren | | F05 | Security | High | `/admin/operations` | `Operations.php` | Seite hat kein `canAccess()`, nur `isDiscovered = false` | Kein Authorization-Guard auf Page-Ebene | Jeder authentifizierte Workspace-Member kann Operations-Seite aufrufen | `canAccess()` implementieren (Workspace-Membership reicht als Minimum) | | F06 | Registrierung | High | Admin + Tenant Panel | `AdminPanelProvider` L143-154, `TenantPanelProvider` L46-48 | Beide Panels entdecken Resources aus demselben Verzeichnis (`app/Filament/Resources`) | `discoverResources(in: app_path('Filament/Resources'))` in beiden Panels | Tenant-scoped Resources (Policy, Inventory, BackupSchedule, etc.) erscheinen potenziell in beiden Panels. `$isScopedToTenant` verhindert teilweise Daten-Leaks, aber Navigation ist dennoch inkonsistent | Resource-Discovery per Panel isolieren: Tenant-Resources in `app/Filament/Tenant/Resources`, Workspace-Resources in `app/Filament/Admin/Resources` | | F07 | IA | High | Admin Panel Settings-Gruppe | `AdminPanelProvider` L59-110 | Settings-Gruppe enthält: "Manage workspaces" + "Integrations" + "Settings" — wirkt wie der primäre Navigationsbereich, obwohl es sekundär sein sollte | NavigationItem-Registrierung im PanelProvider mit statischer Sortierung | Settings/Admin sind prominent, operative Bereiche (nur Monitoring) wirken nachrangig | Settings ans Ende der Navigation verschieben, operative Bereiche nach oben | | F08 | Scope-Modell | High | Workspace-Level-Navigation | `EnsureFilamentTenantSelected` L172-258 | Wenn kein Tenant gewählt ist, wird eine "Workspace-Level"-Navigation per `NavigationBuilder` inline in der Middleware gebaut | Middleware kompensiert fehlendes Workspace-Panel | Fragile Sonderlogik, schwer wartbar, Navigation-Änderungen erfordern Middleware-Änderung statt Panel-Konfiguration | Workspace-Panel als eigenständiges Panel konfigurieren | | F09 | IA/UX | Medium | Brand-Logo (beide Panels) | `AdminPanelProvider` L56 + `TenantPanelProvider` L29 | Brand-Logo auf Tenant-Panel führt zum aktuellen Tenant-Dashboard (`/admin/t/{uuid}`). Im Admin-Panel führt es zu `/admin` (→ Redirect auf Tenant-Dashboard). Es gibt keinen Weg per Logo zum Workspace-Home. | Filament-Default: `brandLogo` verlinkt auf Panel-Home. Admin-Panel hat kein Home → Redirect. | Nutzer können nie per Logo "nach oben" zum Workspace navigieren | Brand-Logo im Workspace-Panel auf Workspace-Home, im Tenant-Panel auf Tenant-Dashboard verlinken. Cross-Level-Navigation über Context-Bar. | | F10 | Routing | Medium | `/admin/operations/{run}` | `routes/web.php` L149-163 | Operations-Detail-Seite ist workspace-scoped, aber über Admin-Panel geroutet mit eigener Middleware-Kette | Custom Route statt Filament-Resource-Page | Deep-Links zu Operations-Runs (z.B. aus Notifications) funktionieren, aber verlassen den Tenant-Kontext | OK als Workspace-Level-Seite, aber muss klar als solche erkennbar sein | | F11 | RBAC | Medium | `AlertsCluster` | `AlertsCluster.php` | `shouldRegisterNavigation()` prüft nur Panel-ID (`=== 'admin'`), nicht Capabilities | Visibility-Check basiert auf Panel-Name, nicht auf Authorization | Cluster erscheint für alle Admin-Panel-Nutzer, egal ob sie `ALERTS_VIEW` haben | `shouldRegisterNavigation()` soll zusätzlich `ALERTS_VIEW` Capability prüfen | | F12 | Routing | Medium | `url(fn (): string => url('/admin/alerts'))` | `TenantPanelProvider` L55 | Hardcoded URL statt Named Route | `url()` statt `route()` | Brüchig bei URL-Änderungen, kein Laravel-Standard | Named Route verwenden | | F13 | IA | Medium | Tenant Panel Sidebar | TenantPanelProvider + Resource discovery | "Directory > Groups" ist einziger Eintrag unter "Directory" | Natürliches Wachstumslimit | Einelementige Navigationsgruppe wirkt unformful | Entweder "Directory" wachsen lassen oder "Groups" in eine bestehende Gruppe integrieren | | F14 | Registration | Low | `InventoryCluster` | `InventoryCluster.php` | Kein `shouldRegisterNavigation()` Override — erscheint potenziell in beiden Panels | Fehlende Panel-Gate-Logik im Cluster | Cluster könnte in falschen Panels sichtbar werden | `shouldRegisterNavigation()` mit Panel-ID-Check hinzufügen (wie AlertsCluster) | | F15 | UX | Low | Context-Bar | `context-bar.blade.php` | Workspace-Dropdown hat nur eine Option: "Switch workspace". Kein Shortcut zu Workspace-Overview/Dashboard. | Dropdown-Inhalt minimal | Nutzer müssen den Workspace erst wechseln und dann navigieren statt direkt zum Workspace-Home zu gelangen | "Workspace overview" Link im Dropdown ergänzen | --- ## 4. Structural Mismatches ### 4.1 UI-Modell vs Code-Modell | Aspekt | UI suggeriert | Code implementiert | Mismatch | |--------|---------------|-------------------|----------| | Monitoring (Runs/Alerts/AuditLog) | Tenant-scoped Monitoring (erscheint in Tenant-Sidebar) | Workspace-scoped Seiten auf Admin-Panel-Routen | **Kritisch**: Scope-Illusion | | Dashboard KPIs | Tenant-spezifische Metriken | "Active operations" und "Inventory active" verlinken auf workspace-weite `/admin/operations` | Scope-Mismatch | | "Settings" Navigationsgruppe | Nebenbereich für Konfiguration | Enthält Workspace-Management + Integrations (=Kernfunktionalität für Admins) | IA-Inversion | | Brand-Logo | "Navigiere zum Home" | Tenant-Panel: OK (→ Tenant-Dashboard). Admin-Panel: Redirect-Loop zu Tenant. | Fehlender Workspace-Home | ### 4.2 Scope-Modell vs Routing | Aspekt | Scope-Modell sagt | Routing implementiert | Mismatch | |--------|-------------------|----------------------|----------| | Workspace-Ebene | Eigener Kontext mit eigenem Home | Kein eigenes Home, kein eigenes Dashboard, nur Redirect | **Kritisch** | | Monitoring-Seiten | Workspace-scoped | Routen unter `/admin/*` mit `panel:admin` Middleware, obwohl Admin-Panel kein Tenancy hat | Middleware-Sonderlogik statt Panel-Architektur | | Operations-View (`/admin/operations/{run}`) | Workspace-scoped Detail | Custom Route mit eigener Middleware-Kette, nicht als Filament Page/Resource registriert | Parallel-Routing neben Filament | ### 4.3 Navigation vs RBAC | Aspekt | Navigation zeigt | RBAC prüft | Mismatch | |--------|------------------|------------|----------| | Audit Log | In Sidebar sichtbar (via NavigationItem in Middleware) | Kein `canAccess()` auf der Page | Visible-and-accessible-without-authorization | | Operations | In Sidebar sichtbar (via NavigationItem) | Kein `canAccess()` auf der Page | Hidden-from-nav-but-accessible-by-url | | AlertsCluster | Prüft Panel-ID, nicht Capability | AlertRulePolicy prüft ALERTS_VIEW | Visibility ≠ Authorization | | Operations im Tenant-Panel | Kein Visibility-Check | OperationRunPolicy prüft Membership | Immer sichtbar, auch für Readonly-User | ### 4.4 Filament-Defaults vs Produktmodell | Filament-Default | Produktmodell erfordert | Aktueller Zustand | |------------------|------------------------|-------------------| | `discoverResources()` ohne Panel-Scoping | Resources per Panel isoliert | Beide Panels discovern dieselben Resources | | Default Panel Home = Dashboard | Workspace-Home ≠ Tenant-Dashboard | Admin-Panel hat kein Home → Redirect auf Tenant-Panel | | Panel `brandLogo` verlinkt auf Panel-Home | Brand-Logo → kontextbezogenes Home | Admin-Panel Home redirected sofort weg | | NavigationItem-Sichtbarkeit = Filament Discovery | RBAC-gesteuerte Sichtbarkeit | Middleware baut Navigation dynamisch | | Cluster shouldRegisterNavigation = true | Per-Panel und per-Capability | Nur Panel-ID Check in AlertsCluster | ### 4.5 Middleware als Architektur-Kompensation | Middleware | Kompensiert | Eigentlich nötig | |-----------|-------------|------------------| | `EnsureFilamentTenantSelected` (270+ LOC) | Fehlende Workspace-Panel-Architektur + fehlende Navigation-Trennung | Eigenständiges Workspace-Panel mit eigener Navigation | | `EnsureWorkspaceSelected` (180+ LOC) | Fehlender Workspace-Home-Einstieg | Workspace-Home als Default-Landing | | `isWorkspaceOptionalPath()` mit Regex | Fehlende saubere Route-Trennung | Workspace-Panel-Routen, die per Middleware-Kette klar sind | | `configureNavigationForRequest()` | Fehlende stabile Workspace-Navigation | Workspace-Panel mit eigener Navigation-Konfiguration | --- ## 5. Target Enterprise Architecture ### 5.1 Drei-Panel-Modell (Zielzustand) ``` ┌═══════════════════════════════════════════════════════════┐ ║ SYSTEM PANEL (path: /system) ║ ║ Guard: platform | Session: Separate ║ ║ Purpose: Break-glass, platform ops, directory, access ║ ║ Home: System Dashboard (Control Tower) ║ ║ Audience: Platform operators ║ ║ Status: ✅ Gut isoliert, gut geschützt ║ ╚═══════════════════════════════════════════════════════════╝ ┌═══════════════════════════════════════════════════════════┐ ║ WORKSPACE PANEL (path: /admin) — DEFAULT PANEL ║ ║ Guard: web | Tenancy: NONE ║ ║ Purpose: Workspace-level administration, cross-tenant ║ ║ monitoring, alerts, integrations, onboarding, settings ║ ║ Home: WorkspaceDashboard (Tenant-Health, Operations KPIs,║ ║ Recent Activity, Alerts Summary) ║ ║ Brand-Logo → /admin (Workspace-Home) ║ ╠───────────────────────────────────────────────────────────╣ ║ NAVIGATION GROUPS: ║ ║ ║ ║ [Dashboard] Workspace-Home ║ ║ ║ ║ [Tenants] Tenant-Übersicht ║ ║ (Onboarding, Tenant-Status, ║ ║ → deep link to Tenant-Panel) ║ ║ ║ ║ [Monitoring] Operations ║ ║ Alerts (Overview, Rules, Targets, ║ ║ Deliveries) ║ ║ Audit Log ║ ║ ║ ║ [Governance] Baseline Profiles ║ ║ Baseline Snapshots ║ ║ ║ ║ [Settings] Workspace Settings ║ ║ Integrations ║ ║ Members ║ ║ Manage Workspaces ║ ╚═══════════════════════════════════════════════════════════╝ ┌═══════════════════════════════════════════════════════════┐ ║ TENANT PANEL (path: /admin/t) ║ ║ Guard: web | Tenancy: Tenant::class ║ ║ Purpose: Tenant-specific operations ║ ║ Home: TenantDashboard ║ ║ Brand-Logo → /admin/t/{uuid} (Tenant-Dashboard) ║ ╠───────────────────────────────────────────────────────────╣ ║ NAVIGATION GROUPS: ║ ║ ║ ║ [Dashboard] Tenant-Dashboard ║ ║ ║ ║ [Inventory] Items / Coverage ║ ║ Policies ║ ║ Policy Versions ║ ║ ║ ║ [Backups & Restore] Backup Schedules ║ ║ Backup Sets ║ ║ Restore Runs ║ ║ ║ ║ [Governance] Findings ║ ║ Baseline Compare ║ ║ ║ ║ [Directory] Groups ║ ║ ║ ║ [Reporting] Review Packs ║ ║ ║ ║ ──────────────────────────────── ║ ║ ⬆ Back to Workspace (Cross-Scope-Link, deutlich ║ ║ gekennzeichnet → /admin) ║ ╚═══════════════════════════════════════════════════════════╝ ``` ### 5.2 Workspace-Home/Dashboard — Empfehlung Das Workspace-Dashboard soll zeigen: 1. **Tenant-Health-Overview**: Anzahl aktive Tenants, Status (OK/Warning/Critical), letzte Sync-Zeiten 2. **Operations-KPIs**: Active/Queued/Failed operations (workspace-weit) 3. **Alert-Summary**: Aktive Alerts, undelivered, rules count 4. **Recent Activity**: Letzte 5 Audit-Log-Einträge (workspace-scoped) 5. **Needs Attention**: Failed operations, unacknowledged findings, overdue SLAs 6. **Quick Actions**: "Onboard tenant", "View operations", "Open tenant" (per Tenant-Link) ### 5.3 Brand-Logo-Verhalten | Panel | Logo-Target | Begründung | |-------|-------------|------------| | System | `/system` | Bleibt im System-Kontext | | Workspace | `/admin` | Workspace-Home (neues Dashboard) | | Tenant | `/admin/t/{uuid}` | Tenant-Dashboard (aktuell korrekt) | ### 5.4 Cross-Scope-Navigation | Richtung | Mechanismus | UI-Hinweis | |----------|-------------|------------| | Workspace → Tenant | Tenant-Liste im Workspace-Dashboard oder Sidebar → "Open in Tenant Panel" | Deutliches Icon (z.B. external-link) + Farb/Style-Unterscheidung | | Tenant → Workspace | Expliziter "Back to Workspace" Link in Tenant-Sidebar (unten) + Context-Bar | Pfeil-Icon + Label "⬆ Workspace" | | Workspace → System | Nur für Platform-Admins über User-Menü oder separate URL | Nicht in normaler Navigation | | Tenant → Tenant | Filament Tenant-Menü (searchable, bereits vorhanden) | ✅ Bereits gut gelöst | ### 5.5 Kanonische Routen | Route | Scope | Zweck | |-------|-------|-------| | `/admin` | Workspace | Workspace-Home/Dashboard | | `/admin/tenants` | Workspace | Tenant-Übersicht (aktuell TenantResource) | | `/admin/operations` | Workspace | Operations-Monitoring | | `/admin/alerts` | Workspace | Alert-Overview | | `/admin/audit-log` | Workspace | Audit-Log | | `/admin/settings/workspace` | Workspace | Workspace-Settings | | `/admin/workspaces` | Workspace | Workspace-Management (cross-workspace) | | `/admin/choose-workspace` | Tenantless | Workspace-Selektor | | `/admin/choose-tenant` | Workspace | Tenant-Selektor | | `/admin/t/{uuid}` | Tenant | Tenant-Dashboard | | `/admin/t/{uuid}/inventory` | Tenant | Inventar | | `/admin/t/{uuid}/policies` | Tenant | Policies | | `/admin/t/{uuid}/findings` | Tenant | Findings | | `/admin/t/{uuid}/backup-sets` | Tenant | Backup Sets | | `/system` | Platform | System Control Tower | --- ## 6. Navigation & Scope Principles ### Verbindliche Architekturregeln 1. **Workspace ist primärer Kontext.** Jeder authentifizierte User befindet sich immer in genau einem Workspace. Der Workspace wird über Session persistiert und in der Context-Bar angezeigt. 2. **Tenant ist operativer Kontext.** Tenant-scoped Seiten erfordern einen aktiven Tenant. Der Tenant-Kontext ist optional auf Workspace-Ebene und verpflichtend auf Tenant-Ebene. 3. **Jede Ebene hat genau einen klaren Home-Einstieg.** System → System Dashboard. Workspace → Workspace Dashboard. Tenant → Tenant Dashboard. 4. **Tenant-scoped Navigation erscheint NIE im Workspace-Panel.** Resources wie Policy, InventoryItem, BackupSchedule, Finding, ReviewPack gehören ausschließlich ins Tenant-Panel. 5. **Workspace-scoped Navigation erscheint NIE im Tenant-Panel.** Operations, Alerts, Audit Log, Workspace Settings, Workspace Management gehören ausschließlich ins Workspace-Panel. 6. **Settings/Admin sind immer untergeordnet zum Kernworkflow.** Settings-Navigationsgruppe steht am Ende der Sidebar, nie am Anfang. 7. **Brand-Logo führt zum kanonischen Home der aktuellen Ebene.** Workspace-Panel → `/admin`. Tenant-Panel → `/admin/t/{uuid}`. 8. **Switch workspace und Manage workspaces sind getrennte Konzepte.** "Switch workspace" wechselt den Kontext (via ChooseWorkspace). "Manage workspaces" ist eine Admin-Funktion (CRUD). 9. **Navigation ist NIE die Sicherheitsgrenze.** Jede Seite muss `canAccess()` implementieren, unabhängig von `shouldRegisterNavigation`. `shouldRegisterNavigation = false` ist eine UX-Entscheidung, keine Security-Maßnahme. 10. **Cross-Scope-Wechsel sind explizit.** Links, die den Scope wechseln (z.B. Tenant → Workspace), müssen visuell als solche erkennbar sein (Icon, Label, Farbe). 11. **Middleware erzeugt keine fachliche Navigation.** Die Navigation wird in der Panel-Konfiguration definiert, nicht dynamisch in Middleware gebaut. 12. **Resource-Discovery ist per Panel isoliert.** Jedes Panel discover Resources nur aus seinem eigenen Verzeichnis. Kein `discoverResources()` über Panel-Grenzen hinweg. 13. **Alle Filament-Defaults müssen explizit bestätigt oder überschrieben werden.** Default-Home, Default-Discovery, Default-Logo-Verhalten dürfen nicht stillschweigend das Produktmodell dominieren. 14. **URL-Semantik spiegelt Scope-Hierarchy wider.** `/admin/...` = Workspace-Level. `/admin/t/{uuid}/...` = Tenant-Level. `/system/...` = Platform-Level. 15. **Polling und Heavy Assets werden capability-gated und interval-kontrolliert.** Workspace-Widgets die workspace-weite Queries machen, dürfen nicht unkontrolliert pollen. --- ## 7. Recommendations ### 7.1 Quick Wins (sofort umsetzbar, geringes Risiko) | # | Empfehlung | Nutzen | Risiko | Aufwand | Abhängigkeiten | |---|------------|--------|--------|---------|----------------| | QW1 | `canAccess()` auf `AuditLog.php` und `Operations.php` implementieren | Security-Lücke schließen | Keins | 30min | Keine | | QW2 | `shouldRegisterNavigation()` in `InventoryCluster` auf Panel-ID + Capability gaten | Verhindert Cross-Panel-Sichtbarkeit | Keins | 15min | Keine | | QW3 | Hardcoded URL `url('/admin/alerts')` durch Named Route ersetzen | Routing-Stabilität | Keins | 5min | Keine | | QW4 | Workspace-Overview-Link in Context-Bar-Dropdown ergänzen | Orientierung verbessern | Keins | 30min | Keine | | QW5 | Dashboard KPI-Links (Active operations, Inventory active) tenant-filtern | Scope-Konsistenz | Keins | 1h | Keine | **Aktion:** Sofort implementieren. ### 7.2 Mittlere Refactors | # | Empfehlung | Nutzen | Risiko | Aufwand | Abhängigkeiten | |---|------------|--------|--------|---------|----------------| | MR1 | Monitoring-NavigationItems aus TenantPanelProvider entfernen | Eliminiert Cross-Scope-Navigation | Mittel (ändert Tenant-Panel UX) | 2h | Workspace-Panel muss Monitoring übernehmen | | MR2 | "Back to Workspace"-Link in Tenant-Panel-Sidebar einführen | Bidirektionale Navigation | Gering | 1h | Workspace-Panel muss existieren mit Home | | MR3 | Resource-Discovery per Panel isolieren (Verzeichnistrennung) | Eliminiert Cross-Panel-Registrierung | Mittel (Dateiumzug) | 4h | Tests müssen angepasst werden | | MR4 | `EnsureFilamentTenantSelected::configureNavigationForRequest()` in Panel-Konfiguration verlagern | Architectural Debt tilgen | Mittel | 4h | Workspace-Panel existiert | | MR5 | AlertsCluster `shouldRegisterNavigation()` um Capability-Check erweitern | RBAC-Konsistenz | Gering | 30min | Keine | **Aktion:** Als Spec schreiben, nach Quick Wins umsetzen. ### 7.3 Größere Strukturänderungen | # | Empfehlung | Nutzen | Risiko | Aufwand | Abhängigkeiten | |---|------------|--------|--------|---------|----------------| | GA1 | Workspace-Home/Dashboard als eigenständige Page im Admin-Panel einführen | Löst F01, F09, ermöglicht eigenständigen Workspace-Kontext | Mittel (Redirect-Logik muss angepasst werden) | 8-16h | Widget-Entwicklung, UX-Design | | GA2 | Monitoring-Navigation komplett in Workspace-Panel verlagern | Löst F02, F03, eliminiert Cross-Scope-Links | Hoch (ändert gesamte Monitoring-UX) | 16-24h | GA1, MR1 | | GA3 | Resource-Verzeichnisstruktur nach Panel aufteilen (`Filament/Admin/Resources`, `Filament/Tenant/Resources`) | Löst F06, verhindert künftige Cross-Panel-Registrierung | Mittel (viele Dateien bewegen) | 4-8h | Tests anpassen | | GA4 | `EnsureFilamentTenantSelected` Middleware refactoren: Pure scope-validation, keine Navigation-Logik | Löst F08, S5, reduziert Middleware-Komplexität | Mittel | 8-16h | GA1, GA2 | **Aktion:** In Constitution/Product-Principles verankern, als Specs planen. --- ## 8. Spec Backlog Proposal ### Spec 120: Workspace Home & Dashboard **Titel:** Workspace-Level Dashboard als eigenständiger Einstieg **Ziel:** Einen stabilen, informativen Workspace-Home-Einstieg schaffen, der Nutzern cross-tenant Überblick, Operations-Status und Quick Actions bietet. **Problem:** `/admin` hat kein Dashboard/Home, redirected sofort auf Tenant-Dashboard. Kein Workspace-Level-Überblick existiert. Die Brand-Logo-Navigation ist sinnlos. **Scope:** WorkspaceDashboard Page, Widgets (Tenant Health, Operations KPIs, Alerts Summary, Recent Activity, Needs Attention), Redirect-Logik anpassen, Brand-Logo-Target korrigieren. **Non-goals:** Keine Änderung der Tenant-Panel-Navigation. Kein neues Panel. **Priorität:** P0 **Risiken:** Widget-Queries müssen workspace-scoped und performant sein. **Abhängigkeiten:** Keine. **Reihenfolge:** 1 (Enabler für alle weiteren Specs) --- ### Spec 121: Monitoring Scope Separation & Cross-Scope Navigation Cleanup **Titel:** Monitoring-Navigation aus Tenant-Panel entfernen, Workspace-Monitoring stärken **Ziel:** Monitoring (Operations, Alerts, Audit Log) gehört eindeutig zum Workspace-Panel. Im Tenant-Panel sollen keine Cross-Scope-Links zu Admin-Routen existieren. **Problem:** Monitoring-Gruppe im Tenant-Panel verlinkt auf `/admin/*`-Routen. User verlassen den Tenant-Kontext ohne Warnung. Dashboard-KPIs verlinken ebenfalls cross-scope. **Scope:** NavigationItems aus TenantPanelProvider entfernen. Monitoring-Navigation im Admin-Panel stärken. Dashboard-KPIs auf tenant-scoped Views lenken. "Back to Workspace"-Link in Tenant-Panel einführen. **Non-goals:** Kein tenant-scoped Monitoring (das kommt ggf. später). **Priorität:** P0 **Risiken:** Nutzer verlieren temporär Monitoring-Zugang im Tenant-Panel. Mitigation: "Back to Workspace → Monitoring" als expliziter Weg. **Abhängigkeiten:** Spec 120 (Workspace-Home existiert als Rückweg-Ziel). **Reihenfolge:** 2 --- ### Spec 122: Resource Discovery Panel Isolation **Titel:** Filament Resource-Discovery per Panel isolieren **Ziel:** Jedes Panel entdeckt nur Resources, die zu seinem Scope gehören. Keine Cross-Panel-Registrierung. **Problem:** Beide Panels rufen `discoverResources(in: app_path('Filament/Resources'))` auf. Tenant-scoped Resources erscheinen im Admin-Panel. AdminPanelProvider registriert explizit tenant-scoped Resources (Policy, Inventory). **Scope:** Verzeichnisstruktur umbauen: `app/Filament/Admin/Resources/` + `app/Filament/Tenant/Resources/`. Discovery-Paths in Providern anpassen. Tests aktualisieren. **Non-goals:** Keine Funktionsänderung an Resources selbst. Kein neues Panel. **Priorität:** P1 **Risiken:** Viele Dateien bewegen → Import-Pfade und Namespaces anpassen. Tests müssen grün bleiben. **Abhängigkeiten:** Keine (kann parallel zu 120/121 laufen). **Reihenfolge:** 3 (parallel möglich) --- ### Spec 123: Page-Level Authorization Zero-Trust Enforcement **Titel:** `canAccess()` auf allen Filament-Pages als Pflicht-Guard **Ziel:** Jede Filament-Page muss eine `canAccess()`-Methode haben, die authorization durchführt. `shouldRegisterNavigation = false` ist keine Security-Maßnahme. **Problem:** `AuditLog`, `Operations` und weitere Pages haben kein `canAccess()`. Sie sind über URL direkt erreichbar. **Scope:** Alle Pages auditieren. Fehlende `canAccess()` ergänzen. Archunit-ähnliche Regel als Test (jede Page-Klasse muss `canAccess()` definieren). **Non-goals:** Keine Policy-Änderungen. Keine neuen Capabilities. **Priorität:** P1 **Risiken:** Gering. Falsche `canAccess()`-Logik könnte Zugang sperren → Tests. **Abhängigkeiten:** Keine. **Reihenfolge:** 2 (parallel zu Spec 121) --- ### Spec 124: Middleware Navigation Extraction **Titel:** Navigation-Logik aus `EnsureFilamentTenantSelected` in Panel-Konfiguration verlagern **Ziel:** Die 270-LOC-Middleware soll reine Scope-Validation machen. Navigation-Build-Logik gehört in Panel-Konfiguration. **Problem:** `configureNavigationForRequest()` baut inline eine "Workspace-Level"-Navigation per `NavigationBuilder`. Das ist fragile Sonderlogik. **Scope:** Navigation-Konfiguration in Admin-Panel-Provider verlagern. Middleware auf Scope-Validation reduzieren. Tests für beide Aspekte separat. **Non-goals:** Kein neues Panel. Keine Funktionsänderung. **Priorität:** P1 **Risiken:** Mittel. Navigation-Verhalten muss identisch bleiben. **Abhängigkeiten:** Spec 120 (Workspace-Home als Landing-Ziel), Spec 121 (Monitoring-Navigation bereinigt). **Reihenfolge:** 4 --- ### Spec 125: Context-Bar & Scope-Indicator Enhancement **Titel:** Context-Bar um Workspace-Home-Link, Scope-Indicator und Back-to-Workspace erweitern **Ziel:** Nutzer sollen jederzeit wissen, auf welcher Ebene sie sich befinden, und explizit zwischen Ebenen wechseln können. **Problem:** Kein Workspace-Home-Link in Context-Bar. Kein visueller Scope-Indicator (Workspace vs Tenant). "Back to Workspace" nur indirekt möglich. **Scope:** Context-Bar-Dropdown erweitern: "Workspace overview" Link. Scope-Badge in Topbar (Workspace | Tenant). "Back to Workspace ↑" im Tenant-Panel. **Non-goals:** Keine Breadcrumbs-Überarbeitung. **Priorität:** P2 **Risiken:** Gering. UX-Änderung, kein Security-Impact. **Abhängigkeiten:** Spec 120 (Workspace-Home existiert). **Reihenfolge:** 5 --- ### Spec 126: Navigation & RBAC Alignment Enforcement **Titel:** Navigation-Sichtbarkeit an Capabilities koppeln (Cluster, NavigationItems, Resources) **Ziel:** Jeder NavigationItem und Cluster soll seine Sichtbarkeit an Capabilities koppeln, nicht nur an Panel-ID. **Problem:** AlertsCluster prüft nur Panel-ID. NavigationItems im AdminPanelProvider sind nicht alle capability-gated. InventoryCluster hat keinen Visibility-Check. **Scope:** Alle Clusters und NavigationItems mit Capability-Checks ausstatten. Architectural Test: "Jeder NavigationItem muss eine `visible()`-Closure haben, die Capabilities prüft." **Non-goals:** Keine neuen Capabilities definieren. **Priorität:** P2 **Risiken:** Gering. Könnte Navigation für Nutzer mit eingeschränkten Rechten ändern → gezieltes Testing. **Abhängigkeiten:** Keine. **Reihenfolge:** 5 (parallel zu Spec 125) --- ### Empfohlene Reihenfolge: ``` 1. Spec 120 (Workspace Home) ← Enabler [P0] 2. Spec 121 (Monitoring Scope) + Spec 123 (canAccess Zero Trust) [P0/P1, parallel] 3. Spec 122 (Resource Discovery Isolation) [P1, parallel] 4. Spec 124 (Middleware Extraction) [P1, after 120+121] 5. Spec 125 (Context-Bar) + Spec 126 (RBAC Alignment) [P2, parallel] ``` Quick Wins (QW1–QW5) werden sofort vor allen Specs implementiert. --- ## Appendix: Discovery-Overlap-Analyse Beide Panels discovern aus `app/Filament/Resources`: | Resource | `$tenantOwnershipRelationshipName` | Admin-Panel (should be) | Tenant-Panel (should be) | Aktuell in | |----------|------------------------------------|-----------------------|------------------------|----| | PolicyResource | `tenant` | ❌ Nein | ✅ Ja | Beide | | InventoryItemResource | `tenant` | ❌ Nein | ✅ Ja | Beide | | BackupScheduleResource | `tenant` | ❌ Nein | ✅ Ja | Beide | | BackupSetResource | `tenant` | ❌ Nein | ✅ Ja | Beide | | RestoreRunResource | `tenant` | ❌ Nein | ✅ Ja | Beide | | FindingResource | `tenant` | ❌ Nein | ✅ Ja | Beide | | ReviewPackResource | `tenant` | ❌ Nein | ✅ Ja | Beide | | PolicyVersionResource | `tenant` | ❌ Nein | ✅ Ja | Beide | | EntraGroupResource | none | ❌ Nein | ✅ Ja | Beide | | TenantResource | none | ✅ Ja | ❌ Nein | Beide (explizit) | | OperationRunResource | none | ✅ Ja | ❌ Nein | Beide | | AlertRuleResource | none | ✅ Ja | ❌ Nein | Beide | | AlertDestinationResource | none | ✅ Ja | ❌ Nein | Beide | | AlertDeliveryResource | none | ✅ Ja | ❌ Nein | Beide | | ProviderConnectionResource | none | ✅ Ja | ❌ Nein | Admin (explicit) | | WorkspaceResource | none | ✅ Ja | ❌ Nein | Admin (explicit, not discovered) | | BaselineProfileResource | none | ✅ Ja | ❌ Nein | Admin (explicit, not discovered) | | BaselineSnapshotResource | none | ✅ Ja | ❌ Nein | Admin (explicit, not discovered) | **Ergebnis:** 9 tenant-scoped Resources werden aktuell in beiden Panels discovert. Filament's Tenancy-System filtert die Daten korrekt per `$tenantOwnershipRelationshipName`, aber die Resources erscheinen trotzdem in der Navigation des Admin-Panels (wenn auch teilweise ohne Daten).