Implements platform feature branch `302-tenant-owned-surface-route-audit`. Target branch: `platform-dev`. Follow-up integration path after merge: `platform-dev` → `dev`. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #357
27 KiB
Tenant-Owned Surface Route Audit
Spec: 302 tenant-owned-surface-route-audit
Date: 2026-05-14
Branch: 302-tenant-owned-surface-route-audit
Scope: repo-derived audit artifact only
Scope Boundary
This audit records current route, navigation, context, global-search, and RBAC posture for admin-relevant tenant-owned surfaces. It does not change application runtime behavior.
Out of scope for this spec:
- application runtime code
- application tests
- routes
- migrations
- assets
- policies
- jobs
- Filament resources, pages, clusters, widgets, or Livewire components
Any runtime defect or product decision discovered here is documented as a blocker or follow-up candidate instead of being patched in this spec.
Audit Method
Primary repo sources:
apps/platform/app/Support/WorkspaceIsolation/TenantOwnedModelFamilies.phpapps/platform/app/Filament/Concerns/WorkspaceScopedTenantRoutes.phpapps/platform/app/Support/Navigation/NavigationScope.phpapps/platform/app/Filament/Concerns/ScopesGlobalSearchToTenant.phpapps/platform/app/Filament/Concerns/ResolvesPanelTenantContext.phpapps/platform/app/Support/OperateHub/OperateHubShell.phpapps/platform/routes/web.phpapps/platform/app/Filament/Resources/apps/platform/app/Filament/Pages/- focused tests under
apps/platform/tests/Feature/Filament/
Filament documentation was checked through Laravel Boost for the current stack. Relevant conclusions for this audit:
- Filament v5 targets Livewire v4.0+ in this app; no Livewire v3 patterns are introduced.
shouldRegisterNavigation()controls navigation registration only and is not an authorization boundary.- A globally searchable Filament resource needs an Edit or View page to provide truthful destinations.
- Destructive Filament actions should execute through
Action::make(...)->action(...)and include->requiresConfirmation(). This spec adds or changes no actions. - URL-only actions should not be treated as confirmation-protected mutations.
Classification Vocabulary
Each audited row has exactly one migration state:
migrated: route, environment navigation, context, search posture, RBAC, and proof are aligned for the current intended admin contract.partial cutover: substantial route/context migration exists, but proof or adjacent entry-point behavior remains incomplete.stale panel logic: current behavior still preserves an older hide-first or panel-split assumption that conflicts with repo-real admin access.valid context gate: a surface is intentionally contextual/subordinate and does not need a standalone route, but still requires trusted workspace/environment context.valid RBAC: the current posture is primarily an authorization exception rather than a route/navigation migration target.ambiguous product IA: implementation cannot safely proceed until the product role of the surface is decided.dead-code dependent: cleanup depends on earlier route/navigation decisions and should not be performed first.
First-Slice Surface Matrix
| Surface | Model/resource/page owner | Route posture | Navigation posture | Context source | Global-search posture | RBAC posture | Existing proof | Blocker | Migration state | Recommended next action |
|---|---|---|---|---|---|---|---|---|---|---|
| Policy | Policy / PolicyResource |
Admin URLs use WorkspaceScopedTenantRoutes under /admin/workspaces/{workspace}/environments/{environment}/policies; list and view pages exist. |
Environment-only via NavigationScope::shouldRegisterEnvironmentNavigation(); workspace home stays clean. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Disabled by resource and registry; PolicyResource has a View page if search is later re-enabled. |
canViewAny() requires tenant membership plus tenant.view; row/detail access uses tenant-owned resolution. |
PanelNavigationSegregationTest, TenantOwnedResourceScopeParityTest, AdminTenantSurfaceParityTest, PolicyResourceAdminSearchParityTest, GovernanceArtifactAdminPanelRegistrationTest. |
None for route audit. | migrated | Keep as reference contract for future tenant-owned resources. |
| PolicyVersion | PolicyVersion / PolicyVersionResource |
Admin URLs use WorkspaceScopedTenantRoutes; list and view pages exist. |
Environment-only via NavigationScope; workspace home stays clean. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Disabled by resource and registry; View page exists if search is later re-enabled. | canViewAny() requires tenant membership plus tenant.view; detail resolution is tenant-owned. |
PanelNavigationSegregationTest, TenantOwnedResourceScopeParityTest, AdminTenantSurfaceParityTest, PolicyVersionAdminSearchParityTest, GovernanceArtifactAdminPanelRegistrationTest. |
None for route audit. | migrated | Keep search disabled until a separate policy-version search spec defines destination copy and ranking. |
| BackupSchedule | BackupSchedule / BackupScheduleResource |
Admin URLs use WorkspaceScopedTenantRoutes; list, create, and edit pages exist. |
Environment-only via NavigationScope; workspace home stays clean. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Not applicable in registry. | Tenant membership and capabilities are enforced through resource methods and action-level UI enforcement. | PanelNavigationSegregationTest, TenantOwnedResourceScopeParityTest, GovernanceArtifactAdminPanelRegistrationTest. |
None for route audit. | migrated | No follow-up in this candidate group. |
| BackupSet | BackupSet / BackupSetResource |
Admin URLs use WorkspaceScopedTenantRoutes; list, create, view pages exist; BackupItemsRelationManager is subordinate. |
Environment-only via NavigationScope; workspace home stays clean. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Not applicable in registry. | Tenant membership/capability checks protect list/detail and restore/export actions. | PanelNavigationSegregationTest, TenantOwnedResourceScopeParityTest, AdminSharedSurfacePanelParityTest, GovernanceArtifactAdminPanelRegistrationTest. |
None for route audit. | migrated | Keep BackupItem as subordinate relation-manager coverage; do not invent standalone route. |
| RestoreRun | RestoreRun / RestoreRunResource |
Admin URLs use WorkspaceScopedTenantRoutes; list, create, view pages exist. |
Environment-only via NavigationScope; workspace home stays clean. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Not applicable in registry. | Tenant membership/capability gates protect tenant-owned restore history and restore mutation flows. | PanelNavigationSegregationTest, TenantOwnedResourceScopeParityTest, GovernanceArtifactAdminPanelRegistrationTest. |
None for route audit. | migrated | Keep separate from workspace-owned OperationRunResource. |
| Finding | Finding / FindingResource |
Admin URLs use WorkspaceScopedTenantRoutes; list and view pages exist. |
Environment-only via NavigationScope; workspace home stays clean. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Not applicable in registry. | Tenant membership/capability checks protect finding visibility and workflows. | PanelNavigationSegregationTest, TenantOwnedResourceScopeParityTest, GovernanceArtifactAdminPanelRegistrationTest, finding RBAC/evidence feature coverage. |
None for route audit. | migrated | No follow-up in this candidate group. |
| FindingException | FindingException / FindingExceptionResource |
Admin URLs use WorkspaceScopedTenantRoutes; list and view pages exist. |
Environment-only via NavigationScope; workspace home is expected to stay clean. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Disabled by resource and registry; View page exists if later re-enabled. | Tenant membership/capability checks protect risk-exception visibility and decision actions. | PanelNavigationSegregationTest sidebar assertions, GovernanceArtifactAdminPanelRegistrationTest, exception/action guard tests. |
High-signal navigation dataset covers sidebar text but not the class-level environment-visible dataset. | partial cutover | Add to the next navigation-contract proof pass or a bounded governance-artifact navigation parity check; no runtime change in this audit. |
| EvidenceSnapshot | EvidenceSnapshot / EvidenceSnapshotResource |
Admin URLs use WorkspaceScopedTenantRoutes; list and view pages exist. |
Environment-only via NavigationScope; environment sidebar proof exists by text but not in the primary class dataset. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Disabled by resource and registry; View page exists if later re-enabled. | canViewAny() / canView() require tenant access plus evidence.view; generation action requires evidence.manage. |
GovernanceArtifactAdminPanelRegistrationTest, GovernanceArtifactEnvironmentContextTest, governance artifact deep-link tests, browser governance smoke coverage. |
Proof is split across governance tests rather than the core navigation segregation dataset. | partial cutover | Create a small governance-artifact environment navigation parity follow-up only if reviewers want one canonical proof lane. |
| InventoryItem | InventoryItem / InventoryItemResource |
Admin URLs use WorkspaceScopedTenantRoutes; list and view pages exist. |
Environment-only via NavigationScope; workspace home stays clean after Spec 301. |
WorkspaceScopedTenantRoutes, explicit tenant query scope for detail, ResolvesPanelTenantContext. |
Not applicable in registry. | Tenant membership plus resource authorization; cross-tenant detail returns 404. | PanelNavigationSegregationTest, TenantOwnedResourceScopeParityTest, Inventory coverage/admin parity tests, GovernanceArtifactAdminPanelRegistrationTest. |
None after Spec 301. | migrated | Keep as completed reference for the candidate group. |
| EntraGroup | EntraGroup / EntraGroupResource |
Direct admin list/detail routes exist and are tenant-scoped through remembered canonical tenant context; resource does not use WorkspaceScopedTenantRoutes. |
shouldRegisterNavigation() returns false on the admin panel, even when an environment context exists. |
ScopesGlobalSearchToTenant, OperateHubShell::activeEntitledTenant(), InteractsWithTenantOwnedRecords, remembered workspace tenant. |
Scoped and enabled; View page exists and search results resolve to scoped detail URLs. | Direct list/detail/global search are tenant-scoped; no-context and cross-tenant access return no results or 404. | EntraGroupAdminScopeTest, EntraGroupGlobalSearchScopeTest, TenantOwnedResourceScopeParityTest, PanelNavigationSegregationTest admin-hidden dataset. |
Product IA is unresolved: groups may belong in primary Directory navigation, secondary Identity lane, or contextual-only entry points. Current admin-hidden test is stale if groups should be environment-visible. | ambiguous product IA | Promote admin-directory-groups-cutover next. Decide the Directory/Groups role, then align navigation, route helper posture, tests, and search-detail destinations. |
| EnvironmentReview | EnvironmentReview / EnvironmentReviewResource |
Admin URLs use WorkspaceScopedTenantRoutes; list and view pages exist. |
Environment-only via NavigationScope; workspace home stays clean. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Disabled by resource and registry. | Tenant access and review/evidence capabilities gate creation and visibility. | GovernanceArtifactAdminPanelRegistrationTest, GovernanceArtifactEnvironmentContextTest, customer-review tests. |
None for route audit. | migrated | No candidate-group follow-up; keep customer-review paths as separate review-domain work if needed. |
| StoredReport | StoredReport / StoredReportResource |
Admin URLs use WorkspaceScopedTenantRoutes; list and view pages exist. |
Environment-only via NavigationScope; navigation proof is governance-specific, not in the core segregation dataset. |
WorkspaceScopedTenantRoutes, ResolvesPanelTenantContext, tenant-owned query helpers. |
Disabled by resource and registry. | canViewAny() and canView() require report-type capabilities and matching workspace/environment. |
GovernanceArtifactAdminPanelRegistrationTest, GovernanceArtifactEnvironmentContextTest, dashboard report-link tests. |
Proof is split across governance/report tests rather than the core navigation segregation dataset. | partial cutover | Optionally include with EvidenceSnapshot in a bounded governance-artifact environment navigation parity proof. |
Residual, Subordinate, and Exception Surfaces
| Surface | Model/resource/page owner | Route posture | Navigation posture | Context source | Global-search posture | RBAC posture | Existing proof | Blocker | Migration state | Recommended next action |
|---|---|---|---|---|---|---|---|---|---|---|
| BackupItem | BackupItem via BackupSetResource::BackupItemsRelationManager |
Subordinate relation-manager surface under backup-set detail; no standalone primary route should be invented. | Inherits BackupSet visibility. | Parent BackupSet tenant context. |
Not applicable. | Inherits backup-set tenant membership/capability gates. | TenantOwnedModelFamilies::residualRolloutInventory(), backup-set relation manager declaration. |
None. | valid context gate | Keep subordinate; add proof only if relation-manager behavior changes. |
| InventoryLink | InventoryLink via InventoryItemResource related-link affordances |
Subordinate metadata under inventory item. | Inherits InventoryItem visibility. | Parent InventoryItem tenant context. |
Not applicable. | Inherits inventory item scope and link target authorization. | TenantOwnedModelFamilies::residualRolloutInventory(), inventory related-context tests. |
None. | valid context gate | Keep subordinate; no standalone route. |
| EntraRoleDefinition | EntraRoleDefinition via Entra admin-role reports/findings |
Indirect read paths through reports, findings, and role-posture evidence. | No standalone navigation in this slice. | Report/finding/evidence parent context. | Not applicable. | Must inherit parent report/finding capability gates. | TenantOwnedModelFamilies::residualRolloutInventory(), stored-report and finding evidence coverage. |
Directory/admin-role IA may need to align with the Entra Groups decision. | ambiguous product IA | Keep indirect unless admin-directory-groups-cutover creates a broader Directory/Admin Roles lane. |
| ManagedEnvironmentPermission | ManagedEnvironmentPermission via diagnostics, onboarding, required-permissions pages |
Contextual pages under /admin/workspaces/{workspace}/environments/{environment}/... or onboarding draft routes; no standalone resource. |
Diagnostics/required-permissions are contextual and not primary sidebar entries. | Route model binding, workspace middleware, selected tenant middleware, page-local access checks. | Not applicable. | Requires workspace membership and environment access; diagnostics mutation actions are capability-gated and confirmation-protected. | routes/web.php, EnvironmentDiagnostics, EnvironmentRequiredPermissions, onboarding tests. |
None for tenant-owned route audit. | valid context gate | Keep contextual; future diagnostics specs should maintain 404 for invalid environment context. |
| FindingExceptionDecision | FindingExceptionDecision via FindingExceptionResource detail/history |
Subordinate to finding exception aggregate. | Inherits FindingException visibility. | Parent finding-exception tenant context. | Not applicable. | Inherits finding-exception capability gates and action authorization. | TenantOwnedModelFamilies::residualRolloutInventory(), finding-exception workflow tests. |
None. | valid context gate | Keep subordinate; no standalone route. |
| FindingExceptionEvidenceReference | FindingExceptionEvidenceReference via FindingExceptionResource evidence sections |
Subordinate to finding exception aggregate. | Inherits FindingException visibility. | Parent finding-exception tenant context. | Not applicable. | Inherits finding-exception visibility plus evidence/report link authorization. | TenantOwnedModelFamilies::residualRolloutInventory(), governance evidence tests. |
None. | valid context gate | Keep subordinate; no standalone route. |
| ProviderConnectionResource | ProviderConnectionResource |
Workspace-admin canonical viewer that references tenant defaults; explicit first-slice exception. | Workspace/integration navigation, not tenant-owned environment navigation. | Workspace membership plus remembered tenant entitlement for destination actions. | Not applicable to first-slice tenant-owned search. | Capability gating remains required on destination/action paths. | TenantOwnedModelFamilies::scopeExceptions(), provider-connection scope/UI enforcement tests. |
None for tenant-owned route audit. | valid RBAC | Do not migrate into the tenant-owned family unless provider IA changes. |
| OperationRunResource / tenantless operation viewer | Workspace-owned operation monitoring plus tenant deep links | Workspace operation routes under /admin/workspaces/{workspace}/operations...; tenant-owned destinations must be checked before rendering. |
Workspace monitoring navigation; OperationRunResource itself is hidden from resource nav. |
Workspace route context plus operation owner/deep-link tenant checks. | Not applicable. | Workspace membership plus tenant entitlement on tenant-owned deep links. | TenantOwnedModelFamilies::scopeExceptions(), operation monitoring tests. |
None for tenant-owned route audit. | valid RBAC | Keep separate from RestoreRunResource; no route migration in this candidate group. |
| AlertDeliveryResource | AlertDeliveryResource |
Mixed workspace-owned and tenant-bound semantics; explicit deferred family. | Workspace alert navigation, not tenant-owned first-slice navigation. | Workspace context plus tenant capability checks for tenant-bound mutations. | Not applicable. | Workspace membership and tenant-specific mutation capability checks remain required. | TenantOwnedModelFamilies::scopeExceptions(), alert delivery/action tests. |
Deferred family; not enough product scope in this audit to classify all alert delivery tenant semantics. | partial cutover | Leave for a bounded alert-delivery route/RBAC audit if alert surfaces become part of this candidate group. |
Non-Resource Environment Pages
| Surface | Model/resource/page owner | Route posture | Navigation posture | Context source | Global-search posture | RBAC posture | Existing proof | Blocker | Migration state | Recommended next action |
|---|---|---|---|---|---|---|---|---|---|---|
| Environment dashboard | EnvironmentDashboard |
Canonical route /admin/workspaces/{workspace}/environments/{environment:slug} via ManagedEnvironmentLinks::viewUrl(). |
Environment landing page, not a resource nav row. | Route model binding, workspace member middleware, selected tenant middleware. | Not applicable. | Tenant dashboard widgets/actions use tenant access and capabilities. | routes/web.php, dashboard feature tests, PanelNavigationSegregationTest canonical environment route. |
None. | migrated | Keep as canonical environment context anchor. |
| Inventory coverage | InventoryCoverage page |
Admin URL resolves to /admin/workspaces/{workspace}/environments/{environment}/inventory/coverage style Filament page route; falls back to /admin without tenant. |
Environment-only via NavigationScope; workspace home stays clean. |
ResolvesPanelTenantContext, route parameters, remembered tenant. |
Not applicable. | canAccess() requires tenant membership plus tenant.view. |
PanelNavigationSegregationTest, inventory coverage/admin parity tests. |
None after Spec 301. | migrated | Keep in Inventory proof lane. |
| Environment diagnostics | EnvironmentDiagnostics page |
Explicit route /admin/workspaces/{workspace}/environments/{environment:slug}/diagnostics. |
Hidden from primary navigation; contextual only. | Route model binding and ResolvesPanelTenantContext. |
Not applicable. | Requires authenticated environment context; repair actions require tenant.manage, are destructive, and use confirmation. |
routes/web.php, diagnostics page code, diagnostics/access-scope tests. |
None for route audit. | valid context gate | Keep contextual; do not add primary navigation without product decision. |
| Required permissions | EnvironmentRequiredPermissions page |
Explicit workspace/environment slug route in page registration; hidden from discovery/navigation. | Hidden from primary navigation; linked from diagnostics/onboarding/reporting contexts. | Route parameters, workspace context, page-local scoped-tenant resolution. | Not applicable. | canAccess() and mount abort invalid tenant access with 404. |
EnvironmentRequiredPermissions tests and permissions-report tests. |
None for route audit. | valid context gate | Keep contextual. |
| Access scopes | ManagedEnvironmentResource\Pages\ManageEnvironmentAccessScopes |
Explicit route /admin/workspaces/{workspace}/environments/{environment:slug}/access-scopes. |
Contextual management page, not tenant-owned resource nav. | Route model binding plus workspace/environment middleware. | Not applicable. | Workspace membership and environment access checks protect access-scope management. | routes/web.php, access-scope feature tests. |
None for route audit. | valid context gate | Keep contextual. |
| Managed environment onboarding | ManagedEnvironmentOnboardingWizard |
Explicit /admin/onboarding and /admin/onboarding/{onboardingDraft} routes. |
Hidden from primary navigation; entry from environment creation flow. | Workspace/onboarding draft context until an environment exists. | Not applicable. | Authenticated workspace user; later environment access assigned through onboarding flow. | routes/web.php, onboarding tests. |
Not a tenant-owned surface until environment creation completes. | valid context gate | Keep outside tenant-owned route repair. |
Repair Order
-
admin-directory-groups-cutoverDecide the admin role for Directory / Entra Groups before touching runtime behavior. Current repo truth shows scoped direct admin access and scoped global search, while admin navigation remains explicitly hidden. The cutover spec should choose one contract: primary environment navigation, secondary Identity/Directory lane, or contextual-only entry points. It should then align
EntraGroupResourceroutes, navigation tests, global-search destinations, and detail access with that decision. -
Governance artifact navigation proof pass, if reviewers require one canonical proof lane
Evidence snapshots, stored reports, and finding exceptions already use workspace/environment routes and tenant context gates, but their proof is spread across governance tests and sidebar text assertions. A small follow-up can add or normalize class-level navigation proof without changing product behavior. This should not be bundled into the Entra Groups cutover.
-
Alert delivery route/RBAC audit, only if alerts enter the tenant-owned candidate group
AlertDeliveryResourceis an explicit deferred family with mixed workspace-owned and tenant-bound behavior. It should remain out of this tenant-owned surface repair sequence unless product scope pulls alert delivery into managed-environment navigation or tenant mutation flows. -
navigation-contract-split, conditionalPromote only if drift remains after Inventory, this audit, and Entra Groups. The target should be a test/contract split between workspace-home clean-sidebar assertions and environment-bound tenant-owned navigation assertions.
-
tenant-panel-dead-code-retirementKeep after route/navigation dependency decisions. Current negative-control tests already assert retired
/admin/t/{tenant}and/admin/tenants/{tenant}entry routes are unavailable; deletion should wait until active surfaces and tests no longer depend on tenant-panel compatibility assumptions.
Unresolved Blockers
- Entra Groups product IA is the only blocker that prevents the next runtime repair from being purely mechanical.
- Governance artifacts have no confirmed runtime blocker, but their proof is distributed across several test families instead of one core navigation dataset.
- Alert delivery remains intentionally deferred and should not be treated as first-slice tenant-owned work.
Filament, RBAC, and Deployment Review
- Livewire v4.0+ compliance is preserved: no Livewire or Filament runtime APIs were changed.
- Provider registration is unchanged; Laravel provider registration remains in
apps/platform/bootstrap/providers.php. - Globally searchable tenant-owned resource:
EntraGroupResourcehas a View page.PolicyResource,PolicyVersionResource,FindingExceptionResource,EvidenceSnapshotResource,EnvironmentReviewResource, andStoredReportResourceare disabled for global search. Other first-slice resources are not applicable for global search in the registry. - Destructive actions were not added or changed. Existing inspected destructive diagnostics actions use
->action(...)and->requiresConfirmation(). - No assets were registered or changed; deployment
filament:assetsrequirements are unchanged. - UI visibility is treated as non-authoritative. Server-side RBAC/context proof is recorded separately from navigation posture.
Validation Evidence
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/PanelNavigationSegregationTest.php tests/Feature/Filament/AdminTenantSurfaceParityTest.php tests/Feature/Filament/AdminSharedSurfacePanelParityTest.php tests/Feature/Filament/TenantOwnedResourceScopeParityTest.php tests/Feature/Filament/EntraGroupAdminScopeTest.php tests/Feature/Filament/EntraGroupGlobalSearchScopeTest.php tests/Feature/Filament/PolicyResourceAdminSearchParityTest.php tests/Feature/Filament/PolicyVersionAdminSearchParityTest.php- Result: passed, 53 tests, 124 assertions, 18.56s.
- Browser smoke test: not run. This spec changes only Markdown audit artifacts and does not alter Filament UI, Livewire interactions, navigation behavior, forms, tables, actions, modals, dashboards, operation drilldowns, workspace/tenant runtime context, or any user-facing flow.
git diff --check- Result: passed, no whitespace errors reported.
git diff --check --no-index /dev/null <spec-file>for each file inspecs/302-tenant-owned-surface-route-audit/- Result: no whitespace warnings reported for the untracked spec package files.
git status --short- Result: only
specs/302-tenant-owned-surface-route-audit/is untracked/changed; no application runtime files are modified.
- Result: only