---
description: "Task list for feature implementation"
---

# Tasks: Tenant UI Polish (Dashboard + Inventory Hub + Operations)

**Input**: Design documents from `specs/058-tenant-ui-polish/`

**Tests**: Required (Pest) — this feature changes runtime UI behavior.

---

## Phase 1: Setup (Shared Infrastructure)

- [X] T001 Confirm feature inputs exist: specs/058-tenant-ui-polish/spec.md, specs/058-tenant-ui-polish/plan.md
- [X] T002 Confirm Phase 0/1 artifacts exist: specs/058-tenant-ui-polish/research.md, specs/058-tenant-ui-polish/data-model.md, specs/058-tenant-ui-polish/contracts/ui.md, specs/058-tenant-ui-polish/contracts/polling.md, specs/058-tenant-ui-polish/quickstart.md

---

## Phase 2: Foundational (Blocking Prerequisites)

- [X] T003 Create shared helper to detect “active runs exist” for tenant polling in app/Support/OpsUx/ActiveRuns.php
- [X] T004 [P] Add focused tests for the helper in tests/Feature/OpsUx/ActiveRunsTest.php

**Checkpoint**: Shared polling predicate exists and is covered.

---

## Phase 3: User Story 1 — Drift-first tenant dashboard (Priority: P1) 🎯 MVP

**Goal**: Tenant-scoped dashboard that surfaces drift + ops KPIs and “Needs Attention”, DB-only.

**Independent Test**: Visiting the dashboard renders drift KPIs, ops KPIs, needs-attention CTAs, and recent lists (10 rows), with no outbound HTTP and no background work dispatched.

### Tests (US1)

- [X] T005 [P] [US1] Add DB-only render test (no outbound HTTP, no background work) in tests/Feature/Filament/TenantDashboardDbOnlyTest.php
- [X] T006 [P] [US1] Add tenant isolation test (no cross-tenant leakage) in tests/Feature/Filament/TenantDashboardTenantScopeTest.php

### Implementation (US1)

