## Summary - introduce a shared tenant-owned query and record-resolution canon for first-slice Filament resources - harden direct views, row actions, bulk actions, relation managers, and workspace-admin canonical viewers against wrong-tenant access - add registry-backed rollout metadata, search posture handling, architectural guards, and focused Pest coverage for scope parity and 404/403 semantics ## Included - Spec 150 package under `specs/150-tenant-owned-query-canon-and-wrong-tenant-guards/` - shared support classes: `TenantOwnedModelFamilies`, `TenantOwnedQueryScope`, `TenantOwnedRecordResolver` - shared Filament concern: `InteractsWithTenantOwnedRecords` - resource/page/policy hardening across findings, policies, policy versions, backup schedules, backup sets, restore runs, inventory items, and Entra groups - additional regression coverage for canonical tenant state, wrong-tenant record resolution, relation-manager congruence, and action-surface guardrails ## Validation - `vendor/bin/sail artisan test --compact` passed - full suite result: `2733 passed, 8 skipped` - formatting applied with `vendor/bin/sail bin pint --dirty --format agent` ## Notes - Livewire v4.0+ compliant via existing Filament v5 stack - provider registration remains in `bootstrap/providers.php` - globally searchable first-slice posture: Entra groups scoped; policies and policy versions explicitly disabled - destructive actions continue to use confirmation and policy authorization - no new Filament assets added; existing deployment flow remains unchanged, including `php artisan filament:assets` when registered assets are used Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #180
118 lines
6.4 KiB
Markdown
118 lines
6.4 KiB
Markdown
# Admin Canonical Tenant Rollout
|
|
|
|
## Purpose
|
|
|
|
Spec 136 completes the workspace-admin canonical tenant rule across admin-visible and admin-reachable shared surfaces. Workspace-admin requests under `/admin/...` resolve tenant context through `App\Support\OperateHub\OperateHubShell::activeEntitledTenant(request())`. Tenant-panel requests under `/admin/t/{tenant}/...` keep panel-native tenant semantics.
|
|
|
|
## Rollout Manifest
|
|
|
|
### Type A: Hard tenant-sensitive
|
|
|
|
- `app/Filament/Resources/PolicyResource.php`
|
|
- `app/Filament/Resources/BackupScheduleResource.php`
|
|
- `app/Filament/Resources/BackupSetResource.php`
|
|
- `app/Filament/Resources/FindingResource.php`
|
|
- `app/Filament/Pages/BaselineCompareLanding.php`
|
|
- `app/Filament/Resources/RestoreRunResource.php`
|
|
- `app/Filament/Resources/InventoryItemResource.php`
|
|
- `app/Filament/Resources/PolicyVersionResource.php`
|
|
- `app/Filament/Pages/TenantDiagnostics.php`
|
|
- `app/Filament/Pages/InventoryCoverage.php`
|
|
- `app/Filament/Widgets/Inventory/InventoryKpiHeader.php`
|
|
|
|
### Type B: Workspace-wide with tenant-default behavior
|
|
|
|
- `app/Filament/Resources/ProviderConnectionResource.php`
|
|
- `app/Filament/Pages/Monitoring/AuditLog.php`
|
|
- `app/Filament/Resources/EntraGroupResource.php`
|
|
- `app/Filament/Resources/AlertDeliveryResource.php`
|
|
|
|
### Type C: Workspace-only non-regression references
|
|
|
|
- `app/Filament/Resources/AlertRuleResource.php`
|
|
- `app/Filament/Resources/BaselineProfileResource.php`
|
|
- `app/Filament/Resources/BaselineSnapshotResource.php`
|
|
- `app/Filament/Resources/TenantResource.php`
|
|
|
|
## Persisted Filter Sync
|
|
|
|
Apply `App\Support\Filament\CanonicalAdminTenantFilterState::sync()` on admin list surfaces that persist filters in session.
|
|
|
|
- `app/Filament/Resources/AlertDeliveryResource/Pages/ListAlertDeliveries.php`
|
|
- `app/Filament/Pages/Monitoring/AuditLog.php`
|
|
- `app/Filament/Resources/BackupScheduleResource/Pages/ListBackupSchedules.php`
|
|
- `app/Filament/Resources/BackupSetResource/Pages/ListBackupSets.php`
|
|
- `app/Filament/Resources/FindingResource/Pages/ListFindings.php`
|
|
- `app/Filament/Resources/InventoryItemResource/Pages/ListInventoryItems.php`
|
|
- `app/Filament/Resources/PolicyVersionResource/Pages/ListPolicyVersions.php`
|
|
- `app/Filament/Resources/ProviderConnectionResource/Pages/ListProviderConnections.php`
|
|
- `app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php`
|
|
|
|
## Guarded Files
|
|
|
|
These files must not introduce raw admin-path `Tenant::current()` or `Filament::getTenant()` reads:
|
|
|
|
- `app/Filament/Pages/BaselineCompareLanding.php`
|
|
- `app/Filament/Pages/TenantDiagnostics.php`
|
|
- `app/Filament/Pages/InventoryCoverage.php`
|
|
- `app/Filament/Widgets/Inventory/InventoryKpiHeader.php`
|
|
- `app/Filament/Resources/PolicyResource.php`
|
|
- `app/Filament/Resources/BackupScheduleResource.php`
|
|
- `app/Filament/Resources/InventoryItemResource.php`
|
|
- `app/Filament/Resources/PolicyVersionResource.php`
|
|
- `app/Filament/Resources/ProviderConnectionResource.php`
|
|
- `app/Filament/Resources/AlertDeliveryResource.php`
|
|
- `app/Filament/Resources/AlertDeliveryResource/Pages/ListAlertDeliveries.php`
|
|
- `app/Filament/Pages/Monitoring/AuditLog.php`
|
|
- `app/Filament/Resources/ProviderConnectionResource/Pages/ListProviderConnections.php`
|
|
|
|
## Exception Inventory
|
|
|
|
Approved tenant-panel-native or bootstrapping exceptions:
|
|
|
|
- `app/Filament/Pages/ChooseTenant.php`
|
|
- `app/Http/Controllers/SelectTenantController.php`
|
|
- `app/Support/Middleware/EnsureFilamentTenantSelected.php`
|
|
- `app/Filament/Concerns/ResolvesPanelTenantContext.php`
|
|
|
|
`app/Filament/Concerns/ResolvesPanelTenantContext.php` is the only shared internal delegation wrapper allowed for this rollout. It is not a new public resolver. Admin semantics still come from `OperateHubShell`.
|
|
|
|
## Global Search
|
|
|
|
- `PolicyResource`: global search disabled explicitly.
|
|
- `PolicyVersionResource`: global search disabled explicitly.
|
|
- `EntraGroupResource`: global search remains enabled and uses admin-aware scoping with a View page.
|
|
|
|
## Future-Surface Rule
|
|
|
|
Any new admin-visible or admin-reachable tenant-sensitive Filament surface must:
|
|
|
|
- resolve workspace-admin tenant context through `OperateHubShell` or the internal `ResolvesPanelTenantContext` helper
|
|
- route tenant-owned list/detail resolution through the shared `InteractsWithTenantOwnedRecords` helper where the surface is tenant-owned
|
|
- keep tenant-panel requests panel-native
|
|
- synchronize persisted tenant-derived filters before render when `persistFiltersInSession()` is used
|
|
- disable global search unless list, detail, and search parity are explicitly tenant-safe
|
|
- keep destructive actions on `->action(...)` with `->requiresConfirmation()` and server-side authorization
|
|
|
|
## Verification Log
|
|
|
|
### Wave 1
|
|
|
|
- 2026-03-11: automated parity coverage added for representative tenant-sensitive resources and admin list scoping.
|
|
- 2026-03-12: manual tenant-switch verification completed on `/admin/findings` with `Phoenicon (DEV)` and `YPTW2 (DEV)`.
|
|
- 2026-03-12: the admin shell changed visible finding rows and row-action tenant IDs together after switching tenants, confirming header context, list queries, and deep links stayed aligned.
|
|
|
|
### Wave 2
|
|
|
|
- 2026-03-11: automated stale-filter and tenant-default coverage added for persisted filter surfaces.
|
|
- 2026-03-12: manual verification completed on `/admin/inventory/inventory-coverage` after fixing remembered-canonical-tenant handling in `EnsureFilamentTenantSelected`.
|
|
- 2026-03-12: switching from `YPTW2 (DEV)` to `Phoenicon (DEV)` changed tenant-driven KPI values while the shared support-matrix table remained available, confirming page-widget parity and the expected safe no-data state.
|
|
- 2026-03-12: tenant-panel navigation under `/admin/t/{tenant}/...` remained route-bound and required explicit tenant switching through the chooser flow instead of reusing remembered admin context.
|
|
|
|
### Wave 3
|
|
|
|
- 2026-03-11: guard inventory and shared-surface panel-split coverage updated for the canonical rollout.
|
|
- 2026-03-12: manual verification completed on `/admin/provider-connections` and confirmed the base dataset stays workspace-wide while the default tenant filter follows the active canonical admin tenant.
|
|
- 2026-03-12: clearing the tenant filter exposed workspace-wide provider connections, while switching back to another tenant reseeded the tenant-default pill and `tenant_id` deep links for the newly selected tenant.
|
|
- 2026-03-12: admin search safety remained unchanged from the rollout contract: `PolicyResource` and `PolicyVersionResource` stay disabled for global search, and `EntraGroupResource` keeps admin-aware global search with a View page.
|