TenantAtlas/docs/audits/enterprise-architecture-audit-2026-03-09.md
ahmido c6e7591d19 feat: add Intune RBAC inventory and backup support (#155)
## Summary
- add Intune RBAC role definitions and role assignments as foundation-backed inventory, backup, and versioned snapshot types
- add RBAC-specific normalization, coverage, permission-warning handling, and preview-only restore safety behavior across existing Filament and service surfaces
- add spec 127 artifacts, contracts, audits, and focused regression coverage for inventory, backup, versioning, verification, and authorization behavior

## Testing
- `vendor/bin/sail bin pint --dirty --format agent`
- `vendor/bin/sail artisan test --compact tests/Feature/Inventory/InventorySyncServiceTest.php tests/Feature/Filament/InventoryCoverageTableTest.php tests/Feature/FoundationBackupTest.php tests/Feature/Filament/RestoreExecutionTest.php tests/Feature/RestoreUnknownPolicyTypeSafetyTest.php tests/Unit/GraphContractRegistryTest.php tests/Unit/FoundationSnapshotServiceTest.php tests/Feature/Verification/IntuneRbacPermissionCoverageTest.php tests/Unit/IntuneRoleDefinitionNormalizerTest.php tests/Unit/IntuneRoleAssignmentNormalizerTest.php`

## Notes
- tasks in `specs/127-rbac-inventory-backup/tasks.md` are complete except `T041`, which is the documented manual QA validation step

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #155
2026-03-09 10:40:51 +00:00

579 lines
41 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 (QW1QW5) 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).