- [X] T007 [US1] Create tenant dashboard page in app/Filament/Pages/TenantDashboard.php
- [X] T008 [US1] Register the tenant dashboard page in app/Providers/Filament/AdminPanelProvider.php (replace default Dashboard page entry)
- [X] T009 [P] [US1] Create dashboard KPI widget(s) in app/Filament/Widgets/Dashboard/DashboardKpis.php
- [X] T010 [P] [US1] Create “Needs Attention” widget in app/Filament/Widgets/Dashboard/NeedsAttention.php
- [X] T011 [P] [US1] Create “Recent Drift Findings” widget (10 rows) in app/Filament/Widgets/Dashboard/RecentDriftFindings.php
- [X] T012 [P] [US1] Create “Recent Operations” widget (10 rows) in app/Filament/Widgets/Dashboard/RecentOperations.php
- [X] T013 [US1] Wire widgets into the dashboard page in app/Filament/Pages/TenantDashboard.php (header/sections) and implement conditional polling per specs/058-tenant-ui-polish/contracts/polling.md
- [X] T014 [US1] Implement drift stale rule (7 days) + CTA wiring in app/Filament/Widgets/Dashboard/NeedsAttention.php
- [X] T015 [US1] Ensure all dashboard queries are tenant-scoped + DB-only in app/Filament/Pages/TenantDashboard.php and app/Filament/Widgets/Dashboard/*.php

**Checkpoint**: US1 is shippable as an MVP.

---

## Phase 4: User Story 2 — Inventory becomes a hub module (Priority: P2)

**Goal**: Inventory becomes a cluster “hub” with consistent left sub-navigation and a shared KPI header across Items / Sync Runs / Coverage.

**Independent Test**: Navigating Items → Sync Runs → Coverage keeps consistent sub-navigation and shared KPI header, tenant-scoped and DB-only.

### Tests (US2)

- [X] T016 [P] [US2] Add DB-only render test for Inventory hub surfaces in tests/Feature/Filament/InventoryHubDbOnlyTest.php
- [X] T017 [P] [US2] Extend/adjust inventory navigation smoke coverage in tests/Feature/Filament/InventoryPagesTest.php

### Implementation (US2)

- [X] T018 [US2] Enable cluster discovery in app/Providers/Filament/AdminPanelProvider.php (add `discoverClusters(...)`)
- [X] T019 [US2] Create Inventory cluster class in app/Filament/Clusters/Inventory/InventoryCluster.php
- [X] T020 [US2] Assign Inventory cluster to inventory pages in app/Filament/Pages/InventoryLanding.php and app/Filament/Pages/InventoryCoverage.php
- [X] T021 [US2] Assign Inventory cluster to inventory resources in app/Filament/Resources/InventoryItemResource.php and app/Filament/Resources/InventorySyncRunResource.php
- [X] T022 [P] [US2] Create shared Inventory KPI header widget in app/Filament/Widgets/Inventory/InventoryKpiHeader.php
- [X] T023 [US2] Add Inventory KPI header widget to InventoryLanding in app/Filament/Pages/InventoryLanding.php
- [X] T024 [US2] Add Inventory KPI header widget to InventoryCoverage in app/Filament/Pages/InventoryCoverage.php
- [X] T025 [US2] Add Inventory KPI header widget to Inventory items list in app/Filament/Resources/InventoryItemResource.php (or its list page)
- [X] T026 [US2] Add Inventory KPI header widget to Inventory sync runs list in app/Filament/Resources/InventorySyncRunResource.php (or its list page)
- [X] T027 [US2] Ensure Inventory KPI definitions match specs/058-tenant-ui-polish/contracts/ui.md (coverage % restorable/total; partial separate; two active operations counts)
- [X] T041 [US2] Inventory coverage semantics reference (A2)
	- Identify and document the exact source-of-truth fields for Inventory KPI aggregation:
		- `inventory_items.policy_type`
		- `config('tenantpilot.supported_policy_types')` meta fields (`restore`, `risk`)
		- Dependency support via existing dependency capability resolver
	- Ensure KPI and chips read from this source only (DB-only).
	- DoD:
		- One canonical place documented and referenced by inventory KPIs.
		- No “magic” or duplicated classification logic across pages/widgets.
- [X] T028 [US2] Ensure “Sync Runs” view is inventory-only per spec in app/Filament/Resources/InventorySyncRunResource.php (query/filter by run type/intent if needed)
- [X] T029 [US2] Standardize coverage chips set on coverage-related surfaces in app/Filament/Pages/InventoryCoverage.php (Restorable, Partial, Risk, Dependencies only)

**Checkpoint**: Inventory hub behaves as a module with consistent sub-navigation + header.

---

## Phase 5: User Story 3 — Operations index “Orders-style” (Priority: P3)

**Goal**: Operations index shows KPIs + status tabs + table, with calm conditional polling.

**Independent Test**: Visiting Operations index shows KPIs and tabs that filter runs per specs/058-tenant-ui-polish/contracts/ui.md, DB-only, calm.

### Tests (US3)

- [X] T030 [P] [US3] Extend Operations DB-only test assertions in tests/Feature/Monitoring/OperationsDbOnlyTest.php (assert tabs/KPI labels appear)
- [X] T031 [P] [US3] Extend Operations tenant isolation coverage in tests/Feature/Monitoring/OperationsTenantScopeTest.php (assert tab views don’t leak)

### Implementation (US3)

- [X] T032 [P] [US3] Create Operations KPI header widget in app/Filament/Widgets/Operations/OperationsKpiHeader.php
- [X] T033 [US3] Add KPIs to the Operations list page in app/Filament/Resources/OperationRunResource/Pages/ListOperationRuns.php
- [X] T034 [US3] Implement status tabs (All/Active/Succeeded/Partial/Failed) on Operations list page in app/Filament/Resources/OperationRunResource/Pages/ListOperationRuns.php
- [X] T035 [US3] Ensure tab filter logic matches specs/058-tenant-ui-polish/contracts/ui.md by adjusting queries in app/Filament/Resources/OperationRunResource/Pages/ListOperationRuns.php
- [X] T036 [US3] Implement conditional polling for Operations list (only while active runs exist) by wiring table polling in app/Filament/Resources/OperationRunResource.php and/or app/Filament/Resources/OperationRunResource/Pages/ListOperationRuns.php
- [X] T037 [US3] Ensure canonical “View run” links still route to OperationRunResource view pages (no legacy routes)
	- Verify existing canonical link helper `App\Support\OperationRunLinks` is used consistently.
	- If no suitable helper exists for a given surface, add a minimal equivalent and use it everywhere.

- [X] T042 [US3] Operations terminology sweep (FR-010)
	- Goal: The UI uses the canonical label “Operations” consistently; no legacy naming remains.
	- Audit + fix in:
		- Navigation label(s)
		- Page titles / breadcrumbs
		- Resource titles / headings
		- Any links mentioning “Bulk Operation Runs” or legacy run naming
	- DoD:
		- No occurrences of legacy labels remain in UI surfaces for Monitoring/Operations.
		- `rg -n "Bulk Operation|BulkOperationRun|Bulk Operation Runs" app resources` returns 0 matches (or matches only in tests explicitly allowed).
		- If ripgrep is unavailable, use `grep -R` with the same patterns.

**Checkpoint**: Operations index is “orders-style” with calm refresh behavior.

---

## Phase 6: Polish & Cross-Cutting Concerns

- [X] T038 [P] Run formatting on changed files in app/** and tests/** via `vendor/bin/sail bin pint --dirty`
- [X] T039 Run targeted tests from specs/058-tenant-ui-polish/quickstart.md and ensure green
- [X] T040 [P] Smoke-check key pages render for a tenant in tests/Feature/Filament/AdminSmokeTest.php (add assertions only if gaps are found)
- [X] T043 Refactor KPI headers to StatsOverviewWidget (Inventory + Operations) to match Filament demo tiles and reduce custom Blade drift
- [X] T044 Inventory IA polish: remove Inventory “Overview”, make Items the default entry, rename “Inventory Sync Runs” → “Sync History”, and move “Run Inventory Sync” to Items header actions

---

## Dependencies & Execution Order

### User Story Dependencies

- US1 (P1) is standalone and can ship first.
- US2 (P2) can be implemented after foundational polling helper; it touches the panel provider and inventory pages/resources.
- US3 (P3) can be implemented after foundational polling helper; it touches the operations resource list page.

Suggested order (MVP-first): Phase 1 → Phase 2 → US1 → US2 → US3 → Polish.

### Parallel Opportunities (examples)

- US1: T009–T012 can be developed in parallel (different widget files).
- US2: T022 can be developed in parallel while T018–T021 are in review.
- US3: T032 can be developed in parallel with test updates (T030–T031).

---

## Parallel Execution Examples (per user story)

### US1
- T005 [P] [US1] tests/Feature/Filament/TenantDashboardDbOnlyTest.php
- T006 [P] [US1] tests/Feature/Filament/TenantDashboardTenantScopeTest.php
- T009 [P] [US1] app/Filament/Widgets/Dashboard/DashboardKpis.php
- T010 [P] [US1] app/Filament/Widgets/Dashboard/NeedsAttention.php
- T011 [P] [US1] app/Filament/Widgets/Dashboard/RecentDriftFindings.php
- T012 [P] [US1] app/Filament/Widgets/Dashboard/RecentOperations.php

### US2
- T016 [P] [US2] tests/Feature/Filament/InventoryHubDbOnlyTest.php
- T022 [P] [US2] app/Filament/Widgets/Inventory/InventoryKpiHeader.php

### US3
- T030 [P] [US3] tests/Feature/Monitoring/OperationsDbOnlyTest.php
- T031 [P] [US3] tests/Feature/Monitoring/OperationsTenantScopeTest.php
- T032 [P] [US3] app/Filament/Widgets/Operations/OperationsKpiHeader.php

---

## Implementation Strategy

### MVP First (US1 only)

1. Complete Phase 1 + Phase 2
2. Implement US1 (dashboard)
3. Run: `vendor/bin/sail artisan test tests/Feature/Filament/TenantDashboardDbOnlyTest.php`
4. Run: `vendor/bin/sail artisan test tests/Feature/Filament/TenantDashboardTenantScopeTest.php`

### Incremental Delivery

- Add US2 next (Inventory hub), then US3 (Operations index).
- After each story, run its targeted tests + the cross-cutting DB-only tests.
