# 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)

```text
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)

```text
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 |
