TenantAtlas/specs/124-inventory-coverage-table/plan.md
2026-03-08 19:32:04 +01: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