165 lines
7.7 KiB
Markdown
165 lines
7.7 KiB
Markdown
# Implementation Plan: Tenant UI Polish (Dashboard + Inventory Hub + Operations)
|
|
|
|
**Branch**: `058-tenant-ui-polish` | **Date**: 2026-01-20 | **Spec**: `specs/058-tenant-ui-polish/spec.md`
|
|
**Input**: Feature specification from `specs/058-tenant-ui-polish/spec.md`
|
|
|
|
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.
|
|
|
|
## Summary
|
|
|
|
- Build a drift-first, tenant-scoped dashboard with “Needs Attention” and recent lists.
|
|
- Make Inventory a hub using a Filament cluster to provide consistent left-side sub-navigation across Items / Sync Runs / Coverage.
|
|
- Upgrade Operations index to “orders-style” with KPIs + status tabs filtering the existing `OperationRunResource` table.
|
|
- Enforce DB-only renders (and DB-only polling) and a calm UI: polling only while active runs exist, and no polling churn in modals.
|
|
|
|
## Technical Context
|
|
|
|
<!--
|
|
ACTION REQUIRED: Replace the content in this section with the technical details
|
|
for the project. The structure here is presented in advisory capacity to guide
|
|
the iteration process.
|
|
-->
|
|
|
|
**Language/Version**: PHP 8.4.15 (Laravel 12.47.0)
|
|
**Primary Dependencies**: Filament v5.0.0, Livewire v4.0.1
|
|
**Storage**: PostgreSQL
|
|
**Testing**: Pest v4 (+ PHPUnit v12 runtime)
|
|
**Target Platform**: Web application (Filament admin panel)
|
|
**Project Type**: Web (Laravel monolith)
|
|
**Performance Goals**: Dashboard/Inventory/Operations render quickly (target <2s for typical tenants) with efficient tenant-scoped queries and no N+1.
|
|
**Constraints**: DB-only for all page renders and any polling/auto-refresh; avoid UI churn in modals.
|
|
**Scale/Scope**: Tenant-scoped surfaces; KPI math on existing `operation_runs`, `findings`, inventory tables.
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
|
|
- Inventory-first: clarify what is “last observed” vs snapshots/backups
|
|
- Read/write separation: any writes require preview + confirmation + audit + tests
|
|
- Graph contract path: Graph calls only via `GraphClientInterface` + `config/graph_contracts.php`
|
|
- Deterministic capabilities: capability derivation is testable (snapshot/golden tests)
|
|
- Tenant isolation: all reads/writes tenant-scoped; cross-tenant views are explicit and access-checked
|
|
- Run observability: long-running/remote/queued work creates/reuses `OperationRun`; start surfaces enqueue-only; Monitoring is DB-only; DB-only <2s actions may skip runs but security-relevant ones still audit-log
|
|
- Automation: queued/scheduled ops use locks + idempotency; handle 429/503 with backoff+jitter
|
|
- Data minimization: Inventory stores metadata + whitelisted meta; logs contain no secrets/tokens
|
|
|
|
Status: ✅ No constitution violations for this feature (read-only, DB-only, tenant-scoped; no Graph calls added).
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/058-tenant-ui-polish/
|
|
├── plan.md # This file (/speckit.plan command output)
|
|
├── research.md # Phase 0 output (/speckit.plan command)
|
|
├── data-model.md # Phase 1 output (/speckit.plan command)
|
|
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
|
├── contracts/ # Phase 1 output (/speckit.plan command)
|
|
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
<!--
|
|
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
|
|
for this feature. Delete unused options and expand the chosen structure with
|
|
real paths (e.g., apps/admin, packages/something). The delivered plan must
|
|
not include Option labels.
|
|
-->
|
|
|
|
```text
|
|
app/
|
|
├── Filament/
|
|
│ ├── Clusters/ # New: Inventory cluster
|
|
│ ├── Pages/ # New/updated: tenant dashboard, inventory landing, coverage
|
|
│ ├── Resources/ # Updated: attach inventory resources to cluster; operations tabs/KPIs
|
|
│ └── Widgets/ # New/updated: KPI header widgets
|
|
├── Models/ # Existing: Tenant, OperationRun, Finding, InventoryItem, InventorySyncRun
|
|
└── Providers/Filament/
|
|
└── AdminPanelProvider.php # Update: discoverClusters(), dashboard page class
|
|
|
|
resources/
|
|
└── views/ # Optional: partials/views for dashboard sections
|
|
|
|
tests/
|
|
└── Feature/
|
|
├── Monitoring/ # Existing: Operations DB-only + tenant scope tests
|
|
└── Filament/ # Existing + new: Inventory/Dashboard page tests
|
|
```
|
|
|
|
**Structure Decision**: Laravel monolith + Filament (v5) conventions. Implement UI changes via:
|
|
- Filament Pages (dashboard + inventory pages)
|
|
- Filament Clusters (inventory sub-navigation)
|
|
- Filament Widgets (KPI headers / recent lists)
|
|
- Filament Resource list tabs (operations index filtering)
|
|
|
|
## Complexity Tracking
|
|
|
|
> **Fill ONLY if Constitution Check has violations that must be justified**
|
|
|
|
None.
|
|
|
|
## Phase 0 — Outline & Research (complete)
|
|
|
|
- Output: `specs/058-tenant-ui-polish/research.md`
|
|
- Key decisions captured:
|
|
- Use Filament clusters for the Inventory hub sub-navigation.
|
|
- Use Filament widgets for KPI headers.
|
|
- Enable polling only while active runs exist.
|
|
|
|
## Phase 1 — Design & Contracts (complete)
|
|
|
|
### Data model
|
|
- Output: `specs/058-tenant-ui-polish/data-model.md`
|
|
- No schema changes required.
|
|
|
|
### UI contracts
|
|
- Output: `specs/058-tenant-ui-polish/contracts/ui.md`
|
|
- Output: `specs/058-tenant-ui-polish/contracts/polling.md`
|
|
|
|
### Provider registration (Laravel 11+)
|
|
- Panel providers remain registered in `bootstrap/providers.php` (no changes required for this feature unless adding a new provider).
|
|
|
|
### Livewire / Filament version safety
|
|
- Livewire v4.0+ (required by Filament v5) is in use.
|
|
|
|
### Asset strategy
|
|
- Prefer existing Filament theme CSS and hook classes; avoid publishing Filament internal views.
|
|
- No heavy assets expected; if any new panel assets are added, ensure deployment runs `php artisan filament:assets`.
|
|
|
|
### Destructive actions
|
|
- None introduced in this feature.
|
|
|
|
### Constitution re-check (post-design)
|
|
- ✅ Inventory-first: dashboard uses Inventory/Findings/OperationRun as last-observed state.
|
|
- ✅ Read/write separation: this feature is read-only.
|
|
- ✅ Graph contract path: no Graph calls added.
|
|
- ✅ Tenant isolation: all queries remain tenant-scoped.
|
|
- ✅ Run observability: only consumes existing `OperationRun` records; no new long-running work is introduced.
|
|
- ✅ Data minimization: no new payload storage.
|
|
|
|
## Phase 2 — Implementation Plan (next)
|
|
|
|
### Story 1 (P1): Drift-first tenant dashboard
|
|
- Create a custom Filament dashboard page (tenant-scoped) and wire it in `AdminPanelProvider` instead of the default `Dashboard::class`.
|
|
- Implement drift + ops KPIs and “Needs Attention” + recent lists using DB-only Eloquent queries.
|
|
- Implement conditional polling (only while active runs exist) using widget polling controls.
|
|
- Tests:
|
|
- Add DB-only coverage tests for the dashboard (no outbound HTTP; no queued jobs on render).
|
|
- Add tenant scope tests for the dashboard.
|
|
|
|
### Story 2 (P2): Inventory becomes a hub
|
|
- Add `discoverClusters()` to `AdminPanelProvider`.
|
|
- Create `InventoryCluster` and assign `$cluster` on inventory pages/resources.
|
|
- Add a shared inventory KPI header (widget) across the cluster surfaces.
|
|
- Tests:
|
|
- Extend existing inventory page tests to assert cluster pages load and remain tenant-scoped.
|
|
|
|
### Story 3 (P3): Operations index “orders-style”
|
|
- Update `OperationRunResource` list page to:
|
|
- Add KPI header widgets.
|
|
- Add tabs: All / Active / Succeeded / Partial / Failed.
|
|
- Enable table polling only while active runs exist.
|
|
- Tests:
|
|
- Extend operations tests to assert page renders with tabs and remains DB-only/tenant-scoped.
|