feat(specs/302): tenant owned surface route audit #357

Merged
ahmido merged 2 commits from 302-tenant-owned-surface-route-audit into platform-dev 2026-05-14 21:15:02 +00:00
7 changed files with 830 additions and 1 deletions

View File

@ -40,6 +40,7 @@
use App\Support\Filament\PanelThemeAsset;
use App\Support\Navigation\NavigationScope;
use App\Support\OperationRunLinks;
use App\Support\Tenants\TenantPageCategory;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\AuthenticateSession;
@ -180,7 +181,8 @@ public function panel(Panel $panel): Panel
)
->renderHook(
PanelsRenderHook::PAGE_START,
fn (): string => request()->routeIs('admin.workspace.managed-environments.index', 'admin.onboarding', 'admin.onboarding.draft', 'filament.admin.pages.choose-environment')
fn (): string => TenantPageCategory::fromRequest(request()) === TenantPageCategory::OnboardingWorkflow
|| request()->routeIs('admin.workspace.managed-environments.index', 'filament.admin.pages.choose-environment')
? ''
: ((bool) config('tenantpilot.bulk_operations.progress_widget_enabled', true)
? view('livewire.bulk-operation-progress-wrapper')->render()

View File

@ -3,6 +3,7 @@
declare(strict_types=1);
use App\Filament\Pages\Workspaces\ManagedEnvironmentOnboardingWizard;
use App\Livewire\BulkOperationProgress;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\User;
@ -27,6 +28,7 @@
->get(route('admin.onboarding'))
->assertSuccessful()
->assertSee('Create or resume a managed environment in this workspace.')
->assertDontSeeLivewire(BulkOperationProgress::class)
->assertDontSee('Multiple onboarding drafts are available.');
});
@ -94,6 +96,7 @@
$this->actingAs($user)
->get(route('admin.onboarding.draft', ['onboardingDraft' => $draft->getKey()]))
->assertSuccessful()
->assertDontSeeLivewire(BulkOperationProgress::class)
->assertSee('Onboarding draft')
->assertSee('Contoso GmbH')
->assertSee('22222222-2222-2222-2222-222222222222')

View File

@ -0,0 +1,44 @@
# Specification Quality Checklist: Tenant-Owned Surface Route Audit
**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-05-14
**Feature**: [spec.md](../spec.md)
## Content Quality
- [x] No runtime implementation details are required for the behavior contract; repo surfaces are named only to bound the audit.
- [x] Focused on user value and business needs: a repo-verified repair inventory and follow-up order.
- [x] Written for product, implementation, and review stakeholders.
- [x] All mandatory Spec Kit and constitution sections are completed.
## Requirement Completeness
- [x] No `[NEEDS CLARIFICATION]` markers remain.
- [x] Requirements are testable and unambiguous.
- [x] Success criteria are measurable.
- [x] Success criteria are scoped to the audit artifact and validation evidence.
- [x] All acceptance scenarios are defined.
- [x] Edge cases are identified.
- [x] Scope is clearly bounded to docs/spec artifacts and repo audit.
- [x] Dependencies and assumptions are identified.
## Feature Readiness
- [x] All functional requirements have clear acceptance criteria.
- [x] User scenarios cover inventory, classification, and repair-order flows.
- [x] Feature meets measurable outcomes defined in Success Criteria.
- [x] No application implementation is hidden inside the specification.
## Candidate Selection Gate
- [x] Candidate is explicitly present in `docs/product/spec-candidates.md`.
- [x] Candidate was directly promoted by the user as `302`.
- [x] Related Spec 301 is treated as completed context and is not modified.
- [x] Close alternatives are deferred with rationale.
- [x] Scope is a small, reviewable audit/prep slice.
## Spec Readiness Notes
- Runtime code changes are explicitly out of scope.
- The later implementation deliverable is expected to be `surface-route-audit.md` inside this spec package.
- Any runtime defect discovered during the audit must be documented as a follow-up blocker or candidate, not fixed in this spec.

View File

