TenantAtlas/specs/122-empty-state-consistency/spec.md
ahmido 73a3a62451 Spec 122: Empty state consistency pass (#148)
## Summary
- unify empty-state UX across the six in-scope Filament list pages
- move empty-state ownership toward resource `table()` definitions while preserving existing RBAC behavior
- add focused Pest coverage for empty-state rendering, CTA outcomes, populated-state regression behavior, and action-surface compliance
- add the Spec 122 planning artifacts and product discovery documents used for this pass

## Changed surfaces
- `PolicyResource`
- `BackupSetResource`
- `RestoreRunResource`
- `BackupScheduleResource`
- `WorkspaceResource`
- `AlertDeliveryResource`

## Tests
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/EmptyStateConsistencyTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/Alerts/AlertDeliveryViewerTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/CreateCtaPlacementTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/PolicySyncStartSurfaceTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/BackupScheduling/BackupScheduleLifecycleAuthorizationTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/BackupSetUiEnforcementTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Filament/RestoreRunUiEnforcementTest.php`
- `vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php`
- `vendor/bin/sail bin pint --dirty --format agent`

## Notes
- Filament v5 / Livewire v4.0+ compliance is preserved.
- Panel provider registration remains unchanged in `bootstrap/providers.php`.
- No new globally searchable resources were added.
- Destructive actions were not introduced by this pass.
- Alert Deliveries is documented as the explicit no-header-action exemption for the empty-state CTA relocation rule.
- Manual light/dark visual QA evidence is still expected in the PR/review artifact set for the remaining checklist items (`T018`, `T025`).

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #148
2026-03-08 02:17:51 +00:00

14 KiB
Raw Permalink Blame History

Feature Specification: Empty State Consistency Pass

Feature Branch: 122-empty-state-consistency
Created: 2026-03-08
Status: Ready for Implementation
Input: Spec 122 — Empty State Consistency Pass (Unified empty states across all primary list pages)

Clarifications

Session 2026-03-08

  • Q: What should the single empty-state CTA be for the read-only Alert Deliveries list? → A: Use “View alert rules” as the single CTA.
  • Q: How should empty-state CTA visibility behave for members who lack the required capability? → A: Preserve existing per-resource behavior (disabled or hidden), but require explanation when shown disabled.
  • Q: Where should the final empty-state configuration live? → A: Prefer resource table() definitions for empty-state heading/description/icon/action, and allow page helpers only when technically required.
  • Q: How should screenshots and visual QA evidence be handled for this feature? → A: Attach screenshots / visual QA evidence to the PR or review, not as committed repo artifacts.

Spec Scope Fields (mandatory)

  • Scope: workspace
  • Primary Routes:
    • Admin UI list pages: Policies, Backup Sets, Restore Runs, Backup Schedules, Workspaces, Alert Deliveries
  • Data Ownership:
    • Tenant-owned lists: Policies, Backup Sets, Restore Runs, Backup Schedules
    • Workspace-owned / workspace-context lists: Workspaces
    • Workspace-context monitoring history list: Alert Deliveries (may include tenant-bound rows; tenant entitlement still applies)
  • RBAC:
    • Membership isolation: non-members are deny-as-not-found (404 semantics)
    • Capability gating: members without the required capability receive authorization denial (403 on execution); UI may show disabled actions with explanatory tooltip
    • Empty-state primary actions MUST remain capability-aware and MUST use the existing UI enforcement helpers already used by each module

User Scenarios & Testing (mandatory)

User Story 1 - First-run clarity on empty lists (Priority: P1)

As a first-time admin, I want to immediately understand what each list page represents when it has no data yet, and what my next best action is.

Why this priority: This is the first impression for new tenants/workspaces and for demos.

Independent Test: For each in-scope list page, with zero records, the page renders a complete empty state (icon + heading + description + one primary action).

Acceptance Scenarios:

  1. Given I open an in-scope list page with no records, When the table renders, Then I see an icon, heading, description, and a single primary action.
  2. Given I click the primary empty-state action, When I have the required permission, Then I am taken to the intended next step (or the intended operation is queued) without errors.

User Story 2 - Enterprise-grade consistency during evaluation (Priority: P2)

As a product evaluator, I want empty pages to feel intentional and guided, with consistent hierarchy and tone.

Why this priority: In low-data environments, evaluators spend disproportionate time on empty states.

Independent Test: Visual and UI assertions confirm consistent presence and ordering of empty-state elements across all in-scope pages.

Acceptance Scenarios:

  1. Given I visit each in-scope list page with no records, When I compare the empty states, Then they share consistent structure and enterprise-appropriate wording (no scaffold-like presentation).

User Story 3 - Permission-aware guidance (Priority: P3)

As a workspace/tenant member without a required capability, I want to understand what Im missing without the UI leaking access outside my membership scope.

Why this priority: Capability-aware UX reduces support load and aligns with RBAC-UX.

Independent Test: With membership but missing capability, the empty-state action is not actionable and explains why; server-side authorization remains enforced.

Acceptance Scenarios:

  1. Given I am a valid member but lack the capability for the primary action, When I view the empty page, Then the CTA is disabled (or hidden where thats the existing pattern) and communicates the missing permission.
  2. Given I am not entitled to the workspace/tenant scope, When I attempt to access the list page, Then the app responds as not found (404 semantics).

Edge Cases

  • Empty state must still render correctly in dark mode and light mode.
  • Empty state must behave correctly when the tenant context is missing/invalid (records are not shown and the page does not leak data).
  • Alert Deliveries list can be empty even when alerts are configured (e.g., no alerts fired yet); copy must set that expectation.

Requirements (mandatory)

Constitution alignment (required): This feature introduces no new external integrations and no new background work. It only adjusts how existing list pages communicate “no records” states and which single next-step action is presented.

Constitution alignment (OPS-UX): This feature MUST NOT change operation UX semantics. Where an empty-state action already queues an operation (e.g., sync), it continues to follow the existing 3-surface feedback contract and uses the canonical operation UX presenter.

Constitution alignment (RBAC-UX): This feature MUST NOT relax authorization. It reuses existing capability gating and server-side authorization. Membership remains deny-as-not-found (404 semantics); missing capability remains 403 on execution.

Constitution alignment (Filament Action Surfaces): This feature modifies list empty states and therefore MUST satisfy the Action Surface Contract for the “ListEmptyState” slot for each in-scope resource.

Constitution alignment (UX-001 — Layout & Information Architecture): Each in-scope list pages empty state must have a specific title, an explanation, and exactly 1 CTA.

Functional Requirements

  • FR-001: Each in-scope primary list page MUST render a complete empty state when there are zero records.
  • FR-002: Each empty state MUST include: icon, heading, description, and exactly one primary action.
  • FR-003: Empty-state copy MUST be contextual to the module and explain both (a) why its empty and (b) the next best action.
  • FR-004: Empty-state primary actions MUST remain capability-aware and MUST respect existing UI enforcement rules.
  • FR-004a: The feature MUST preserve each resources existing CTA visibility model for capability enforcement rather than forcing all empty-state actions into a single visible-disabled or hidden-only pattern.
  • FR-004b: When an empty-state CTA is shown disabled for a valid member, it MUST explain the missing permission using the resources existing helper text or tooltip pattern.
  • FR-005: Empty-state rendering MUST remain correct in both light and dark mode.
  • FR-006: Empty-state configuration MUST be defined in a single, consistent place per list page (to prevent drift and scaffold-like inconsistencies).
  • FR-006a: Where Filament supports it, empty-state heading, description, icon, and action MUST be defined in the resource table() configuration.
  • FR-006b: Page-level empty-state helpers MAY be used only when technically required, and MUST NOT split responsibility in a way that causes drift between heading/description/icon/action definitions.
  • FR-007: Out-of-scope resources MUST remain unchanged, including: Finding, Entra Group, Policy Version, Operation Run.
  • FR-008: The Alert Deliveries empty state MUST use a single navigational CTA labeled “View alert rules” to direct operators to the configuration surface most likely to explain or resolve an empty history.
  • FR-008a: Alert Deliveries is the sole explicit UX-001 relocation exemption for this feature: the View alert rules CTA appears only in the empty state and MUST NOT persist as a table-header action once deliveries exist, because the surface remains intentionally read-only and header-action free.

Module-specific empty-state copy (baseline direction)

  • Policies: “No policies synced yet. Sync your first tenant to see Intune policies here.”
  • Backup Sets: “No backup sets. Create a backup set to start protecting your configurations.”
  • Restore Runs: “No restore runs. Start a restoration from a backup set.”
  • Backup Schedules: “No schedules configured. Set up automated backups.”
  • Workspaces: “No workspaces. Create your first workspace.”
  • Alert Deliveries: “No alert deliveries. Deliveries appear automatically when alert rules fire.”

Clarified CTA direction

  • Alert Deliveries: use a single CTA labeled “View alert rules”.

UI Action Matrix (mandatory when Filament is changed)

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
Policy list Admin UI — Policies list page “Sync from Intune” View action View + “More” (as-is) As-is “Sync from Intune” As-is N/A (read-only details) No CTA continues to queue the existing sync operation; no change to operation UX semantics.
Backup Sets list Admin UI — Backup Sets list page “Create” (existing behavior) View action View + “More” Yes “Create backup set” As-is Create/Edit as-is Yes (existing audit logger) Empty state becomes contextual and guided; CTA remains capability gated.
Restore Runs list Admin UI — Restore Runs list page “Create” (existing behavior) As-is As-is Yes “New restore run” As-is Create wizard as-is Yes (existing audit logger) Empty state becomes contextual and guided; CTA remains capability gated.
Backup Schedules list Admin UI — Backup Schedules list page “New backup schedule” (existing behavior) Clickable row View/Edit as-is Yes “New backup schedule” Edit page header as-is Save/Cancel as-is No CTA remains capability-aware; disabled state explains missing permission.
Workspaces list Admin UI — Workspaces list page “New workspace” (existing behavior) View action View/Edit as-is No “New workspace” As-is Save/Cancel as-is No Workspace membership isolation remains deny-as-not-found.
Alert Deliveries list Monitoring — Alert Deliveries list page None (read-only) Clickable row None None “View alert rules” (navigation) View page (read-only) N/A No Adds guided empty state despite read-only list; CTA is a next-step navigation to alert rule configuration, not a mutation. Explicit UX-001 exemption: this CTA does not relocate to the header when records exist.

RBAC clarification

  • Preserve each resources current capability-aware CTA behavior (disabled vs hidden) rather than standardizing all empty-state actions to one pattern.

Placement clarification

  • Prefer resource table() definitions for empty-state heading, description, icon, and action; use page helpers only when technically required.

Visual QA evidence clarification

  • Screenshot and dark-mode visual QA evidence for affected resources must be attached to the PR or review record, not committed into the repository.

Explicit exemptions

  • Alert Deliveries header-action exemption: Alert Deliveries remains a read-only monitoring history surface with no persistent header action. Its single CTA (View alert rules) exists only while the list is empty. Once deliveries exist, the CTA does not relocate to the header; this is an explicit UX-001 exemption for this feature and must remain documented in the PR or review.

Acceptance Criteria / Definition of Done

  1. All in-scope resources render a full empty state when the table has no records.
  2. Each empty state includes icon, heading, description, and exactly one primary CTA.
  3. Empty-state actions preserve existing RBAC/UI-enforcement behavior.
  4. Visual review confirms centered, intentional hierarchy consistent with the baseline reference pattern.
  5. Dark mode renders correctly for every affected list page.
  6. Populated-table behavior remains unchanged.
  7. Screenshot or visual QA evidence for all affected resources is attached to the PR or review artifact set, rather than committed to the repository.

Testing Requirements

  • Feature/UI test per in-scope resource for empty table rendering.
  • Feature/UI test coverage for each in-scope CTA outcome so empty-state actions either navigate to the intended next step or queue the intended existing operation.
  • Permission test coverage to ensure CTA visibility or disabled state remains aligned with existing resource behavior.
  • Manual visual verification in light and dark mode for every affected list page.
  • Automated regression coverage for representative populated-table behavior, including CTA relocation for create-capable surfaces and the documented no-header-action exemption for Alert Deliveries.
  • Smoke test confirming populated resources still render their standard tables and existing actions.
  • PR/review attachment checklist confirming screenshots or equivalent visual QA evidence were captured for all affected resources.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: 100% of in-scope list pages display icon + heading + description + 1 CTA when empty.
  • SC-002: In a first-run demo with no records, an evaluator can correctly identify the purpose and next action on each in-scope page without guidance.
  • SC-003: Users without capability can still understand the required permission from the disabled/hidden state messaging, without any cross-scope leakage.
  • SC-004: No regressions: populated tables continue to render their existing columns, actions, and behaviors unchanged.