# Feature Specification: Filament Table UX Standardization & List Consistency

**Feature Branch**: `125-table-ux-standardization`  
**Created**: 2026-03-08  
**Status**: Draft  
**Input**: User description: "Spec 125 — Filament Table UX Standardization & List Consistency"

## Spec Scope Fields *(mandatory)*

- **Scope**: workspace
- **Primary Routes**: All Filament table surfaces under `/admin`, `/admin/t/{tenant}/...`, and `/system` that render resource lists, relation manager tables, table widgets, custom table pages, or picker tables
- **Data Ownership**: Both workspace-owned and tenant-owned records are affected only at the presentation and interaction layer; this feature does not redefine underlying ownership or introduce new record types
- **RBAC**: Existing workspace membership, tenant membership, plane separation, and capability gates remain unchanged; the standard applies only within each surface’s current authorization boundaries

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Scan Core Lists Predictably (Priority: P1)

As an operator moving between major product lists, I can rely on a consistent default table structure so I can find, sort, and compare records without relearning each screen.

**Why this priority**: Predictable list behavior is the core value of the feature. If major tables still feel inconsistent, the repo-wide standardization effort fails even if individual tables improve cosmetically.

**Independent Test**: Can be fully tested by updating one critical list page to follow the standard and verifying that its primary identifier is searchable and sortable, low-value technical detail is not dominant by default, and the table has a domain-specific empty state.

**Acceptance Scenarios**:

1. **Given** a critical product table with multiple records, **When** the user opens the page, **Then** the table presents a calm default view with a clear primary identifier, meaningful contextual columns, and technical detail kept secondary.
2. **Given** a populated critical table, **When** the user sorts by the primary identifier or recency field, **Then** the list responds in a way that matches the table’s domain purpose.

---

### User Story 2 - Keep List Context Across Refresh (Priority: P2)

As a user investigating records over several page loads, I can refresh or return to key list pages without losing my search, sort, or filter context.

**Why this priority**: Losing table state creates repeated work and breaks operational flow. Persistence is one of the clearest gaps identified in the audit and materially affects day-to-day usability.

**Independent Test**: Can be tested by applying search, sort, and filters on a resource list, refreshing the page, and confirming that the list reopens in the same state.

**Acceptance Scenarios**:

1. **Given** a resource list with an active search term, sort order, and filter selection, **When** the user refreshes the page, **Then** the same list context remains active.
2. **Given** a user returns to a key resource list after navigating away, **When** the page loads again in the same session, **Then** the previously chosen list state is preserved.

---

### User Story 3 - Reveal Detail Only When Needed (Priority: P3)

As an advanced operator, I can access technical fields such as identifiers and timestamps when needed without having those fields dominate every list by default.

**Why this priority**: Enterprise operators still need detail, but the product should present it on demand instead of overwhelming the default table surface.

**Independent Test**: Can be tested by opening a standardized table, confirming that technical detail is hidden by default, and then exposing the detail without losing access to the record’s primary context.

**Acceptance Scenarios**:

1. **Given** a standardized list that contains technical identifiers or low-frequency metadata, **When** the user opens column controls, **Then** those detail fields are available without being forced into the default layout.
2. **Given** a table with long identifiers or technical strings, **When** the user inspects the list, **Then** those values remain readable and accessible without breaking the page layout.

### Edge Cases

- When a table has no records at all, it shows a domain-specific empty state with a clear explanation and only RBAC-allowed next steps.
- When a table contains relation-backed or computed fields that would create unacceptable sort or search cost, the standard allows a documented exception instead of forcing an expensive interaction.
- When a cross-tenant or cross-workspace list is shown, the default visible columns still preserve enough context to distinguish records safely.
- When exact chronology matters more than quick scanning, the table may keep an absolute time presentation as a documented exception to the general relative-time convention.

## Requirements *(mandatory)*

