TenantAtlas/specs/124-inventory-coverage-table/plan.md
ahmido 3971c315d8 feat: add inventory coverage interactive table (#151)
## Summary
- replace the static Inventory Coverage HTML tables with a Filament native searchable, sortable, filterable table on the existing tenant page
- normalize supported policy types and foundations into one runtime dataset while preserving centralized badge semantics and the documented read-only action-surface exemption
- add the full spec kit artifact set for feature 124 and focused Pest coverage for rendering, search, sort, filters, empty state, and regression-sensitive page copy

## Testing
- `vendor/bin/sail bin pint --dirty --format agent`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/InventoryCoverageTableTest.php tests/Feature/Filament/InventoryPagesTest.php tests/Feature/Filament/InventoryHubDbOnlyTest.php`

## Filament Notes
- Livewire v4.0+ compliance: yes, this uses Filament v5 table APIs on the existing page and does not introduce any Livewire v3 patterns
- Provider registration: unchanged; Laravel 11+ provider registration remains in `bootstrap/providers.php`
- Globally searchable resources: none changed in this feature; no Resource global-search behavior was added or modified
- Destructive actions: none; the page remains read-only and only exposes a non-destructive clear-filters empty-state action
- Asset strategy: no new panel or shared assets were added, so no `filament:assets` deployment change is required for this feature
- Testing plan delivered: focused Filament/Pest coverage for the page table surface plus existing page-load regressions

## Follow-up
- Manual dark-mode and badge-regression QA from task `T018` is still pending and should be completed before merge if that check remains mandatory in your review flow.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #151
2026-03-08 18:33:00 +00:00

6.0 KiB

Implementation Plan: Inventory Coverage Interactive Table

Branch: 124-inventory-coverage-table | Date: 2026-03-08 | Spec: /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/124-inventory-coverage-table/spec.md Input: Feature specification from /Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/124-inventory-coverage-table/spec.md

Note: This template is filled in by the /speckit.plan command. See .specify/scripts/ for helper scripts.

Summary

Convert the tenant-scoped Inventory Coverage page at /admin/t/{tenant}/inventory/coverage from duplicated Blade-rendered static tables into a Filament-native custom-data table backed by the existing inventory policy metadata and coverage capability resolver. The implementation will normalize supported policy types and foundation types into a single runtime dataset, preserve current badge semantics, and add native search, sorting, category filtering, conditional restore-mode filtering, and an explicit zero-results reset path without introducing new storage, routes, or permissions.

Technical Context

Language/Version: PHP 8.4.15
Primary Dependencies: Laravel 12, Filament 5, Livewire 4, Tailwind CSS 4, existing CoverageCapabilitiesResolver, InventoryPolicyTypeMeta, BadgeCatalog, and TagBadgeCatalog
Storage: N/A for this feature; page remains read-only and uses registry/config-derived runtime data while PostgreSQL remains unchanged
Testing: Pest 4 feature/component tests with Filament Livewire table helpers, plus manual dark-mode and badge-regression QA
Target Platform: Laravel Sail local development, Filament admin panel, Dokploy-hosted web deployment
Project Type: web application
Performance Goals: Coverage page render and table interactions stay effectively instantaneous for registry-sized datasets with no external calls and no database writes
Constraints: No data-model redesign, no new API surface, no Graph calls, no new RBAC rules, preserve badge semantics, preserve tenant-scoped access, and keep dark-mode parity
Scale/Scope: One tenant-scoped Filament page, one interactive table, dozens of runtime-derived coverage rows spanning supported policy types and foundations

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

Gate Pre-Research Post-Design Notes
Inventory-first / snapshots-second PASS PASS Read-only inventory coverage metadata only; no backup or snapshot behavior changes.
Read/write separation PASS PASS No writes, no destructive actions, no confirmations or audit mutations introduced.
Graph contract path N/A N/A No Graph calls or contract-registry changes required.
Deterministic capabilities PASS PASS Existing coverage capability resolution stays centralized in existing resolver and metadata catalogs.
Workspace + tenant isolation PASS PASS Existing tenant-scoped page access remains unchanged and server-side gated by current membership/capability checks.
RBAC-UX authorization semantics PASS PASS No new authorization behavior; implementation keeps current tenant-view gating and avoids raw capability strings.
Run observability / Ops-UX N/A N/A No long-running, remote, queued, or scheduled work.
Data minimization PASS PASS Page remains registry-derived and read-only; no extra persistence or logging payloads.
BADGE-001 centralized badge semantics PASS PASS Existing badge catalogs remain the only source for labels, colors, and icons.
Filament Action Surface Contract PASS WITH EXPLICIT EXEMPTION PASS WITH EXPLICIT EXEMPTION Coverage rows are runtime-derived support metadata with no underlying record detail route. The design intentionally omits record inspection and row/bulk actions, and compensates with a first-class searchable/sortable/filterable table plus explicit empty-state reset behavior.
UX-001 layout and IA PASS PASS The page remains a Filament page with a native table, obvious filters, zero-result reset CTA, and dark-mode-safe presentation.

Implementation Notes

  • Restore-mode support is intentionally conditional. The implementation and test suite must use deterministic runtime fixtures for both supported branches: one dataset with restore values so the restore filter is rendered, and one dataset without restore values so the filter is omitted.

Project Structure

Documentation (this feature)

specs/124-inventory-coverage-table/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   └── inventory-coverage-page.openapi.yaml
└── tasks.md

Source Code (repository root)

app/
├── Filament/
│   ├── Clusters/Inventory/InventoryCluster.php
│   ├── Pages/InventoryCoverage.php
│   └── Widgets/Inventory/InventoryKpiHeader.php
├── Services/Inventory/CoverageCapabilitiesResolver.php
└── Support/Inventory/
    ├── InventoryCoverage.php
    └── InventoryPolicyTypeMeta.php

resources/
└── views/filament/pages/inventory-coverage.blade.php

tests/
└── Feature/Filament/
    ├── InventoryPagesTest.php
    └── InventoryCoverageTableTest.php

Structure Decision: Keep the existing single Laravel application structure. Implement the feature inside the current Filament page and Blade view, with no new base directories and with a focused Filament feature test added under tests/Feature/Filament/.

Complexity Tracking

Violation Why Needed Simpler Alternative Rejected Because
Filament table inspection-affordance exemption for coverage rows Coverage entries are derived from runtime registry metadata rather than first-class records with a natural detail route or resource Adding a fake detail page or inert row action would add UI ceremony without improving user value, and would conflict with the feature goal of delivering a concise searchable support matrix