## 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
579 lines
41 KiB
Markdown
579 lines
41 KiB
Markdown
# 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).
|