TenantAtlas/specs/301-admin-inventory-navigation-cutover/plan.md
ahmido 3a30b9060c feat(specs/301): admin inventory navigation cutover (#356)
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
2026-05-14 14:50:08 +00:00

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: InventoryCluster and InventoryCoverage blanket 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 to bootstrap/app.php.
  • Global search: InventoryItemResource already has a View page. InventoryCoverage is 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:assets posture 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.php
    • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec301InventoryNavigationCutoverSmokeTest.php if added
    • cd 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

  1. 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.
  2. Converge Inventory navigation:
    • Replace blanket Filament::getCurrentPanel()?->getId() === 'admin' false returns in Inventory cluster/page classes with the shared environment-navigation rule.
    • Ensure InventoryItemResource remains aligned and no route-name workaround is regressed.
  3. Preserve context behavior:
    • Align InventoryCoverage route/URL behavior with the canonical environment route if the page still uses a flat admin path.
    • Keep InventoryCoverage resolving context through ResolvesPanelTenantContext and OperateHubShell.
    • Do not add query-only navigation or a new remembered-environment state.
  4. 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 NavigationScope with 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

  1. Livewire v4.0+ compliance: The repo uses Livewire 4.1.4 with Filament 5.2.1. This slice must not reference Livewire v3 APIs.
  2. Provider registration location: No provider changes are planned. Existing Laravel provider registration remains in apps/platform/bootstrap/providers.php.
  3. Globally searchable resources: InventoryItemResource has a View page. InventoryCoverage is a page, not a globally searchable resource. No new global search behavior is introduced.
  4. 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.
  5. Asset strategy: No assets are registered. Deployment filament:assets posture remains unchanged.
  6. 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.