@ -0,0 +1,199 @@
# Implementation Plan: Tenant-Owned Surface Route Audit
**Branch**: `302-tenant-owned-surface-route-audit` | **Date**: 2026-05-14 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/302-tenant-owned-surface-route-audit/spec.md`
## Summary
Produce a repo-verified audit matrix for tenant-owned admin surfaces after the Inventory navigation cutover. The implementation is docs/spec-artifact only: create `surface-route-audit.md`, classify each audited surface against existing route/navigation/context/global-search/RBAC contracts, cite current tests or gaps, and recommend a bounded follow-up repair order. No application runtime code changes are in scope.
## Technical Context
**Language/Version**: PHP 8.4.15 for inspected application code; Markdown for delivered audit artifact
**Primary Dependencies**: Laravel 12.52.0, Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1
**Storage**: PostgreSQL in the application; N/A for this docs-only audit slice
**Testing**: Existing Pest feature tests; no new tests required by this spec
**Validation Lanes**: confidence for focused existing Filament tests; `git diff --check` for artifact hygiene
**Target Platform**: Laravel Sail local development; Dokploy deployment unaffected
**Project Type**: Laravel/Filament application with Spec Kit artifacts under `specs/`
**Performance Goals**: N/A; no runtime behavior changes
**Constraints**: No application code changes; no route enablement; no navigation changes; no global-search enablement; no migrations; no assets
**Scale/Scope**: Tenant-owned admin surface inventory, starting from `TenantOwnedModelFamilies` and admin Filament resources/pages/tests
## UI / Surface Guardrail Plan
- **Guardrail scope**: no operator-facing surface change; audit/prep artifact only
- **Native vs custom classification summary**: N/A for runtime; existing surfaces are inspected, not changed
- **Shared-family relevance**: navigation, route generation, global search, authorization, relation entry points
- **State layers in scope**: route context, shell/navigation posture, global-search scope, RBAC posture as audited facts only
- **Audience modes in scope**: internal product owner / implementer / reviewer
- **Decision/diagnostic/raw hierarchy plan**: default-visible matrix fields first; source-file and test evidence second
- **Raw/support gating plan**: N/A; no product data or raw tenant payloads included
- **One-primary-action / duplicate-truth control**: one recommended next action per surface row
- **Handling modes by drift class or surface**: document-in-feature for contained findings; follow-up-spec for runtime repair; reject-or-split for broad migration bundles
- **Repository-signal treatment**: review-mandatory for stale navigation/search/RBAC signals; report-only for unrelated code quality findings
- **Special surface test profiles**: standard-native-filament for referenced existing surfaces
- **Required tests or manual smoke**: existing focused Pest tests only; no browser smoke because no UI changes
- **Exception path and spread control**: no runtime exception; document-only classification labels stay inside the audit artifact
- **Active feature PR close-out entry**: Guardrail
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes, audit touches shared route/navigation/search/RBAC concepts
- **Systems touched**:
- `apps/platform/app/Support/WorkspaceIsolation/TenantOwnedModelFamilies.php`
- `apps/platform/app/Filament/Concerns/WorkspaceScopedTenantRoutes.php`
- `apps/platform/app/Support/Navigation/NavigationScope.php`
- `apps/platform/app/Filament/Concerns/ScopesGlobalSearchToTenant.php`
- `apps/platform/app/Support/OperateHub/OperateHubShell.php`
- `apps/platform/routes/web.php`
- `apps/platform/app/Filament/Resources/`
- `apps/platform/app/Filament/Pages/`
- `apps/platform/tests/Feature/Filament/`
- **Shared abstractions reused**: N/A at runtime; the audit measures each surface against the existing helpers above
- **New abstraction introduced? why?**: none
- **Why the existing abstraction was sufficient or insufficient**: the audit records sufficiency per surface; it must not introduce replacement machinery
- **Bounded deviation / spread control**: document-only migration-state labels; no executable classification layer
## OperationRun UX Impact
- **Touches OperationRun start/completion/link UX?**: no
- **Central contract reused**: N/A
- **Delegated UX behaviors**: N/A
- **Surface-owned behavior kept local**: existing run links may be mentioned as evidence but are not changed
- **Queued DB-notification policy**: N/A
- **Terminal notification path**: N/A
- **Exception path**: none
## Provider Boundary & Portability Fit
- **Shared provider/platform boundary touched?**: no runtime boundary change
- **Provider-owned seams**: Entra Groups and provider-specific diagnostics may appear as audited surface names only
- **Platform-core seams**: workspace/environment route context, navigation scope, tenant-owned global-search scope, RBAC semantics
- **Neutral platform terms / contracts preserved**: workspace, managed environment, tenant-owned surface, route posture, navigation posture, repair blocker
- **Retained provider-specific semantics and why**: provider-specific surface names remain contextual to the audited resource/page
- **Bounded extraction or follow-up path**: follow-up-spec if the audit finds provider-specific semantics leaking into platform-core route or search contracts
## Constitution Check
*GATE: Must pass before implementation. Re-check after audit artifact is produced.*
- Inventory-first: audit only; no Inventory, snapshot, backup, or provider truth changes.
- Read/write separation: read-only repo audit; no write/change function.
- Graph contract path: no Microsoft Graph calls or contract changes.
- Deterministic capabilities: audit records existing capability posture; no resolver changes.
- RBAC-UX: audit must record non-member 404 versus member-missing-capability 403 expectations and server-side proof separately from UI visibility.
- Workspace isolation: audit must distinguish workspace-home cleanliness from environment-bound visibility.
- Tenant isolation: audit must identify tenant-owned surfaces that need workspace plus managed-environment entitlement.
- Run observability: no `OperationRun` creation or lifecycle change.
- Test governance: existing focused tests are evidence; missing proof is documented as a gap, not hidden by new broad tests.
- Proportionality: one audit artifact is narrower than a route/navigation framework or broad migration.
- No premature abstraction: no new registry, resolver, strategy, or framework.
- Persisted truth: no runtime persistence; the audit is repair evidence only.
- Behavioral state: migration-state labels are document-only and must not become product state.
- Shared pattern first: the audit measures current usage of existing shared helpers before recommending any new work.
- Provider boundary: provider-specific surfaces remain named only where current repo truth requires them.
- Filament-native UI: no UI is changed; future repairs must preserve Filament v5 and Livewire v4 conventions.
- Filament v5 / Livewire v4 compliance: the plan does not introduce Livewire v3 references or legacy Filament APIs.
- Provider registration location: no provider registration changes; Laravel provider registration remains in `apps/platform/bootstrap/providers.php`.
- Global search rule: the audit must record every globally searchable resource's Edit/View-page eligibility or disabled posture.
- Destructive actions: none are added or changed; any surface with destructive actions is inspected only for follow-up risk.
- Asset strategy: no assets are registered; deploy-time `filament:assets` requirements are unchanged.
## Test Governance Check
- **Test purpose / classification by changed surface**: N/A for runtime; confidence evidence from existing Feature tests
- **Affected validation lanes**: confidence and diff-check only
- **Why this lane mix is the narrowest sufficient proof**: the deliverable is an audit artifact; existing feature tests and source references prove current posture
- **Narrowest proving command(s)**:
- `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`
- `git diff --check`
- **Fixture / helper / factory / seed / context cost risks**: none
- **Expensive defaults or shared helper growth introduced?**: no
- **Heavy-family additions, promotions, or visibility changes**: none
- **Surface-class relief / special coverage rule**: standard-native-filament relief; no new browser proof
- **Closing validation and reviewer handoff**: reviewers should verify the matrix evidence, runtime no-change boundary, and follow-up split
- **Budget / baseline / trend follow-up**: none
- **Review-stop questions**: Did any task edit app code? Does every row cite repo evidence? Are runtime bugs documented as follow-ups?
- **Escalation path**: document-in-feature for audit findings; follow-up-spec for runtime repair
- **Active feature PR close-out entry**: Guardrail
- **Why no dedicated follow-up spec is needed**: this spec is the audit; surface-specific repairs become separate specs only after the matrix identifies them
## Project Structure
### Documentation (this feature)
```text
specs/302-tenant-owned-surface-route-audit/
├── checklists/
│ └── requirements.md
├── plan.md
├── spec.md
├── surface-route-audit.md # Created during implementation, not preparation
└── tasks.md
```
### Source Code (repository root)
```text
apps/platform/app/Filament/
├── Concerns/
├── Pages/
└── Resources/
apps/platform/app/Support/
├── Navigation/
├── OperateHub/
└── WorkspaceIsolation/
apps/platform/routes/web.php
apps/platform/tests/Feature/Filament/
```
**Structure Decision**: The implementation edits only the spec package. Application files and tests are inspected as evidence and remain unchanged.
## Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| Document-only classification labels | The audit needs consistent row states to compare surfaces | Freeform prose would make repair ordering harder to review |
## Implementation Phases
### Phase 1 - Preparation and Scope Lock
Confirm Spec 301 is completed context, verify no `302` package existed before this branch, and keep the implementation boundary to the spec package.
### Phase 2 - Surface Inventory
Build the initial surface set from `TenantOwnedModelFamilies::firstSlice()`, residual inventory, scope exceptions, Filament resources/pages, route files, and focused tests.
### Phase 3 - Posture Classification
For each surface, classify route posture, navigation posture, context source, global-search posture, RBAC posture, evidence, blocker, migration state, and recommended next action.
### Phase 4 - Repair Order
Convert findings into a bounded repair order. Keep Entra Groups cutover, navigation contract split, tenant-panel dead-code retirement, and any surface-specific repairs as separate recommendations.
### Phase 5 - Validation and Close-Out
Run the existing focused tests when available, run `git diff --check`, verify no application files changed, and record any failures as audit findings or blockers.
## Rollout Considerations
- No environment variables.
- No database migrations.
- No queues or scheduled workers.
- No storage or volume changes.
- No Dokploy runtime impact.
- No `filament:assets` change.
- Staging/production validation is N/A unless a later repair spec changes runtime behavior.
## Risk Controls
- Stop if implementation requires runtime code changes; promote a separate repair spec instead.
- Do not treat document classification labels as product states.
- Do not revive `/admin/t/{tenant}` or `/admin/tenants/{tenant}` routes.
- Do not change tests that encode current behavior; document stale tests as findings.
- Keep all follow-up recommendations scoped as bounded candidates.

View File

@ -0,0 +1,302 @@
# Feature Specification: Tenant-Owned Surface Route Audit
**Feature Branch**: `302-tenant-owned-surface-route-audit`
**Created**: 2026-05-14
**Status**: Draft
**Input**: User description: "tenant-owned-surface-route-audit als 302"
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
- **Problem**: The repo has moved toward workspace-first managed-environment routing, but the tenant-owned admin surface set is still understood through scattered code, tests, and candidate notes. Operators and implementers cannot tell which tenant-owned surfaces are fully migrated, intentionally hidden, partially cut over, blocked by product IA decisions, or dependent on retired tenant-panel behavior without reconstructing the answer manually.
- **Today's failure**: After Spec 301 restored Inventory navigation, adjacent surfaces such as Entra Groups, policies, backups, restore runs, findings, evidence, reports, diagnostics, and subordinate relation surfaces still need a repo-verified posture. Without an audit matrix, follow-up work risks either mass-enabling navigation too broadly or preserving stale hide-first assumptions as if they were product decisions.
- **User-visible improvement**: The next repair can be chosen from one clear, repo-verified inventory of tenant-owned admin surfaces, including route posture, navigation posture, context source, global-search posture, RBAC posture, existing proof, blocker, and recommended next action.
- **Smallest enterprise-capable version**: Produce one bounded audit artifact for admin-reachable tenant-owned surfaces and one sequenced repair-prep order. Do not enable routes, change navigation, migrate resources, delete dead code, or decide product IA for individual surfaces in this slice.
- **Explicit non-goals**: No mass navigation re-enablement, no broad runtime migration, no Entra Groups cutover decision, no navigation contract split, no tenant-panel dead-code deletion, no application code changes, no new persisted state, and no new framework for route auditing.
- **Permanent complexity imported**: One repo-local audit artifact in this spec package plus review tasks. No runtime models, tables, enums, services, registries, UI components, assets, jobs, or policies are introduced.
- **Why now**: `docs/product/spec-candidates.md` lists this as the second step after `admin-inventory-navigation-cutover`; Spec 301 is completed and explicitly deferred this generic route audit.
- **Why not local**: A local fix to one resource would hide the cross-surface drift. The current problem is incomplete shared understanding, so the narrowest correct step is a read-only repo audit and repair order.
- **Approval class**: Cleanup
- **Red flags triggered**: One lightweight document-only classification vocabulary is used for the audit matrix. It is not a runtime taxonomy or product state family.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 2 | Produktnaehe: 1 | Wiederverwendung: 1 | **Gesamt: 10/12**
- **Decision**: approve
## Spec Scope Fields *(mandatory)*
- **Scope**: canonical-view
- **Primary Routes**:
- `/admin/workspaces/{workspace}`
- `/admin/workspaces/{workspace}/environments`
- `/admin/workspaces/{workspace}/environments/{environment}`
- `/admin/workspaces/{workspace}/environments/{environment}/...` tenant-owned resource/page routes generated by Filament
- retired or legacy tenant route families such as `/admin/t/{tenant}/...` and `/admin/tenants/{tenant}/...` as negative-control inputs only
- **Data Ownership**: The audit covers tenant-owned and managed-environment-owned runtime records that require workspace plus managed-environment entitlement at authorization time. No product data is created or changed.
- **RBAC**: The audit must record membership and capability expectations for each surface. Non-member workspace or tenant access remains deny-as-not-found. Member-without-capability remains 403 where capability checks apply. UI visibility remains non-authoritative.
For canonical-view specs, the spec MUST define:
- **Default filter behavior when tenant-context is active**: Environment-bound routes resolve their managed-environment context from the canonical workspace/environment route or current trusted context helpers. Workspace-level routes must not show tenant-owned surfaces unless a valid environment context is established.
- **Explicit entitlement checks preventing cross-tenant leakage**: The audit must verify whether each surface uses existing context/authorization paths such as `WorkspaceScopedTenantRoutes`, `NavigationScope`, `OperateHubShell`, `ScopesGlobalSearchToTenant`, `canAccess`, `canViewAny`, policy methods, and route middleware. Any missing or ambiguous check is documented as a repair blocker, not patched in this slice.
## Cross-Cutting / Shared Pattern Reuse *(mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write `N/A - no shared interaction family touched`)*
- **Cross-cutting feature?**: yes
- **Interaction class(es)**: navigation entry points, route generation, global search result destinations, tenant-owned detail/list surfaces, relation-manager entry points
- **Systems touched**:
- `apps/platform/app/Filament/Concerns/WorkspaceScopedTenantRoutes.php`
- `apps/platform/app/Support/Navigation/NavigationScope.php`
- `apps/platform/app/Filament/Concerns/ScopesGlobalSearchToTenant.php`
- `apps/platform/app/Support/OperateHub/OperateHubShell.php`
- `apps/platform/app/Support/WorkspaceIsolation/TenantOwnedModelFamilies.php`
- `apps/platform/app/Filament/Resources/*`
- `apps/platform/app/Filament/Pages/*`
- `apps/platform/routes/web.php`
- focused Filament feature tests under `apps/platform/tests/Feature/Filament/`
- **Existing pattern(s) to extend**: No runtime path is extended in this slice. The audit must measure surfaces against existing shared paths: workspace-scoped tenant routes, navigation scope, tenant-scoped global search, route middleware, and tenant-owned query helpers.
- **Shared contract / presenter / builder / renderer to reuse**: N/A for runtime. The audit should refer to the existing shared helpers above rather than defining a new route/navigation framework.
- **Why the existing shared path is sufficient or insufficient**: Sufficiency is the question being audited per surface. The output must state whether each surface already uses the shared path, legitimately deviates, or needs a follow-up repair.
- **Allowed deviation and why**: Document-only deviation. The audit may classify exceptions, but it must not create executable exception logic.
- **Consistency impact**: Future repair specs should use the audit to avoid parallel local navigation/search/routing behavior.
- **Review focus**: Reviewers must verify that the audit is repo-derived, that no runtime code was changed, and that follow-up recommendations are split into bounded candidates.
## OperationRun UX Impact *(mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an `OperationRun`; otherwise write `N/A - no OperationRun start or link semantics touched`)*
- **Touches OperationRun start/completion/link UX?**: no
- **Shared OperationRun UX contract/layer reused**: N/A
- **Delegated start/completion UX behaviors**: N/A
- **Local surface-owned behavior that remains**: The audit may mention tenant-owned surfaces that link to runs, but it does not change OperationRun start, completion, link, notification, or monitoring behavior.
- **Queued DB-notification policy**: N/A
- **Terminal notification path**: N/A
- **Exception required?**: none
## Provider Boundary / Platform Core Check *(mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write `N/A - no shared provider/platform boundary touched`)*
- **Shared provider/platform boundary touched?**: no runtime boundary change
- **Boundary classification**: N/A for implementation. The audit may record provider-owned surfaces such as Entra Groups separately from platform-core route/context rules.
- **Seams affected**: Read-only review of route, navigation, global search, and authorization seams.
- **Neutral platform terms preserved or introduced**: Use `workspace`, `managed environment`, `tenant-owned surface`, `route posture`, `navigation posture`, and `repair blocker`.
- **Provider-specific semantics retained and why**: Provider-specific names such as Entra Groups remain only as audited surface names. They do not become platform-core vocabulary.
- **Why this does not deepen provider coupling accidentally**: The output is a bounded audit artifact and does not change shared contracts or runtime labels.
- **Follow-up path**: document-in-feature for the audit; follow-up-spec for any product-sensitive or runtime repair.
## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)*
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | no runtime UI change | N/A | navigation, route, global search review only | none | no | `N/A - audit/prep artifact only` |
| Existing tenant-owned admin surfaces | no change in this slice | Native Filament surfaces are inspected, not changed | navigation, route, search | shell, page, route context as audited facts only | no runtime exception | The audit records current posture without re-rendering or enabling surfaces |
## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | Secondary Context | Product/engineering chooses the next bounded repair spec | Surface classification, blocker, recommended next action | Route names, resource/page classes, tests, search posture, RBAC notes | Not an operator runtime surface; it guides repair sequencing | Follows Admin Workspace Navigation & Tenant-owned Surface Repair candidate order | Prevents repeated manual reconstruction and broad repair bundling |
## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)*
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | internal implementer/reviewer | Surface name, classification, blocker, next action | Source files, test files, route names, global-search notes | N/A | Promote the next bounded repair | Raw payloads and product data are out of scope | One matrix row per surface prevents duplicate scattered posture notes |
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | Audit / Planning | Repo audit matrix | Choose next repair candidate | Read matrix row | N/A | N/A | N/A | `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` | N/A | Workspace/environment route posture fields | Tenant-owned surface | Migration state, blocker, next action | docs-only audit artifact |
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Tenant-owned surface audit artifact | Product owner / implementer / reviewer | Decide which tenant-owned surface repair should be promoted next | Internal audit matrix | Which surfaces are already migrated, blocked, stale, or ready for a bounded repair? | Surface classification, blocker, next action, proof status | File/test/route evidence | route posture, navigation posture, search posture, RBAC posture, proof status | Docs-only; no TenantPilot or Microsoft tenant mutation | Promote next bounded spec | none |
## Proportionality Review *(mandatory when structural complexity is introduced)*
- **New source of truth?**: no runtime source of truth. The audit artifact is repair-prep evidence, not product truth.
- **New persisted entity/table/artifact?**: no runtime persistence. One spec-package audit artifact is expected during implementation.
- **New abstraction?**: no
- **New enum/state/reason family?**: no runtime family. The audit uses document-only labels: migrated, partial cutover, stale panel logic, valid context gate, valid RBAC, ambiguous product IA, dead-code dependent.
- **New cross-domain UI framework/taxonomy?**: no runtime framework or taxonomy.
- **Current operator problem**: The team cannot safely choose the next tenant-owned route/navigation repair without a repo-verified surface inventory.
- **Existing structure is insufficient because**: Candidate notes, tests, resources, route helpers, and model-family metadata each hold part of the answer, but no single artifact records the cross-surface posture.
- **Narrowest correct implementation**: Create one audit matrix and repair order from current repo evidence.
- **Ownership cost**: The matrix must be maintained only when a follow-up repair changes the posture. No runtime code or framework cost is added.
- **Alternative intentionally rejected**: A broad migration or route/navigation framework split is rejected because the audit must first identify the actual drift and product-decision blockers.
- **Release truth**: Current-release repair preparation.
### Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.
Canonical replacement is preferred over preservation.
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
- **Test purpose / classification**: Feature-validation review using existing Pest feature tests; no new runtime test family is required unless the audit discovers that the audit artifact itself needs a repo guard in a follow-up spec.
- **Validation lane(s)**: confidence for existing focused Filament tests; N/A for runtime because this slice does not change app behavior.
- **Why this classification and these lanes are sufficient**: The deliverable is a repo audit. Existing route, navigation, global-search, and admin-scope tests provide evidence; any missing proof is documented as an audit gap and follow-up blocker rather than patched here.
- **New or expanded test families**: none in this spec.
- **Fixture / helper cost impact**: none.
- **Heavy-family visibility / justification**: none.
- **Special surface test profile**: standard-native-filament for any referenced existing Filament surface; no browser proof is required because no UI changes are made.
- **Standard-native relief or required special coverage**: ordinary feature-test evidence and static route/resource review only.
- **Reviewer handoff**: Confirm no runtime code changed, every audit row links to repo evidence, test gaps are marked as gaps, and follow-up repairs are split.
- **Budget / baseline / trend impact**: none.
- **Escalation needed**: document-in-feature.
- **Active feature PR close-out entry**: Guardrail.
- **Planned validation commands**:
- `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`
- `git diff --check`
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Inventory the tenant-owned admin surface set (Priority: P1)
As an implementer preparing the next repair, I need a repo-verified matrix of tenant-owned admin surfaces so I can see which surfaces are migrated, hidden, blocked, or stale before changing behavior.
**Why this priority**: Without the matrix, every follow-up risks repeating the broad drift that Spec 301 intentionally avoided.
**Independent Test**: Review `surface-route-audit.md` and confirm each first-slice tenant-owned family from `TenantOwnedModelFamilies::firstSlice()` plus named residual exceptions has a row with route posture, navigation posture, context source, global-search posture, RBAC posture, proof status, blocker, and next action.
**Acceptance Scenarios**:
1. **Given** the current repo surface set, **When** the audit is completed, **Then** every tenant-owned first-slice model/resource family is represented exactly once.
2. **Given** a tenant-owned surface with no direct primary resource, **When** it is subordinate or indirect, **Then** the audit records the parent relation or indirect surface instead of inventing a primary route.
3. **Given** a surface with unclear product IA, **When** it is classified, **Then** the blocker is recorded as ambiguous product IA and the next action is a bounded follow-up decision.
---
### User Story 2 - Classify route, navigation, search, and RBAC posture (Priority: P2)
As a reviewer, I need each surface classified against the existing route/navigation/global-search/RBAC contracts so I can distinguish valid gates from stale panel logic.
**Why this priority**: The audit only helps if it separates legitimate denials from implementation drift.
**Independent Test**: Sample at least one surface in each classification group and verify the matrix cites concrete files, route families, or tests that support the classification.
**Acceptance Scenarios**:
1. **Given** a migrated surface, **When** it is classified, **Then** the matrix identifies the canonical workspace/environment route path or route-generation helper.
2. **Given** a stale hidden surface, **When** it is classified, **Then** the matrix names the hidden navigation or panel logic and marks it as a repair candidate, not a product decision.
3. **Given** a global-search capable resource, **When** it is classified, **Then** the matrix records whether it has an Edit or View page or whether global search is disabled.
4. **Given** an inaccessible tenant-owned surface, **When** RBAC posture is classified, **Then** non-member 404 and member-missing-capability 403 expectations are recorded separately where applicable.
---
### User Story 3 - Produce a sequenced repair order (Priority: P3)
As a product owner, I need a recommended follow-up order so adjacent repairs remain small and do not become a single umbrella migration.
**Why this priority**: The candidate group already names follow-ups, but the audit must make the next one defensible from repo evidence.
**Independent Test**: Confirm the audit includes one ordered follow-up list with blockers and explicitly keeps runtime fixes out of this spec.
**Acceptance Scenarios**:
1. **Given** surfaces classified as stale panel logic or partial cutover, **When** the audit proposes follow-up work, **Then** each recommendation is scoped as a bounded spec candidate.
2. **Given** surfaces blocked by product IA, **When** the audit proposes follow-up work, **Then** it calls out the decision needed before implementation.
3. **Given** tenant-panel dead-code dependencies, **When** the audit proposes follow-up work, **Then** it keeps deletion after route/navigation replacement decisions.
## Edge Cases
- A surface may be tenant-owned by data but intentionally workspace-canonical by route; the audit must record both facts.
- A surface may be tenant-owned but subordinate to a relation manager; the audit must not create an artificial top-level route recommendation.
- A surface may be tenant-bound but not globally searchable; the audit must distinguish disabled/not-applicable search from missing search coverage.
- A direct URL may be reachable while navigation is hidden; the audit must classify route access and navigation registration separately.
- A test may encode stale behavior; the audit must record that as a test-contract finding without changing tests in this slice.
- Legacy `/admin/t/{tenant}` and `/admin/tenants/{tenant}` behavior must be treated as negative-control evidence, not as a route family to revive.
## Requirements *(mandatory)*
### Functional Requirements
- **FR-302-001**: The implementation MUST create `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` as the single audit matrix artifact.
- **FR-302-002**: The audit MUST cover every first-slice tenant-owned family listed by `TenantOwnedModelFamilies::firstSlice()`.
- **FR-302-003**: The audit MUST cover documented residual or exception surfaces from `TenantOwnedModelFamilies::residualRolloutInventory()` and `scopeExceptions()` when they have admin-reachable or admin-relevant surfaces.
- **FR-302-004**: Each audited row MUST include surface name, model/resource/page owner, route posture, navigation posture, context source, global-search posture, RBAC posture, existing proof, blocker, migration state, and recommended next action.
- **FR-302-005**: Migration state MUST be one of: migrated, partial cutover, stale panel logic, valid context gate, valid RBAC, ambiguous product IA, or dead-code dependent.
- **FR-302-006**: The audit MUST distinguish route reachability from navigation registration.
- **FR-302-007**: The audit MUST distinguish workspace-home cleanliness from environment-bound admin visibility.
- **FR-302-008**: The audit MUST verify global-search posture for resources using tenant-scoped search or search-disabled posture, including the Filament v5 requirement that globally searchable resources have an Edit or View page.
- **FR-302-009**: The audit MUST record existing high-signal tests that prove each posture or explicitly mark proof as missing.
- **FR-302-010**: The audit MUST produce a recommended repair order that keeps `admin-directory-groups-cutover`, `navigation-contract-split`, and `tenant-panel-dead-code-retirement` as separate follow-up candidates unless repo evidence justifies a different bounded order.
- **FR-302-011**: The implementation MUST NOT modify application runtime code, routes, migrations, models, services, jobs, Filament resources, Livewire components, policies, commands, views, assets, or tests.
- **FR-302-012**: Any discovered runtime defect MUST be documented as a follow-up blocker or candidate, not fixed in this spec.
### Non-Functional Requirements
- **NFR-302-001**: The audit must be repo-derived from current files and tests, not roadmap-aspirational.
- **NFR-302-002**: The audit must be concise enough to review in one PR and structured enough for later implementation agents to use directly.
- **NFR-302-003**: The feature must remain docs/spec-artifact only and must not change runtime behavior.
- **NFR-302-004**: Filament v5 and Livewire v4 compliance must be preserved by not introducing legacy APIs or new runtime code.
- **NFR-302-005**: No new assets are registered; deployment `filament:assets` requirements are unchanged.
### RBAC / Security Requirements
- **SEC-302-001**: The audit MUST record whether each surface's expected denial semantics are non-member 404 and member-without-capability 403, where applicable.
- **SEC-302-002**: The audit MUST treat UI visibility as non-authoritative and identify server-side authorization proof separately.
- **SEC-302-003**: The audit MUST flag any surface where route/context access appears to depend only on navigation hiding.
### Auditability / Observability Requirements
- **AUD-302-001**: This docs-only slice introduces no `AuditLog` event and no `OperationRun`.
- **AUD-302-002**: The audit artifact must provide evidence references sufficient for reviewers to trace each conclusion back to repo files or tests.
### Data / Truth-Source Requirements
- **DATA-302-001**: No product data or database schema is changed.
- **DATA-302-002**: Tenant-owned runtime truth remains in existing models/tables; the audit artifact is repair evidence only.
- **DATA-302-003**: The audit must not promote document classification labels into product state or persisted truth.
## Success Criteria *(mandatory)*
- **SC-302-001**: `surface-route-audit.md` exists and covers the expected tenant-owned surface inventory.
- **SC-302-002**: Every row has route, navigation, context, search, RBAC, proof, blocker, migration state, and next-action fields.
- **SC-302-003**: The audit identifies at least one ordered follow-up path and explains why close alternatives are deferred or blocked.
- **SC-302-004**: No application runtime files are changed.
- **SC-302-005**: Existing focused Filament validation commands either pass or any failures are documented as pre-existing/runtime follow-up blockers.
## Assumptions
- The user explicitly requested feature number `302`; `specs/302-tenant-owned-surface-route-audit` did not exist before this preparation.
- `301-admin-inventory-navigation-cutover` is completed context and must not be rewritten.
- The implementation deliverable is an audit artifact, not an application behavior change.
- `TenantOwnedModelFamilies` is the starting inventory, but the audit may add admin-relevant pages/resources discovered from Filament files and tests.
- The current Laravel/Filament stack is Laravel 12, Filament 5, Livewire 4, Pest 4, and PHP 8.4.
## Risks
- The audit could become too broad if it tries to solve every route or IA problem it finds.
- Document-only labels could be mistaken for runtime taxonomy if not clearly bounded.
- Some tests may assert stale behavior; those must be reported as findings rather than edited in this spec.
- A later implementation loop could accidentally patch runtime code unless the tasks keep the docs-only boundary explicit.
## Out of Scope
- Any application code change.
- Any migration, model, service, job, policy, command, view, route, Filament resource/page, Livewire component, or test edit.
- Broad runtime route migration.
- Mass navigation re-enablement.
- Entra Groups cutover implementation.
- Navigation contract split implementation.
- Tenant-panel dead-code deletion.
- New global-search enablement.
- New audit log or OperationRun behavior.
## Follow-up Spec Candidates
- `admin-directory-groups-cutover`
- `navigation-contract-split`, only if the audit shows shared contract drift remains after bounded surface repairs
- `tenant-panel-dead-code-retirement`
- surface-specific repair specs named by `surface-route-audit.md`
## Manual Promotion Notes
- **Selected candidate title**: `tenant-owned-surface-route-audit`
- **Source location**: `docs/product/spec-candidates.md`, Admin Workspace Navigation & Tenant-owned Surface Repair candidate group.
- **Why selected**: User explicitly promoted it as `302`; it is the recommended follow-up after `admin-inventory-navigation-cutover`.
- **Close alternatives deferred**: `admin-directory-groups-cutover` needs the audit/product IA evidence first; `navigation-contract-split` should happen only if drift remains after bounded repairs; `tenant-panel-dead-code-retirement` should wait until dependencies are known.
- **Roadmap relationship**: UI and Product Maturity Polish, parallel immediate repair lane for Admin Workspace Navigation & Tenant-owned Surface Repair.
- **Completed-spec guardrail result**: Spec 301 has completed task markers and is treated as historical/completed context only. Specs 279-301 are not modified by this preparation.
- **Smallest viable implementation slice**: Create the audit matrix and repair-prep order only; do not patch runtime.

View File

@ -0,0 +1,149 @@
# 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.php`
- `apps/platform/app/Filament/Concerns/WorkspaceScopedTenantRoutes.php`
- `apps/platform/app/Support/Navigation/NavigationScope.php`
- `apps/platform/app/Filament/Concerns/ScopesGlobalSearchToTenant.php`
- `apps/platform/app/Filament/Concerns/ResolvesPanelTenantContext.php`
- `apps/platform/app/Support/OperateHub/OperateHubShell.php`
- `apps/platform/routes/web.php`
- `apps/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
1. `admin-directory-groups-cutover`
Decide 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 `EntraGroupResource` routes, navigation tests, global-search destinations, and detail access with that decision.
2. 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.
3. Alert delivery route/RBAC audit, only if alerts enter the tenant-owned candidate group
`AlertDeliveryResource` is 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.
4. `navigation-contract-split`, conditional
Promote 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.
5. `tenant-panel-dead-code-retirement`
Keep 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: `EntraGroupResource` has a View page. `PolicyResource`, `PolicyVersionResource`, `FindingExceptionResource`, `EvidenceSnapshotResource`, `EnvironmentReviewResource`, and `StoredReportResource` are 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:assets` requirements 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 in `specs/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.

View File

@ -0,0 +1,130 @@
# Tasks: Tenant-Owned Surface Route Audit
**Input**: Design documents from `/specs/302-tenant-owned-surface-route-audit/`
**Prerequisites**: `spec.md`, `plan.md`, `checklists/requirements.md`
**Tests**: No new runtime tests are planned. This is a docs/spec-artifact audit. Existing focused Pest feature tests are used as evidence and validation.
## Test Governance Checklist
- [x] Lane assignment is named and is the narrowest sufficient proof for the changed behavior.
- [x] New or changed tests stay N/A because no application behavior changes.
- [x] Shared helpers, factories, seeds, fixtures, and context defaults stay unchanged.
- [x] Planned validation commands cover the audit evidence without adding unrelated lane cost.
- [x] The declared surface test profile is `standard-native-filament`.
- [x] Any material budget, baseline, trend, or escalation note is recorded as none or as a follow-up blocker in the audit artifact.
## Phase 1: Preparation and Scope Lock
**Purpose**: Confirm this implementation remains an audit artifact and does not reopen completed specs or runtime work.
- [x] T001 Review `specs/302-tenant-owned-surface-route-audit/spec.md`, `specs/302-tenant-owned-surface-route-audit/plan.md`, and `specs/302-tenant-owned-surface-route-audit/checklists/requirements.md` before editing any artifact.
- [x] T002 Review `docs/product/spec-candidates.md` Admin Workspace Navigation & Tenant-owned Surface Repair candidate group and confirm this implementation is limited to `tenant-owned-surface-route-audit`.
- [x] T003 Review `specs/301-admin-inventory-navigation-cutover/spec.md`, `specs/301-admin-inventory-navigation-cutover/plan.md`, and `specs/301-admin-inventory-navigation-cutover/tasks.md` as completed context only; do not modify them.
- [x] T004 Run `git status --short --branch` from `/Users/ahmeddarrazi/Documents/projects/wt-plattform` and stop if unrelated uncommitted changes exist.
- [x] T005 Create `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` with sections for audit scope, matrix, repair order, validation evidence, and unresolved blockers.
- [x] T006 Record in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` that application runtime code, tests, routes, migrations, assets, policies, jobs, and Filament classes are not to be edited in this spec.
---
## Phase 2: User Story 1 - Inventory the Tenant-Owned Admin Surface Set (Priority: P1)
**Goal**: Produce the initial repo-derived tenant-owned surface inventory.
**Independent Test**: The audit matrix contains one row for every first-slice tenant-owned family plus relevant residual or exception surfaces.
- [x] T007 [P] [US1] Extract first-slice surface families from `apps/platform/app/Support/WorkspaceIsolation/TenantOwnedModelFamilies.php` into `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T008 [P] [US1] Extract residual rollout and explicit scope-exception surfaces from `apps/platform/app/Support/WorkspaceIsolation/TenantOwnedModelFamilies.php` into `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T009 [P] [US1] Cross-check tenant-owned Filament resources under `apps/platform/app/Filament/Resources/` and add any admin-relevant resource/page owner notes to `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T010 [P] [US1] Cross-check tenant-owned or managed-environment-bound Filament pages under `apps/platform/app/Filament/Pages/` and add any non-resource surfaces to `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T011 [US1] Mark subordinate surfaces such as relation managers or indirect evidence/report sections in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` without inventing standalone routes.
---
## Phase 3: User Story 2 - Classify Route, Navigation, Search, and RBAC Posture (Priority: P2)
**Goal**: Classify every audited surface against the existing repo contracts.
**Independent Test**: Each matrix row has route posture, navigation posture, context source, global-search posture, RBAC posture, proof, blocker, migration state, and recommended next action.
- [x] T012 [P] [US2] Audit route generation and route reachability for each surface using `apps/platform/app/Filament/Concerns/WorkspaceScopedTenantRoutes.php`, `apps/platform/routes/web.php`, and resource `getPages()` declarations; record results in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T013 [P] [US2] Audit navigation registration for each surface using `apps/platform/app/Support/Navigation/NavigationScope.php`, `shouldRegisterNavigation()` methods, and relevant cluster/page/resource classes; record results in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T014 [P] [US2] Audit managed-environment context resolution using `apps/platform/app/Support/OperateHub/OperateHubShell.php`, `apps/platform/app/Filament/Concerns/ResolvesPanelTenantContext.php`, and workspace-context helpers; record results in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T015 [P] [US2] Audit tenant-scoped global-search posture using `apps/platform/app/Filament/Concerns/ScopesGlobalSearchToTenant.php`, resource search configuration, and `TenantOwnedModelFamilies::searchPostureForModel()`; record results in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T016 [P] [US2] For any globally searchable resource, verify an Edit or View page exists or global search is disabled, using resource `getPages()` declarations under `apps/platform/app/Filament/Resources/`; record the finding in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T017 [P] [US2] Audit RBAC and denial semantics from `canAccess`, `canViewAny`, policies/capabilities, route middleware, and relevant tests under `apps/platform/tests/Feature/Filament/`; record non-member 404 and member-missing-capability 403 posture in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T018 [US2] Assign each audited row exactly one migration state in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`: migrated, partial cutover, stale panel logic, valid context gate, valid RBAC, ambiguous product IA, or dead-code dependent.
- [x] T019 [US2] Mark missing proof, stale test contracts, or ambiguous product IA as blockers in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` instead of editing application tests or code.
---
## Phase 4: User Story 3 - Produce a Sequenced Repair Order (Priority: P3)
**Goal**: Convert the classification into bounded follow-up recommendations.
**Independent Test**: The audit artifact contains one ordered repair list and each recommendation is scoped as a separate candidate or explicitly deferred.
- [x] T020 [US3] Add a repair-order section to `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` that orders stale panel logic, partial cutover, product IA blockers, and dead-code dependencies.
- [x] T021 [US3] Keep `admin-directory-groups-cutover` as a separate recommendation in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` unless the audit proves it should remain deferred.
- [x] T022 [US3] Keep `navigation-contract-split` as conditional follow-up in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`, only if shared contract drift remains after bounded repairs.
- [x] T023 [US3] Keep `tenant-panel-dead-code-retirement` after route/navigation dependency decisions in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T024 [US3] Add any newly discovered surface-specific repair candidates to `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` with one-sentence scope, blocker, and why it should not be bundled into this audit.
---
## Phase 5: Validation Evidence
**Purpose**: Use existing tests and source checks to validate the audit without changing runtime behavior.
- [x] T025 Run `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` and record pass/fail evidence in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md`.
- [x] T026 Validation command did not fail; no runtime patch was needed in this spec.
- [x] T027 Run `git diff --check` from `/Users/ahmeddarrazi/Documents/projects/wt-plattform` and resolve only whitespace/artifact issues inside `specs/302-tenant-owned-surface-route-audit/`.
- [x] T028 Run `git status --short` from `/Users/ahmeddarrazi/Documents/projects/wt-plattform` and confirm the changed files are limited to `specs/302-tenant-owned-surface-route-audit/`.
---
## Phase 6: Filament, RBAC, and Scope Review
**Purpose**: Close the preparation contract and prevent hidden runtime implementation.
- [x] T029 Confirm in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` that Filament v5 and Livewire v4 compatibility is preserved because no runtime APIs changed.
- [x] T030 Confirm in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` that no panel provider registration changed and Laravel provider registration remains in `apps/platform/bootstrap/providers.php`.
- [x] T031 Confirm in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` that globally searchable resources have Edit/View pages or are recorded as disabled/not applicable.
- [x] T032 Confirm in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` that no destructive actions were added or changed, and any destructive-action concerns are listed only as follow-up observations.
- [x] T033 Confirm in `specs/302-tenant-owned-surface-route-audit/surface-route-audit.md` that no assets were registered and deployment `filament:assets` requirements are unchanged.
- [x] T034 Update `specs/302-tenant-owned-surface-route-audit/spec.md`, `specs/302-tenant-owned-surface-route-audit/plan.md`, or `specs/302-tenant-owned-surface-route-audit/tasks.md` only if the audit discovers a preparation-artifact inconsistency that blocks safe implementation handoff.
---
## Dependencies
- Phase 1 must complete before the audit matrix is created.
- Phase 2 inventory must complete before Phase 3 classification.
- Phase 3 classification must complete before Phase 4 repair ordering.
- Phase 5 validation can run after enough matrix rows exist to cite evidence.
- Phase 6 closes the handoff after validation evidence is recorded.
## Parallel Execution Examples
- T007, T008, T009, and T010 can run in parallel because they read different inventory sources and write distinct sections/rows in `surface-route-audit.md`.
- T012, T013, T014, T015, T016, and T017 can run in parallel if each worker owns different columns or surface groups in `surface-route-audit.md`.
- T021, T022, T023, and T024 can run in parallel after T020 establishes the repair-order section.
## Implementation Strategy
1. Complete the audit matrix before making recommendations.
2. Prefer evidence-backed classifications over speculative cleanup.
3. Treat missing proof as a finding, not a reason to broaden this spec.
4. Stop and create a follow-up candidate if runtime changes appear necessary.
## Explicit Non-Goals
- [x] Do not modify application runtime code.
- [x] Do not modify application tests.
- [x] Do not add or change routes.
- [x] Do not change Filament resources, pages, clusters, widgets, or Livewire components.
- [x] Do not create migrations, models, services, jobs, policies, commands, views, or assets.
- [x] Do not re-enable hidden navigation.
- [x] Do not implement Entra Groups cutover.
- [x] Do not split the navigation contract.
- [x] Do not retire tenant-panel dead code.