**Constitution alignment (required):** This feature does not introduce Microsoft Graph calls, new write behavior, queue or schedule behavior, or `OperationRun` usage. It standardizes existing table UX on already-authorized screens only.

**Constitution alignment (RBAC-UX):** This feature touches both the tenant/admin plane and the platform plane, but it does not change authorization semantics. Non-membership remains deny-as-not-found, capability denial remains unchanged where it already applies, and all existing action-level server-side authorization must remain intact. Any new empty-state action shown on a surface must stay capability-gated and tenant-safe.

**Constitution alignment (BADGE-001):** Existing centralized badge semantics for status, outcome, severity, and boolean-like signals remain the source of truth. The standard may improve consistency of where badges appear in tables, but it must not introduce local badge vocabularies or ad-hoc status mappings.

**Constitution alignment (Filament Action Surfaces):** This feature satisfies the Action Surface Contract by preserving each table’s existing action architecture as table-local behavior. The scope is limited to list consistency, empty states, pagination, persistence, and column visibility; row actions, bulk actions, header actions, and inspection affordances remain explicit per surface and are not globally redesigned.

**Constitution alignment (UX-001 — Layout & Information Architecture):** This feature directly supports the table portions of UX-001 by requiring meaningful empty states and consistent search, sort, and filtering behavior for core dimensions. It does not change create, edit, or view form layout patterns.

### Functional Requirements

- **FR-001**: The system MUST define and document a repo-wide table standard for all production Filament list surfaces.
- **FR-002**: The standard MUST classify visible table columns into Primary, Context, and Detail tiers as a review and implementation convention.
- **FR-003**: Every production table MUST expose a searchable primary identifier unless a documented exception establishes that search provides no user value for that surface or would introduce unacceptable query cost.
- **FR-004**: Every production table MUST define an explicit default sort unless a documented exception is required for domain or query-safety reasons.
- **FR-005**: Meaningful identifiers, recency fields, statuses, and operational counts MUST be sortable when doing so is useful and safe for the underlying query.
- **FR-006**: Technical identifiers, low-frequency metadata, and secondary timestamps MUST not dominate the default list surface and SHOULD be available as on-demand detail where practical.
- **FR-007**: General-purpose tables SHOULD present no more than seven columns by default unless a denser default view is explicitly justified.
- **FR-008**: Timestamp, null-value, and identifier presentation MUST follow consistent product-wide rules so similar values scan the same way across tables.
- **FR-009**: Every production table MUST provide a domain-specific empty state with clear explanatory copy, and it MUST include a next step only when one is meaningful and authorized.
- **FR-010**: Pagination options and default page sizes MUST follow explicit conventions by table class rather than relying on inconsistent implicit defaults.
- **FR-011**: The designated critical resource lists (`TenantResource`, `PolicyResource`, `BackupSetResource`, `BackupScheduleResource`, `ProviderConnectionResource`, `FindingResource`, and `OperationRunResource`) MUST preserve search, sort, and filter state across refresh within the same session.
- **FR-012**: The standard MUST reduce default horizontal overload by moving lower-value detail out of the initial view before any cosmetic workaround is considered.
- **FR-013**: The rollout MUST not worsen known query-risk tables by forcing expensive sorts, searches, or row-level computations without review.
- **FR-014**: The feature MUST preserve existing RBAC behavior, tenancy boundaries, action semantics, and audit expectations for every affected table surface.
- **FR-015**: The rollout MUST be phased so that conventions and critical high-value tables are addressed before the remaining table surface is aligned.
- **FR-016**: Future table changes MUST be reviewable against the same standard so new list surfaces do not drift back to ad hoc behavior.

## UI Action Matrix *(mandatory when Filament is changed)*

If this feature adds/modifies any Filament Resource / RelationManager / Page, fill out the matrix below.

For each surface, list the exact action labels, whether they are destructive (confirmation? typed confirmation?),
RBAC gating (capability + enforcement helper), and whether the mutation writes an audit log.

| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Resource list tables | app/Filament/Resources/**/Pages/List*.php | Existing table-local actions retained | Existing row inspection affordance retained per resource | Existing resource-local actions retained | Existing grouped bulk actions retained where already supported | Added or refined per table when meaningful and authorized | Unchanged by this spec | Unchanged by this spec | Unchanged | Standardizes list behavior only; no action redesign |
| Relation manager tables | app/Filament/Resources/**/RelationManagers/*.php | Existing relation-manager actions retained | Existing table-local inspection pattern retained | Existing relation-manager row actions retained | Existing grouped bulk actions retained where applicable | Added or refined per table when meaningful and authorized | Unchanged by this spec | Unchanged by this spec | Unchanged | Detail visibility and pagination are standardized without changing mutation semantics |
| Table widgets and custom table pages | app/Filament/Widgets/*.php and app/Filament/Pages/*.php | Existing page or widget actions retained | Existing inspection affordance retained where records are inspectable | Existing row actions retained | Existing grouped bulk actions retained where applicable | Added or refined per surface when meaningful and authorized | Unchanged by this spec | Not applicable unless the page already provides forms | Unchanged | Read-only or operational surfaces may have no row actions; this spec does not force them |
| Picker or selection tables | app/Livewire/** and table-backed selection pages | Existing selection or header actions retained | Existing selection affordance retained | Existing selection-related row actions retained | Existing grouped bulk actions retained where applicable | Added only when it helps a blocked user recover | Unchanged by this spec | Unchanged by this spec | Unchanged | This spec standardizes calm defaults and pagination, not picker workflow semantics |

### Key Entities *(include if feature involves data)*

- **Table Surface**: Any production Filament-backed list surface, including resource lists, relation managers, widgets, custom pages, and picker tables.
- **Column Visibility Tier**: The conceptual classification of a column as Primary, Context, or Detail, used to decide whether it should be dominant, visible by default, or available on demand.
- **Table Behavior Profile**: The combination of default sort, search scope, empty-state behavior, pagination, state persistence, and overflow handling expected for a given table.
- **Documented Exception**: A justified, reviewable deviation from the standard where domain clarity, tenant safety, or query cost makes the default rule inappropriate.

## Assumptions

- The existing audit inventory of approximately 36 production tables is sufficiently accurate to drive phased rollout planning, with minor recount differences allowed during implementation.
- Existing action labels, filters, query scopes, and badge mappings remain table-local unless a later spec proves a shared change is required.
- Critical rollout tables include `TenantResource`, `PolicyResource`, `BackupSetResource`, `BackupScheduleResource`, `ProviderConnectionResource`, `FindingResource`, `OperationRunResource`, and `BackupItemsRelationManager`; query-risk system pages such as `Directory/Workspaces` remain in scope for the broader rollout with documented exceptions where needed.
- Resource-list persistence is mandatory in this phase, while broader persistence beyond those surfaces may be adopted later only where it fits cleanly.

## Dependencies

- The feature depends on an up-to-date inventory of production table surfaces and their current behavior gaps.
- The feature depends on retaining current authorization policies, capability registries, and centralized badge semantics during rollout.
- The feature depends on performance review of relation-backed and computed columns before new sort or search behavior is enabled.

## Success Criteria *(mandatory)*

### Measurable Outcomes

- **SC-001**: In the post-rollout audit, 100% of production tables have an explicit default sort or a documented exception.
- **SC-002**: In the post-rollout audit, 100% of production tables provide a domain-specific empty state.
- **SC-003**: At least 90% of general-purpose production tables present seven or fewer columns by default unless a documented exception exists.
- **SC-004**: On all designated critical resource lists, a user can refresh the page without losing the current search, sort, and filter context during the same session.
- **SC-005**: In manual QA of critical tables, an operator can reach any hidden technical identifier or timestamp needed for troubleshooting in two interactions or fewer.
