TenantAtlas/specs/125-table-ux-standardization/plan.md
ahmido a4f5c4f122 Spec 125: standardize Filament table UX (#152)
## Summary
- standardize Filament table defaults across resources, relation managers, widgets, custom pages, and picker tables
- add shared pagination profiles, calm default column visibility, explicit empty states, and session persistence on designated critical resource lists
- complete Spec 125 artifacts, regression tests, and dashboard widget follow-up for lazy loading, sortable columns, and toggleable detail columns

## Verification
- `docker exec tenantatlas-laravel.test-1 php artisan test --compact --filter=BaselineCompareNow`
- `docker exec tenantatlas-laravel.test-1 php artisan test --compact --filter=TableStandardsBaseline`
- `docker exec tenantatlas-laravel.test-1 php artisan test --compact --filter=TableDetailVisibility`
- `docker exec tenantatlas-laravel.test-1 php artisan test --compact --filter=FilamentTableRiskExceptions`
- full suite run completed: `2017 passed, 10 failed, 8 skipped`
- manual browser QA completed on the tenant dashboard for lazy loading, sortable widget columns, toggleable hidden status columns, badges, and pagination

## Known Failures
The full suite still has 10 pre-existing failures unrelated to this branch:
- `Tests\\Unit\\OpsUx\\SummaryCountsNormalizerTest`
- `Tests\\Feature\\BackupWithAssignmentsConsistencyTest` (2 tests)
- `Tests\\Feature\\BaselineDriftEngine\\CaptureBaselineContentTest`
- `Tests\\Feature\\BaselineDriftEngine\\CompareContentEvidenceTest`
- `Tests\\Feature\\BaselineDriftEngine\\ResolverTest`
- `Tests\\Feature\\Filament\\TenantDashboardDbOnlyTest`
- `Tests\\Feature\\Operations\\ReconcileAdapterRunsJobTrackingTest`
- `Tests\\Feature\\ReviewPack\\ReviewPackRbacTest`
- `Tests\\Feature\\Verification\\VerificationReportRedactionTest`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #152
2026-03-08 22:54:56 +00:00

120 lines
9.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Implementation Plan: Filament Table UX Standardization & List Consistency
**Branch**: `125-table-ux-standardization` | **Date**: 2026-03-08 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/125-table-ux-standardization/spec.md`
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/125-table-ux-standardization/spec.md`
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.
## Summary
Standardize the products Filament list surfaces with a convention-first, native-Filament rollout that keeps table behavior explicit in existing `table()` definitions, adds resource-list state persistence, normalizes default sort and empty-state behavior, and reduces default column sprawl through a documented Primary / Context / Detail model. The implementation will avoid a heavy helper framework, preserve existing action and RBAC behavior, keep centralized badge semantics intact, and allow only a tiny pagination-profile helper early in the rollout where the reuse is purely mechanical and does not hide per-surface table logic.
## Technical Context
**Language/Version**: PHP 8.4.15
**Primary Dependencies**: Laravel 12, Filament 5, Livewire 4, Tailwind CSS 4, existing `BadgeCatalog` / `BadgeRenderer`, existing UI enforcement helpers, existing Filament resources, relation managers, widgets, and Livewire table components
**Storage**: PostgreSQL remains unchanged; this feature is presentation-layer and behavior-layer only
**Testing**: Pest 4 feature tests for critical Filament list surfaces, relation manager coverage where applicable, targeted regression tests for persistence and empty states, plus manual QA for layout calmness and overflow edge cases
**Target Platform**: Laravel Sail local development, Filament admin and system panels in a web application deployed through Dokploy
**Project Type**: web application
**Performance Goals**: No material query regression on existing hot tables; no new obvious N+1 patterns; key list surfaces remain responsive under enterprise-sized datasets; resource-list refresh preserves state without custom client logic
**Constraints**: No new plugin dependency, no macro-first strategy, no heavy base table abstraction, no action redesign, no general search redesign, no panel-wide CSS width hacks, no authorization behavior changes, no new asset pipeline work
**Scale/Scope**: Approximately 36 production Filament table surfaces across resources, relation managers, widgets, custom pages, system pages, and picker tables, with a first-wave focus on critical resource lists plus the most overloaded relation-manager hotspot. Query-risk system tables remain part of the broader rollout and must be aligned conservatively with documented exceptions where needed.
## 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 | The feature changes only list presentation and interaction patterns on existing inventory-, snapshot-, and operations-related surfaces; it does not redefine storage semantics. |
| Read/write separation | PASS | PASS | No new write workflows are introduced. Existing destructive or operational actions remain table-local and unchanged in behavior. |
| Graph contract path | N/A | N/A | No Graph calls or contract registry changes are part of this feature. |
| Deterministic capabilities | PASS | PASS | Existing capability resolution and UI enforcement remain the source of truth; the rollout does not introduce raw capability strings or role checks. |
| Workspace + tenant isolation | PASS | PASS | The feature spans `/admin`, `/admin/t/{tenant}/...`, and `/system`, but keeps each surface inside its current entitlement boundary. |
| RBAC-UX authorization semantics | PASS | PASS | Non-member 404 and member-without-capability 403 semantics remain unchanged; empty-state CTAs must remain capability-gated. |
| Run observability / Ops-UX | N/A | N/A | No new long-running, queued, or remote work is introduced. Existing operation actions remain governed by current `OperationRun` patterns outside this features scope. |
| Data minimization and safe logging | PASS | PASS | The rollout changes table rendering only and does not add new payload logging or persistence. |
| BADGE-001 centralized badge semantics | PASS | PASS | Existing `BadgeCatalog` / `BadgeRenderer` infrastructure stays authoritative. The standard does not create table-local badge mappings. |
| Filament Action Surface Contract | PASS | PASS | Actions remain explicit per surface. The rollout standardizes list consistency without redesigning header, row, bulk, or view actions. |
| UX-001 table obligations | PASS | PASS | The feature directly strengthens empty states, search/sort behavior, and table clarity while leaving create/edit/view layouts untouched. |
| Filament v5 / Livewire v4 compliance | PASS | PASS | The repo already runs Filament v5 on Livewire v4, which remains unchanged by this plan. |
| Panel provider registration | PASS | PASS | No panel provider changes are required; Laravel 11+ panel registration remains in `bootstrap/providers.php`. |
| Global search safety for first-wave resources | PASS | PASS | Tenant, Policy, BackupSet, BackupSchedule, and Finding resources already have View or Edit pages. ProviderConnectionResource and OperationRunResource are explicitly not globally searchable. |
| Asset strategy | PASS | PASS | No new assets are required. Existing deployment expectations, including `php artisan filament:assets`, remain unchanged. |
## Implementation Notes
- The first-wave critical resource surfaces are `TenantResource`, `PolicyResource`, `BackupSetResource`, `BackupScheduleResource`, `ProviderConnectionResource`, `FindingResource`, `OperationRunResource`, and the most overloaded relation-backed table `BackupItemsRelationManager`.
- The current codebase already uses native Filament table features such as `defaultSort()`, `toggleable()`, `emptyStateHeading()`, `emptyStateDescription()`, `emptyStateActions()`, and `paginated([...])`, but session persistence methods are effectively absent and there is no existing shared `StandardTableDefaults` helper. A narrow pagination-profile helper is acceptable as an early foundational aid because it captures only repeated page-size options and keeps search, sort, visibility, and empty-state behavior explicit in each surface.
- `app/Filament/System/Pages/Directory/Workspaces.php` is a confirmed query-risk hotspot because it computes health and recent-failure metrics per row; any new sort/search behavior there must remain conservative.
- `app/Filament/Resources/BackupSetResource/RelationManagers/BackupItemsRelationManager.php` is a confirmed density and action-heavy hotspot; the rollout must calm the default surface without disturbing its existing operational actions.
- Destructive actions are not redesigned here. Existing destructive actions must continue to use `->requiresConfirmation()` and current UI enforcement helpers.
## Project Structure
### Documentation (this feature)
```text
specs/125-table-ux-standardization/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── filament-table-state.openapi.yaml
└── tasks.md
```
### Source Code (repository root)
```text
app/
├── Filament/
│ ├── Pages/
│ │ ├── InventoryCoverage.php
│ │ └── Monitoring/Operations.php
│ ├── Resources/
│ │ ├── TenantResource.php
│ │ ├── PolicyResource.php
│ │ ├── BackupSetResource.php
│ │ ├── BackupScheduleResource.php
│ │ ├── ProviderConnectionResource.php
│ │ ├── FindingResource.php
│ │ ├── OperationRunResource.php
│ │ ├── BackupSetResource/RelationManagers/BackupItemsRelationManager.php
│ │ ├── PolicyResource/RelationManagers/VersionsRelationManager.php
│ │ └── Workspaces/WorkspaceResource.php
│ ├── System/Pages/
│ │ ├── Directory/Tenants.php
│ │ ├── Directory/Workspaces.php
│ │ ├── Ops/Runs.php
│ │ ├── Ops/Failures.php
│ │ ├── Ops/Stuck.php
│ │ └── Security/AccessLogs.php
│ └── Widgets/
│ └── Dashboard/
│ ├── RecentDriftFindings.php
│ └── RecentOperations.php
├── Livewire/
│ ├── BackupSetPolicyPickerTable.php
│ ├── EntraGroupCachePickerTable.php
│ └── SettingsCatalogSettingsTable.php
└── Support/
└── Badges/
├── BadgeCatalog.php
└── BadgeRenderer.php
tests/
├── Feature/Filament/
└── Feature/Rbac/
```
**Structure Decision**: Keep the existing single Laravel application structure and update table behavior at the current surface boundaries. If a tiny shared helper emerges as justified during implementation, it should live under `app/Support/Filament/` or an equally local support namespace and remain limited to mechanical repetition such as pagination profiles.
## Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| None | Not applicable | The design stays within the constitution and the specs anti-abstraction constraints |