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

214 lines
13 KiB
Markdown

# Implementation Plan: Admin Inventory Navigation Cutover
**Branch**: `301-admin-inventory-navigation-cutover` | **Date**: 2026-05-14 | **Spec**: [spec.md](./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)
```text
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:
```text
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.