Implements platform feature branch `301-admin-inventory-navigation-cutover`. Target branch: `platform-dev`. Follow-up integration path after merge: `platform-dev` → `dev`. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #356
13 KiB
Implementation Plan: Admin Inventory Navigation Cutover
Branch: 301-admin-inventory-navigation-cutover | Date: 2026-05-14 | Spec: spec.md
Input: Feature specification from /specs/301-admin-inventory-navigation-cutover/spec.md
Summary
Restore Inventory as a discoverable environment-bound admin navigation surface. The implementation should remove or narrow Inventory-only blanket admin navigation suppression, reuse the current NavigationScope environment-surface rule, preserve workspace-home sidebar cleanliness, and update tests so they protect the correct split: workspace home hides tenant-owned navigation, environment routes show Inventory.
No application implementation is performed in this preparation step.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12.52.0
Primary Dependencies: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1
Storage: PostgreSQL, no schema changes
Testing: Pest feature tests; optional Browser smoke for visible sidebar behavior
Validation Lanes: confidence, browser if smoke is added
Target Platform: Laravel Sail local development; Dokploy container deployment for staging/production
Project Type: Laravel application in apps/platform
Performance Goals: Navigation/page-load remains DB-only; no Graph calls or queued work are introduced
Constraints: Workspace and managed-environment isolation must remain enforced; workspace home must not show tenant-owned navigation; no Entra Groups decision
Scale/Scope: Two Inventory surfaces plus tests
UI / Surface Guardrail Plan
- Guardrail scope: changed operator-facing navigation surfaces
- Native vs custom classification summary: native Filament navigation/cluster/page/resource
- Shared-family relevance: navigation entry points
- State layers in scope: shell, page, route context, Livewire update referer handling through existing
NavigationScope - Audience modes in scope: operator-MSP
- Decision/diagnostic/raw hierarchy plan: navigation-only entry points; diagnostics stay inside existing Inventory pages
- Raw/support gating plan: N/A
- One-primary-action / duplicate-truth control: Sidebar links open existing Inventory pages and do not add alternate status summaries or action cards
- Handling modes by drift class or surface: review-mandatory for Inventory navigation; report-only for unrelated tenant-owned surfaces
- Repository-signal treatment:
InventoryClusterandInventoryCoverageblanket admin-hidden checks are active repair targets; Entra Groups remains follow-up - Special surface test profiles: standard-native-filament
- Required tests or manual smoke: feature tests required; browser smoke recommended if sidebar rendering is touched visibly
- Exception path and spread control: none
- Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage
Shared Pattern & System Fit
- Cross-cutting feature marker: yes
- Systems touched: Filament navigation, Inventory cluster/page/resource,
NavigationScope, panel/context tests - Shared abstractions reused:
NavigationScope::shouldRegisterEnvironmentNavigation(),WorkspaceScopedTenantRoutes,ResolvesPanelTenantContext,OperateHubShell - New abstraction introduced? why?: none
- Why the existing abstraction was sufficient or insufficient: Existing environment-navigation detection is sufficient. Current Inventory cluster/page classes are insufficient because they bypass it with a blanket admin-panel hidden rule.
- Bounded deviation / spread control: none. Do not create a local Inventory-only replacement for
NavigationScope.
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: no
- Central contract reused: N/A
- Delegated UX behaviors: Existing Inventory Sync start behavior remains unchanged
- Surface-owned behavior kept local: Navigation visibility only
- Queued DB-notification policy: N/A
- Terminal notification path: N/A
- Exception path: none
Provider Boundary & Portability Fit
- Shared provider/platform boundary touched?: no
- Provider-owned seams: N/A
- Platform-core seams: N/A
- Neutral platform terms / contracts preserved: workspace, environment, Inventory, Coverage
- Retained provider-specific semantics and why: Existing Inventory item provider metadata remains unchanged
- Bounded extraction or follow-up path: none
Constitution Check
GATE: Must pass before implementation starts. Re-check after implementation.
- Inventory-first: pass. Inventory remains last-observed managed-environment truth.
- Read/write separation: pass. Navigation repair is read-only; existing Inventory Sync action remains unchanged.
- Graph contract path: pass. No Graph calls or contract changes.
- Deterministic capabilities: pass. Existing capability resolver remains the authorization path.
- RBAC-UX: pass. UI visibility remains non-security; existing access checks stay authoritative.
- Workspace isolation: pass. Workspace home negative-control tests remain mandatory.
- Tenant/managed-environment isolation: pass. Wrong workspace/environment pairs remain not found.
- Run observability: N/A. No new OperationRun lifecycle.
- Test governance: pass if tasks keep feature/browser proof focused and avoid a route-audit sweep.
- Proportionality: pass. No new structures, persistence, states, or frameworks.
- Shared pattern first: pass. Reuse
NavigationScope. - Provider boundary: pass. No provider seam change.
- Filament-native UI: pass. Native Filament cluster/resource/page navigation only; no custom UI.
- Filament v5 / Livewire v4: pass. The repo uses Filament 5.2.1 and Livewire 4.1.4.
- Panel provider registration: unchanged. Laravel provider registration remains in
apps/platform/bootstrap/providers.php; no provider is added tobootstrap/app.php. - Global search:
InventoryItemResourcealready has a View page.InventoryCoverageis a page, not a globally searchable resource. No new globally searchable resource is introduced. - Destructive actions: none introduced or changed. Existing Inventory Sync is an operation start, not changed by this slice; any touched action must retain authorization and current confirmation/notification behavior.
- Asset strategy: no assets are registered; deploy
filament:assetsposture is unchanged.
Test Governance Check
- Test purpose / classification by changed surface: Feature for navigation registration and context; Browser only for rendered sidebar proof
- Affected validation lanes: confidence, browser
- Why this lane mix is the narrowest sufficient proof: The behavior is mostly PHP navigation gating and route/context resolution. One browser smoke is enough to prove the visible sidebar if it changes.
- Narrowest proving command(s):
cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/PanelNavigationSegregationTest.php tests/Feature/Filament/InventoryCoverageAdminTenantParityTest.php tests/Feature/Filament/InventoryHubDbOnlyTest.php tests/Feature/Filament/InventoryPagesTest.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec301InventoryNavigationCutoverSmokeTest.phpif addedcd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
- Fixture / helper / factory / seed / context cost risks: Low; reuse existing tenant/workspace helpers and Inventory factories
- 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
- Closing validation and reviewer handoff: Verify the feature does not change Entra Groups, does not widen into route-audit, and does not show Inventory on workspace home.
- Budget / baseline / trend follow-up: none
- Review-stop questions: Has workspace-home cleanliness remained a test? Are Inventory cluster/page visible in environment context? Did any unrelated surface become visible?
- Escalation path: document-in-feature
- Active feature PR close-out entry: Guardrail / Exception / Smoke Coverage
- Why no dedicated follow-up spec is needed: The next follow-up specs are already named in
docs/product/spec-candidates.md; this slice only repairs Inventory.
Project Structure
Documentation (this feature)
specs/301-admin-inventory-navigation-cutover/
├── spec.md
├── plan.md
├── tasks.md
└── checklists/
└── requirements.md
Source Code (repository root)
Likely affected runtime surfaces during later implementation:
apps/platform/app/Filament/Clusters/Inventory/InventoryCluster.php
apps/platform/app/Filament/Pages/InventoryCoverage.php
apps/platform/app/Filament/Resources/InventoryItemResource.php
apps/platform/app/Support/Navigation/NavigationScope.php
apps/platform/tests/Feature/Filament/PanelNavigationSegregationTest.php
apps/platform/tests/Feature/Filament/InventoryCoverageAdminTenantParityTest.php
apps/platform/tests/Feature/Filament/InventoryHubDbOnlyTest.php
apps/platform/tests/Feature/Filament/InventoryPagesTest.php
apps/platform/tests/Browser/Spec301InventoryNavigationCutoverSmokeTest.php
Structure Decision: Use existing Laravel/Filament app structure. Do not create new base folders or new shared navigation framework.
Complexity Tracking
No constitution violation or BLOAT-001 trigger is expected. If implementation introduces any new abstraction, route family, persistent state, status family, or UI framework, stop and update this plan before continuing.
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| N/A | N/A | N/A |
Data Model
No schema, model, migration, factory, seeder, or persisted entity changes are in scope.
Technical Approach
- Update proof first:
- Split current admin-hidden navigation expectations so workspace-home hidden behavior is preserved while environment-bound Inventory visibility is expected.
- Keep Entra Groups in the admin-hidden dataset or otherwise explicitly assert it remains out of scope.
- Add Coverage URL proof so
InventoryCoverage::getUrl(panel: 'admin', tenant: $environment)resolves to the canonical workspace/environment route.
- Converge Inventory navigation:
- Replace blanket
Filament::getCurrentPanel()?->getId() === 'admin'false returns in Inventory cluster/page classes with the shared environment-navigation rule. - Ensure
InventoryItemResourceremains aligned and no route-name workaround is regressed.
- Replace blanket
- Preserve context behavior:
- Align
InventoryCoverageroute/URL behavior with the canonical environment route if the page still uses a flat admin path. - Keep
InventoryCoverageresolving context throughResolvesPanelTenantContextandOperateHubShell. - Do not add query-only navigation or a new remembered-environment state.
- Align
- Validate:
- Run focused Filament feature tests.
- Add/run a browser smoke only if the rendered sidebar proof is needed.
- Run Pint for touched platform files.
Risk Controls
- Do not touch Entra Groups.
- Do not modify completed Specs
279-300. - Do not replace
NavigationScopewith a page-local helper. - Do not expose environment-owned navigation on
/admin/workspaces/{workspace}. - Do not add Graph calls, queue work, assets, migrations, or OperationRun lifecycle changes.
Rollout Considerations
- Staging: Run the focused feature tests and browser smoke before promotion.
- Production: No migration, env var, queue, cron, storage, or asset deployment impact is expected.
- Rollback: Revert the small navigation/test change if sidebar behavior regresses. No data rollback is required.
Implementation Phases
Phase 1 - Proof and Scope Lock
Update tests so the current bug is expressed as a failing expectation: Inventory is visible in environment context and hidden at workspace home.
Phase 2 - Inventory Navigation Repair
Adjust Inventory cluster/page navigation registration to use the existing environment-navigation contract.
Phase 3 - Context and DB-only Safety
Re-run Inventory Coverage and Inventory hub tests to confirm context resolution, DB-only rendering, and coverage truth remain unchanged.
Phase 4 - Validation and Close-Out
Run the focused validation commands, optional browser smoke, Pint, and final scope checks. Record the close-out note in the active PR.
Filament v5 Output Contract
- Livewire v4.0+ compliance: The repo uses Livewire 4.1.4 with Filament 5.2.1. This slice must not reference Livewire v3 APIs.
- Provider registration location: No provider changes are planned. Existing Laravel provider registration remains in
apps/platform/bootstrap/providers.php. - Globally searchable resources:
InventoryItemResourcehas a View page.InventoryCoverageis a page, not a globally searchable resource. No new global search behavior is introduced. - Destructive actions: None are introduced or changed. If any touched action becomes destructive during implementation, it must use
Action::make(...)->action(...),->requiresConfirmation(), authorization, and current audit/notification rules. - Asset strategy: No assets are registered. Deployment
filament:assetsposture remains unchanged. - Testing plan: Cover Filament navigation registration, workspace-home negative control, environment-bound visibility, Inventory Coverage context, DB-only Inventory rendering, and a bounded browser smoke if rendered sidebar behavior changes.