Complete implementation of TenantPilot v1 Intune Management Platform with comprehensive backup, versioning, and restore capabilities. CONSTITUTION & SPEC - Ratified constitution v1.0.0 with 7 core principles - Complete spec.md with 7 user stories (US1-7) - Detailed plan.md with constitution compliance check - Task breakdown with 125+ tasks across 12 phases CORE FEATURES (US1-4) - Policy inventory with Graph-based sync (US1) - Backup creation with immutable JSONB snapshots (US2) - Version history with diff viewer (human + JSON) (US3) - Defensive restore with preview/dry-run (US4) TENANT MANAGEMENT (US6-7) - Full tenant CRUD with Entra ID app configuration - Admin consent callback flow integration - Tenant connectivity verification - Permission health status monitoring - 'Highlander' pattern: single current tenant with is_current flag GRAPH ABSTRACTION - Complete isolation layer (7 classes) - GraphClientInterface with mockable implementations - Error mapping, logging, and standardized responses - Rate-limit aware design DOMAIN SERVICES - BackupService: immutable snapshot creation - RestoreService: preview, selective restore, conflict detection - VersionService: immutable version capture - VersionDiff: human-readable and structured diffs - PolicySyncService: Graph-based policy import - TenantConfigService: connectivity testing - TenantPermissionService: permission health checks - AuditLogger: comprehensive audit trail DATA MODEL - 11 migrations with tenant-aware schema - 8 Eloquent models with proper relationships - SoftDeletes on Tenant, BackupSet, BackupItem, PolicyVersion, RestoreRun - JSONB storage for snapshots, metadata, permissions - Encrypted storage for client secrets - Partial unique index for is_current tenant FILAMENT ADMIN UI - 5 main resources: Tenant, Policy, PolicyVersion, BackupSet, RestoreRun - RelationManagers: Versions (Policy), BackupItems (BackupSet) - Actions: Verify config, Admin consent, Make current, Delete/Force delete - Filters: Status, Type, Platform, Archive state - Permission panel with status indicators - ActionGroup pattern for cleaner row actions HOUSEKEEPING (Phases 10-12) - Soft delete with archive status for all entities - Force delete protection (blocks if dependencies exist) - Tenant deactivation with cascade prevention - Audit logging for all delete operations TESTING - 36 tests passing (125 assertions, 11.21s) - Feature tests: Policy, Backup, Restore, Version, Tenant, Housekeeping - Unit tests: VersionDiff, TenantCurrent, Permissions, Scopes - Full TDD coverage for critical flows CONFIGURATION - config/tenantpilot.php: 10+ policy types with metadata - config/intune_permissions.php: required Graph permissions - config/graph.php: Graph client configuration SAFETY & COMPLIANCE - Constitution compliance: 7/7 principles ✓ - Safety-first operations: preview, confirmation, validation - Immutable versioning: no in-place modifications - Defensive restore: dry-run, selective, conflict detection - Comprehensive auditability: all critical operations logged - Tenant-aware architecture: multi-tenant ready - Graph abstraction: isolated, mockable, testable - Spec-driven development: spec → plan → tasks → implementation OPERATIONAL READINESS - Laravel Sail for local development - Dokploy deployment documentation - Queue/worker ready architecture - Migration safety notes - Environment variable documentation Tests: 36 passed Duration: 11.21s Status: Production-ready (98% complete)
319 lines
18 KiB
Markdown
319 lines
18 KiB
Markdown
---
|
||
|
||
description: "Task list for TenantPilot v1 implementation"
|
||
---
|
||
|
||
# Tasks: TenantPilot v1
|
||
|
||
**Input**: Design documents from `.specify/spec.md` and `.specify/plan.md`
|
||
**Prerequisites**: plan.md (complete), spec.md (complete)
|
||
|
||
## Phase 1: Setup (Shared Infrastructure)
|
||
|
||
- [x] T001 [P] [Shared] Confirm Sail/Env ready; ensure `.env` has PostgreSQL settings for Sail and Filament admin user seeded (if missing) in `database/seeders/`.
|
||
- [x] T002 [P] [Shared] Add baseline docs for local dev and staging promotion notes in `README.md` (Sail commands, staging-before-prod reminder).
|
||
|
||
## Phase 2: Foundational (Blocking Prerequisites)
|
||
|
||
- [x] T003 [Shared] Add tenant-aware migrations for `tenants`, `policies`, `policy_versions`, `backup_sets`, `backup_items`, `restore_runs`, `audit_logs` with JSONB payloads and FK/time indexes in `database/migrations/`.
|
||
- [x] T004 [Shared] Create models with relationships and guarded attributes for the above entities in `app/Models/`.
|
||
- [x] T005 [Shared] Implement Graph abstraction contracts (`GraphClientInterface`, error mapping, logging hooks) in `app/Services/Graph/` with a mockable adapter.
|
||
- [x] T006 [Shared] Add audit logging service/helper to capture actor, tenant, operation, resources, outcome in `app/Services/Intune/AuditLogger.php`.
|
||
- [x] T007 [Shared] Seed supported policy types/metadata for initial scope in `database/seeders/PoliciesSeeder.php` and ensure tenant scoping.
|
||
|
||
## Phase 3: User Story 1 - Policy inventory listing (Priority: P1)
|
||
|
||
### Tests for User Story 1
|
||
|
||
- [x] T008 [P] [US1] Feature test for Filament policy listing and filtering (tenant-scoped) in `tests/Feature/Filament/PolicyListingTest.php` using mocked Graph sync.
|
||
|
||
### Implementation for User Story 1
|
||
|
||
- [x] T009 [US1] Implement policy sync/import orchestrator using Graph abstraction in `app/Services/Intune/PolicySyncService.php` (no direct Graph in UI).
|
||
- [x] T010 [US1] Create Filament resource/table for policies with filters and metadata columns in `app/Filament/Resources/PolicyResource.php`.
|
||
- [x] T011 [US1] Add command/job to sync policies (queues-ready) in `app/Console/Commands/SyncPolicies.php` and queue job under `app/Jobs/`.
|
||
|
||
## Phase 4: User Story 2 - Backup creation and browsing (Priority: P1)
|
||
|
||
### Tests for User Story 2
|
||
|
||
- [x] T012 [P] [US2] Feature test for creating backup sets with multiple policies and verifying immutable JSONB snapshots + audit log in `tests/Feature/Filament/BackupCreationTest.php`.
|
||
|
||
### Implementation for User Story 2
|
||
|
||
- [x] T013 [US2] Implement backup domain service to assemble snapshots from policies with Graph payload retrieval in `app/Services/Intune/BackupService.php`.
|
||
- [x] T014 [US2] Add Filament resource/pages for backup sets and items (list/detail) in `app/Filament/Resources/BackupSetResource.php`.
|
||
- [x] T131 [UX] [US2] Refactor BackupSet policy selection to RelationManager:
|
||
- Remove the multi-select policy picker from the BackupSet **Create** form (keep Create minimal: name/description).
|
||
- After create, redirect to BackupSet **Edit/View** where items can be managed.
|
||
- Add `BackupItemsRelationManager` to `BackupSetResource` showing a table with columns: Policy Name, Type (badge), Restore (badge), Risk (badge).
|
||
- Add header action “Policies hinzufügen” (searchable, multiple) that adds items/attaches policies **tenant-scoped** and prevents duplicates per BackupSet.
|
||
- Provide a remove action (detach/soft-delete as per domain rules).
|
||
|
||
- [x] T132 [P] [US2] Update/extend `tests/Feature/Filament/BackupCreationTest.php` to cover the new UX flow:
|
||
- Create BackupSet without policies.
|
||
- Add multiple policies via RelationManager action.
|
||
- Verify immutable JSONB snapshots + audit log behavior remains correct.
|
||
- [x] T015 [US2] Wire audit logging for backup creation events in `app/Services/Intune/BackupService.php` using `AuditLogger`.
|
||
|
||
## Phase 5: User Story 3 - Version history and diff (Priority: P1)
|
||
|
||
### Tests for User Story 3
|
||
|
||
- [x] T016 [P] [US3] Feature test for version capture and timeline display in `tests/Feature/Filament/PolicyVersionTest.php`.
|
||
- [x] T017 [P] [US3] Unit test for diff generation (human summary + JSON diff) in `tests/Unit/VersionDiffTest.php`.
|
||
|
||
### Implementation for User Story 3
|
||
|
||
- [x] T018 [US3] Implement version capture service with immutable JSONB writes in `app/Services/Intune/VersionService.php`.
|
||
- [x] T019 [US3] Create diff helper (summary + structured JSON) in `app/Services/Intune/VersionDiff.php` and surface in Filament version compare view in `app/Filament/Resources/PolicyVersionResource.php`.
|
||
- [x] T020 [US3] Hook version capture into relevant flows (manual trigger + backup/restore hooks) ensuring audit logging.
|
||
|
||
## Phase 6: User Story 4 - Restore with preview and confirmation (Priority: P1)
|
||
|
||
### Tests for User Story 4
|
||
|
||
- [x] T021 [P] [US4] Feature test for restore preview (change summary, conflicts, selective items) in `tests/Feature/Filament/RestorePreviewTest.php`.
|
||
- [x] T022 [P] [US4] Feature test for confirmed restore execution capturing audit logs and per-item outcomes in `tests/Feature/Filament/RestoreExecutionTest.php`.
|
||
|
||
### Implementation for User Story 4
|
||
|
||
- [x] T023 [US4] Implement restore service with preview/dry-run and selective item application in `app/Services/Intune/RestoreService.php`, integrating Graph adapter and conflict detection.
|
||
- [x] T024 [US4] Add Filament restore UI (wizard or pages) showing preview, warnings, and confirmation gate in `app/Filament/Resources/RestoreRunResource.php`.
|
||
- [x] T025 [US4] Record restore run lifecycle (start, per-item result, completion) and audit events in `restore_runs` and `audit_logs`.
|
||
|
||
## Phase 7: User Story 5 - Operational readiness and environments (Priority: P2)
|
||
|
||
### Implementation for User Story 5
|
||
|
||
- [x] T026 [US5] Document Dokploy staging→production promotion steps, required env vars, queue/worker expectations, and migration safety notes in `README.md` or `docs/deploy.md`.
|
||
- [x] T027 [US5] Add quick Sail commands and test invocation notes to `README.md` (e.g., `./vendor/bin/sail artisan test`) and ensure sample env entries for Graph credentials.
|
||
## Phase 8: User Story 6 - Tenant hinzufügen & Entra ID App-Setup (Priority: P1)
|
||
|
||
- [x] T030 [US6] Migration für `tenants` ergänzen/prüfen:
|
||
- Felder: `name`, `tenant_id` (GUID), `domain`, `app_client_id`, `app_status`, `app_notes`,
|
||
`created_at`, `updated_at`.
|
||
- Optional: Felder für Secret/Certificate-Config (verschlüsselt), falls benötigt.
|
||
|
||
- [x] T031 [US6] Eloquent Model `Tenant`:
|
||
- Beziehungen zu `policies`, `backup_sets`, `restore_runs`, `policy_versions`, `audit_logs`
|
||
über `tenant_id`.
|
||
- Tenant-aware Scopes, falls vorhanden (z. B. `forTenant()`).
|
||
|
||
- [x] T032 [US6] Filament-Resource `TenantResource`:
|
||
- Listenansicht: Name, Tenant ID, Domain, App-Status, erstellt/am.
|
||
- Create/Edit-Form: Name, Tenant ID, Domain, App-Client-ID, optionale Notizen.
|
||
- Detailseite mit Actions:
|
||
- „Open in Entra“ (Link zur App/Tenant im Entra-Portal),
|
||
- optional: „Copy Admin Consent URL“.
|
||
|
||
- [x] T033 [US6] `TenantConfigService` (oder Erweiterung des Graph-Clients):
|
||
- Methode `testConnectivity(Tenant $tenant)`: führt einen einfachen Graph-Call aus
|
||
(z. B. `/organization` oder ähnliches) mit den App-Daten des Tenants.
|
||
- Rückgabe: DTO/Array mit `success`, `error_message` (falls vorhanden).
|
||
|
||
- [x] T034 [US6] Action „Verify configuration“ in `TenantResource`:
|
||
- Ruft `testConnectivity()` auf,
|
||
- setzt `app_status` auf z. B. `ok`, `error` oder `consent_required`,
|
||
- zeigt eine Filament-Notification mit dem Ergebnis,
|
||
- schreibt einen Audit-Log-Eintrag (`tenant.config.verified`).
|
||
|
||
- [x] T035 [US6] Tenant-Kontext in bestehende Services integrieren:
|
||
- `PolicySyncService`, `BackupService`, `RestoreService` so anpassen,
|
||
dass sie einen `Tenant` oder `tenant_id` übergeben bekommen
|
||
und den Graph-Client mit diesem Kontext verwenden.
|
||
- Sicherstellen, dass alle policy/backup/restore/audit-Datensätze `tenant_id` setzen.
|
||
|
||
- [x] T036 [US6] Feature-Test `TenantSetupTest`:
|
||
- Erstellen eines Tenants via Filament (Create-Form).
|
||
- Aufruf der Action „Verify configuration“ mit gemocktem Graph-Client:
|
||
- einmal mit erfolgreichem Call → `app_status = ok`,
|
||
- einmal mit Fehler → `app_status = error` + passende Notification.
|
||
- Prüfen, dass Audit-Logs geschrieben werden.
|
||
|
||
- [x] T037 [US6] Admin-Consent Callback Route
|
||
- Route/Controller, der als `redirect_uri` der Entra-ID-App dient.
|
||
- Liest `tenant` / `error` / `admin_consent` aus der Query.
|
||
- Ordnet das dem richtigen `Tenant` zu (z. B. via `state`).
|
||
- Aktualisiert `app_status` (z. B. `ok`, `error`, `consent_denied`).
|
||
- Zeigt eine Bestätigungs-/Fehlerseite für den Admin.
|
||
---
|
||
|
||
## Phase 9: User Story 7 - Berechtigungsübersicht & Health-Status (Priority: P1)
|
||
|
||
- [x] T040 [US7] Zentrale Permissions-Liste anlegen:
|
||
- `config/intune_permissions.php` mit allen aktuell benötigten Graph-Berechtigungen:
|
||
- technischer Name (z. B. `DeviceManagementConfiguration.ReadWrite.All`),
|
||
- Typ: `application` / `delegated`,
|
||
- kurze Beschreibung,
|
||
- Feature-Tags (z. B. `["policy-sync", "backup"]`).
|
||
- Optional: `docs/permissions.md` mit einer Tabelle Feature ↔ Permission als
|
||
menschlich lesbare Referenz.
|
||
|
||
- [x] T041 [US7] Datenmodell für Tenant-Berechtigungen:
|
||
- Variante A (einfach): JSONB-Feld `granted_permissions` in `tenants` (Liste von Permission-Keys).
|
||
- Variante B (feiner): Tabelle `tenant_permissions` mit
|
||
`(tenant_id, permission_key, status, last_checked_at)`.
|
||
- `status` mindestens: `ok`, `missing`, `error`.
|
||
|
||
- [x] T042 [US7] Service `TenantPermissionService`:
|
||
- `getRequiredPermissions(): array` – liest aus `config/intune_permissions.php`.
|
||
- `getGrantedPermissions(Tenant $tenant): array` – liest aus Graph oder aus
|
||
`tenant_permissions`/`granted_permissions`.
|
||
- `compare(Tenant $tenant): TenantPermissionStatusDTO` – liefert pro Permission
|
||
den Status (ok/missing/error) + Gesamthealth.
|
||
|
||
- [x] T043 [US7] Integration in Tenant-Detail-UI:
|
||
- Auf der `TenantResource`-Detailseite ein Panel/Section „Permissions“:
|
||
- Liste aller **required permissions**,
|
||
- pro Zeile: Name, Typ, Feature-Tags, Status (Icon + Label: OK/fehlt/Fehler).
|
||
- Optional: Link zu Doku oder Entra-Darstellung (z. B. „How to grant these permissions“).
|
||
|
||
- [x] T044 [US7] Action „Verify configuration“ erweitern:
|
||
- Zusätzlich zu `testConnectivity()` auch `TenantPermissionService::compare()` aufrufen.
|
||
- Ergebnisse in `tenant_permissions`/`granted_permissions` speichern.
|
||
- `app_status` und Permission-Health aktualisieren.
|
||
- Audit-Log-Eintrag `tenant.permissions.checked` schreiben.
|
||
|
||
- [x] T045 [US7] Tests für Permissions:
|
||
- Unit-Tests für `TenantPermissionService::compare()`:
|
||
- Szenarien: alle ok, Permission fehlt, Graph-Error.
|
||
- Feature-Test für Tenant-Detailseite:
|
||
- required permissions werden angezeigt,
|
||
- fehlende werden als fehlend markiert,
|
||
- „Verify configuration“ aktualisiert den Status wie erwartet.
|
||
|
||
## Phase 9b: Scope-Ausrichtung auf neue Objekttypen
|
||
|
||
- [x] T028 [Scope] Konfiguration `config/tenantpilot.php` auf die in `scope.supported_types` definierten Objekttypen erweitern (type/key, endpoint, label/category, optional risk/restore-Hinweis). Sicherstellen, dass diese Liste die einzige Quelle für Policy-Sync/Backup/Restore ist.
|
||
- [x] T029 [Scope] Filament-UI an neue Typen anpassen: Tabellenfilter/Grouping nach Kategorie (z. B. Config/Compliance/Scripts/Apps/CA), Backup/Restore-Formulare mit Hinweisen zu Restore-Level aus `scope.restore_matrix` (z. B. CA/enrollment restrictions = preview-only).
|
||
|
||
|
||
## Phase 10: Housekeeping – Delete-Funktionen für Backups & Versions
|
||
|
||
- [x] T060 [HK] BackupSets soft deletable machen:
|
||
- `backup_sets` (und ggf. `backup_items`) Migration/Model mit `SoftDeletes` (deleted_at).
|
||
- Sicherstellen, dass RestoreRuns keine gelöschten BackupSets verwenden; Delete nur erlauben,
|
||
wenn keine zugehörigen RestoreRuns existieren.
|
||
|
||
- [x] T061 [HK] Filament-Delete-Action für BackupSets:
|
||
- In `BackupSetResource` Delete-Action in List- und/oder Detail-View hinzufügen.
|
||
- Mit Confirmation-Dialog (“This will archive this backup set and hide it from the UI.”).
|
||
- Delete disabled/hidden, wenn `restore_runs` für das Set existieren.
|
||
- Nach Delete Audit-Log (`backup.deleted`) schreiben.
|
||
|
||
- [x] T062 [HK] PolicyVersions soft deletable machen:
|
||
- `policy_versions` Migration/Model um `SoftDeletes` erweitern.
|
||
- Alle Queries und Filament-Resources so lassen, dass standardmäßig nur non-deleted Versions
|
||
angezeigt werden.
|
||
|
||
- [x] T063 [HK] Filament-Delete-Action für PolicyVersions:
|
||
- In `PolicyVersionResource` Delete-Action hinzufügen (List/Detail).
|
||
- Confirmation + Audit-Log (`policy_version.deleted`).
|
||
|
||
- [x] T064 [HK] Tests für Housekeeping:
|
||
- Feature-Test: Löschen eines BackupSets ohne RestoreRun → `deleted_at` gesetzt, UI-Eintrag weg,
|
||
Audit-Log vorhanden.
|
||
- Feature-Test: BackupSet mit RestoreRun → Delete-Action nicht verfügbar.
|
||
- Feature-Test: Löschen einer PolicyVersion → `deleted_at` gesetzt, nicht mehr in List sichtbar.
|
||
|
||
## Phase 11: Housekeeping – Tenant löschen/deaktivieren
|
||
|
||
- [x] T070 [HK] Tenants soft deletable machen:
|
||
- `tenants` Model um `SoftDeletes` erweitern, Migration ggf. `deleted_at` hinzufügen.
|
||
- Optional: Feld `status` (enum/string: `active`, `archived`) einführen; beim Delete auf `archived` setzen.
|
||
- Alle Standard-Queries für Tenants nur `active` / nicht gelöscht anzeigen.
|
||
|
||
- [x] T071 [HK] Tenant-Delete-Action (Deaktivieren) in `TenantResource`:
|
||
- Delete-/Archive-Action in der Tenant-Liste und/oder Detailseite hinzufügen.
|
||
- Deutlich machen: “Deaktiviert diesen Tenant. Historische Daten bleiben vorhanden, neue Aktionen
|
||
sind nicht mehr möglich.”
|
||
- Bei Ausführung:
|
||
- `deleted_at` setzen (und ggf. `status = archived`),
|
||
- Audit-Log `tenant.deleted` oder `tenant.archived` schreiben.
|
||
|
||
- [x] T072 [HK] Verhalten für deaktivierte Tenants:
|
||
- In `PolicySyncService`, `BackupService`, `RestoreService` prüfen, dass nur aktive Tenants
|
||
verwendet werden; bei deaktiviertem Tenant frühzeitig mit verständlicher Fehlermeldung abbrechen.
|
||
- In Filament-Navigation Tenants, Policies, Backups, Restores eines deaktivierten Tenants nicht
|
||
mehr in Standard-Listen anzeigen (es sei denn, es gibt explizite “Show archived”-Filter).
|
||
|
||
- [x] T073 [HK] (Optional) RestoreRuns soft deletable machen:
|
||
- `restore_runs` Model/Migration mit `SoftDeletes`.
|
||
- Delete-Action in `RestoreRunResource` hinzufügen (nur UI-Aufräumung, keine Folgen für Backups).
|
||
- Audit-Log `restore_run.deleted` schreiben.
|
||
|
||
- [x] T074 [HK] Tests für Tenant-Delete:
|
||
- Feature-Test: Tenant löschen/deaktivieren → Tenant taucht nicht mehr in Standardlisten auf,
|
||
`deleted_at` (und `status`) ist gesetzt, Audit-Event existiert.
|
||
- Feature-Test: Versuch, mit deaktiviertem Tenant einen Policy-Sync/Backup/Restore zu starten,
|
||
führt zu einem klaren Fehler (und kein Graph-Call wird ausgeführt).
|
||
|
||
## Phase 12: Housekeeping – Hard Deletes (Force Delete)
|
||
|
||
- [x] T075 [HK] Force-Delete-Actions ergänzen:
|
||
- Filament-Listen für Tenants, BackupSets, PolicyVersions, RestoreRuns erhalten „Force delete“
|
||
Aktionen (sichtbar nur im Trashed-Filter), mit klarer Confirmation.
|
||
- BackupSets: Force delete nur, wenn keine RestoreRuns existieren; löscht Items mit.
|
||
- Tenants: Force delete nur, wenn archiviert; blockiert für aktive Tenants.
|
||
- Alle Force-Deletes schreiben Audit-Log-Einträge vor der endgültigen Löschung.
|
||
- Tests für Force-Delete-Flows (erfolgreich/blockiert) ergänzen.
|
||
## Phase 12: Single current tenant ("Highlander")
|
||
|
||
- [x] T120 [TENANT] Migration `add_is_current_to_tenants`:
|
||
- Spalte `is_current` (boolean, default false, not null) zu `tenants` hinzufügen.
|
||
- Partielle Unique-Index anlegen, z. B.:
|
||
- `UNIQUE INDEX tenants_current_unique ON tenants (is_current)
|
||
WHERE is_current = true AND deleted_at IS NULL`.
|
||
|
||
- [x] T121 [TENANT] Tenant-Model anpassen:
|
||
- Methode `makeCurrent()` implementieren:
|
||
- Transaktion: alle anderen Tenants `is_current = false`, dieser Tenant `is_current = true`.
|
||
- Methode `static current()` implementieren:
|
||
- Wenn `INTUNE_TENANT_ID` gesetzt ist → Tenant mit dieser GUID laden,
|
||
sonst Exception, wenn nicht gefunden / deaktiviert.
|
||
- Wenn nicht gesetzt → Tenant mit `is_current = true` und `status = active`
|
||
(und `deleted_at` null) zurückgeben.
|
||
- Wenn keiner → Exception “No current tenant selected”.
|
||
- `findOrCreateDefault()` deprecaten/entfernen; keine Dummy-Tenants mehr erzeugen.
|
||
|
||
- [x] T122 [TENANT] Data-Migration / Cleanup:
|
||
- Falls mindestens ein Tenant mit `app_status = ok` existiert:
|
||
- einen als `is_current = true` markieren (z. B. den ersten).
|
||
- `local-tenant` auf `status = archived`, `is_current = false` setzen.
|
||
- Sicherstellen, dass `local-tenant` nie wieder als aktueller Kontext verwendet wird.
|
||
|
||
- [x] T123 [TENANT] Filament `TenantResource` UI:
|
||
- Spalte/Badge für `is_current` in der Liste hinzufügen.
|
||
- Table-Action "Make current" ergänzen:
|
||
- nur sichtbar für aktive Tenants, die nicht `is_current` sind.
|
||
- ruft `makeCurrent()` auf und zeigt Notification.
|
||
- Alte Logik entfernen, die `local-tenant` automatisch als Default nutzt.
|
||
|
||
- [x] T124 [TENANT] Consumers refactoren:
|
||
- Alle Vorkommen von `findOrCreateDefault()` suchen und durch `Tenant::current()`
|
||
(oder expliziten Tenant) ersetzen:
|
||
- Policy-Sync (Command + Filament-Action),
|
||
- BackupSet-Erstellung,
|
||
- RestoreRun-Erstellung,
|
||
- ggf. weitere Services.
|
||
|
||
- [x] T125 [TENANT] Tests:
|
||
- Unit-Tests für `Tenant::current()`:
|
||
- INTUNE_TENANT_ID gesetzt → nimmt diesen Tenant, Fehler wenn nicht vorhanden.
|
||
- INTUNE_TENANT_ID nicht gesetzt → nimmt den mit `is_current = true`.
|
||
- kein current Tenant → Exception.
|
||
- Feature-Test für "Make current" in `TenantResource`:
|
||
- Nach der Action ist genau ein Tenant `is_current = true`, alle anderen `false`.
|
||
- Optional: Test, dass `local-tenant` nach Cleanup nicht mehr als Kontext gewählt wird.
|
||
|
||
- [x] T130 [UX] Tabellen-Aktionen in Dropdown bündeln (ActionGroup)
|
||
- In `TenantResource` (Tenants-Liste) die Zeilen-Aktionen refaktorieren:
|
||
- `View` (optional) direkt anzeigen.
|
||
- Alle weiteren Aktionen (`Edit`, `Admin consent`, `Verify configuration`,
|
||
`Deactivate`, `Force delete`) in eine `Tables\Actions\ActionGroup` mit
|
||
"⋯"-Icon verschieben.
|
||
- Prüfen, ob in anderen Ressourcen mit vielen Row-Actions (z.B. Backups,
|
||
RestoreRuns) ebenfalls eine `ActionGroup` sinnvoll ist und diese konsistent
|
||
einsetzen.
|