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
12 KiB
Implementation Plan: Tenant-Owned Surface Route Audit
Branch: 302-tenant-owned-surface-route-audit | Date: 2026-05-14 | Spec: 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.phpapps/platform/app/Filament/Concerns/WorkspaceScopedTenantRoutes.phpapps/platform/app/Support/Navigation/NavigationScope.phpapps/platform/app/Filament/Concerns/ScopesGlobalSearchToTenant.phpapps/platform/app/Support/OperateHub/OperateHubShell.phpapps/platform/routes/web.phpapps/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
OperationRuncreation 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:assetsrequirements 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.phpgit 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)
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)
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:assetschange. - 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.