TenantAtlas/specs/126-filter-ux-standardization/plan.md
ahmido c6e7591d19 feat: add Intune RBAC inventory and backup support (#155)
## Summary
- add Intune RBAC role definitions and role assignments as foundation-backed inventory, backup, and versioned snapshot types
- add RBAC-specific normalization, coverage, permission-warning handling, and preview-only restore safety behavior across existing Filament and service surfaces
- add spec 127 artifacts, contracts, audits, and focused regression coverage for inventory, backup, versioning, verification, and authorization behavior

## Testing
- `vendor/bin/sail bin pint --dirty --format agent`
- `vendor/bin/sail artisan test --compact tests/Feature/Inventory/InventorySyncServiceTest.php tests/Feature/Filament/InventoryCoverageTableTest.php tests/Feature/FoundationBackupTest.php tests/Feature/Filament/RestoreExecutionTest.php tests/Feature/RestoreUnknownPolicyTypeSafetyTest.php tests/Unit/GraphContractRegistryTest.php tests/Unit/FoundationSnapshotServiceTest.php tests/Feature/Verification/IntuneRbacPermissionCoverageTest.php tests/Unit/IntuneRoleDefinitionNormalizerTest.php tests/Unit/IntuneRoleAssignmentNormalizerTest.php`

## Notes
- tasks in `specs/127-rbac-inventory-backup/tasks.md` are complete except `T041`, which is the documented manual QA validation step

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #155
2026-03-09 10:40:51 +00:00

14 KiB
Raw Blame History

Implementation Plan: Filter UX Standardization

Branch: 126-filter-ux-standardization | Date: 2026-03-09 | Spec: spec.md Input: Feature specification from /specs/126-filter-ux-standardization/spec.md

Note: This plan is generated by the /speckit.plan workflow and aligned to the current repository constitution.

Summary

Standardize filter UX across TenantPilots important Filament list surfaces using native Filament filters, native session persistence, and light regression guards. The implementation will add the persistence trio to all Tier 1 and Tier 2 filtered resource lists, expand consistent TrashedFilter usage, add missing date-range and essential domain filters on the highest-value surfaces, align prioritized status filters to centralized vocabularies, and extend existing Pest guard and Livewire coverage without introducing a custom filter framework. A thin shared helper layer is intentionally selected for repeated option-source, archived-filter, and date-range mechanics because those repetitions are already proven across the target surfaces. After the main rollout, the plan also allows two low-risk follow-ups where operator review exposed the same gap: BaselineSnapshotResource and BackupItemsRelationManager.

Technical Context

Language/Version: PHP 8.4.15
Primary Dependencies: Laravel 12, Filament v5, Livewire v4.0+, Tailwind CSS v4, Pest v4, existing BadgeCatalog / BadgeRenderer, existing TagBadgeCatalog / TagBadgeRenderer, existing Filament resource tables
Storage: PostgreSQL remains unchanged; session persistence uses Filament-native session keys and existing workspace/tenant context
Testing: Pest v4 feature tests, Livewire component tests for Filament list pages, existing guard tests in tests/Feature/Guards, and focused manual QA for persistence and date-range indicators
Target Platform: Laravel Sail web application with Filament admin and system panels under /admin, /admin/t/{tenant}/..., and /system
Project Type: Laravel monolith / Filament web application
Performance Goals: No material query regression on existing list pages; new date-range and status filters must compose with existing scopes without introducing obvious N+1 or high-cost relation queries; list-state persistence remains native and server-driven
Constraints: Filament-native first, no plugin dependency, no heavy helper framework, no grouped custom filter UI, no authorization behavior changes, no schema changes, no new asset pipeline work, and any extracted helper must remain thin and mechanically scoped
Scale/Scope: 12 Tier 12 resource lists define the core standard; 5 immediate persistence-gap resources, 6 immediate essential-filter targets, 2 prioritized status-source alignments, 1 existing table guard suite to expand, and 2 approved low-effort follow-up surfaces only after core consistency is stable

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 filtering behavior on existing inventory, backup, governance, directory, and monitoring surfaces; no snapshot or inventory semantics change.
Read/write separation PASS PASS No new write workflows or operation starts are introduced. Existing mutations remain unchanged and outside this features scope.
Graph contract path N/A N/A No Microsoft Graph calls, GraphClientInterface usage, or contract registry changes are involved.
Deterministic capabilities PASS PASS No new capabilities, role checks, or permission derivation logic are introduced. Existing capability registries remain authoritative.
Workspace + tenant isolation PASS PASS The design explicitly keeps existing workspace and tenant query scopes intact while adding filters and persistence.
RBAC-UX authorization semantics PASS PASS Non-member 404 and member-without-capability 403 semantics remain unchanged; filter additions must not widen visibility.
Destructive confirmation PASS / N/A PASS / N/A No destructive actions are added or modified. Existing destructive actions remain subject to ->requiresConfirmation().
Global search tenant safety PASS PASS This feature does not expand global search. In-scope resources that are globally searchable already have View pages; resources not intended for global search remain unchanged.
Tenant isolation PASS PASS Tenant-owned list queries remain tenant-scoped, and workspace-scoped canonical monitoring screens remain entitlement-safe.
Run observability / Ops-UX N/A N/A No new long-running, remote, or queued work is introduced.
Data minimization and safe logging PASS PASS No new persistence model or logging payloads are added.
BADGE-001 centralized semantics PASS PASS Status and outcome vocabularies are aligned through existing central badge/catalog infrastructure or thin option-source additions, not ad-hoc local arrays.
Filament Action Surface Contract PASS PASS The feature changes list filters only. Existing header, row, bulk, empty-state, and detail actions remain resource-local.
UX-001 table obligations PASS PASS The feature directly strengthens the table-filter portion of UX-001 by standardizing important list filtering and persistence.
Filament v5 / Livewire v4 compliance PASS PASS All work remains within Filament v5 and Livewire v4-native APIs.
Panel provider registration PASS PASS No panel-provider changes are needed; Laravel 11+ provider registration remains in bootstrap/providers.php.
Asset strategy PASS PASS No new global or on-demand assets are required. Existing deploy-time php artisan filament:assets expectations remain unchanged.

Implementation Notes

  • Livewire v4.0+ compliance: All planned filters, session persistence, and list tests use existing Filament v5 and Livewire v4 patterns already present in the repo.
  • Provider registration location: Unchanged. Filament panel providers remain registered in bootstrap/providers.php.
  • Global search rule: This feature does not make new resources globally searchable. In-scope resources with existing View pages such as FindingResource, PolicyVersionResource, RestoreRunResource, ProviderConnectionResource, InventoryItemResource, AlertDeliveryResource, and EntraGroupResource remain compliant if searched; OperationRunResource remains a non-navigation canonical resource and is not being expanded for global search here.
  • Destructive actions: No new destructive actions are added. Existing destructive actions on changed resources must keep their current authorization and ->requiresConfirmation() handling.
  • Asset strategy: No new assets. Deployment continues to rely on the existing Filament asset process, including php artisan filament:assets where already required.
  • Testing plan: Extend FilamentTableStandardsGuardTest, add focused filter behavior and persistence coverage on changed list pages, and keep representative tenant/workspace scope regression checks.

Project Structure

Documentation (this feature)

specs/126-filter-ux-standardization/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   └── filament-filter-state.openapi.yaml
└── tasks.md

Source Code (repository root)

app/
├── Filament/
│   └── Resources/
│       ├── FindingResource.php
│       ├── InventoryItemResource.php
│       ├── OperationRunResource.php
│       ├── PolicyResource.php
│       ├── TenantResource.php
│       ├── BackupScheduleResource.php
│       ├── BackupSetResource.php
│       ├── RestoreRunResource.php
│       ├── PolicyVersionResource.php
│       ├── ProviderConnectionResource.php
│       ├── AlertDeliveryResource.php
│       ├── EntraGroupResource.php
│       ├── BaselineProfileResource.php
│       ├── AlertRuleResource.php
│       ├── AlertDestinationResource.php
│       └── Workspaces/WorkspaceResource.php
├── Models/
│   ├── Finding.php
│   ├── AlertDelivery.php
│   └── BaselineProfile.php
└── Support/
    ├── Badges/
    │   ├── BadgeCatalog.php
    │   ├── BadgeRenderer.php
    │   ├── TagBadgeCatalog.php
    │   └── Domains/
    └── Baselines/
        └── BaselineProfileStatus.php

tests/
├── Feature/
│   ├── Guards/
│   │   └── FilamentTableStandardsGuardTest.php
│   ├── Filament/
│   │   ├── TableStatePersistenceTest.php
│   │   ├── Findings/
│   │   ├── Alerts/
│   │   └── [resource-specific table tests]
│   └── Rbac/
└── Browser/
    └── [not expected for first pass]

Structure Decision: Keep the work in the existing Laravel/Filament monolith and update resource-local table() definitions plus the current guard and feature test suites. The thin shared helper layer should live under app/Support/Filament/ and remain limited to repeated mechanical presets such as centralized option sourcing plus archive and date-range filters.

Complexity Tracking

Violation Why Needed Simpler Alternative Rejected Because
None Not applicable The design stays within the constitution and the specs no-framework constraint

Approved Exceptions

  • None approved. The only implementation risk that surfaced was RestoreRunResource needing an explicit tenant-scoped base query to preserve intended isolation.
  • No transitional status-source exceptions remain for FindingResource or AlertDeliveryResource; both now use the thin shared option catalog.

Phase 0 — Research (output: research.md)

See: research.md

Research goals:

  • Confirm the native Filament patterns already used for persistence, date-range filters, and archive visibility.
  • Confirm the current resource-level gaps on the Tier 1 and Tier 2 targets.
  • Confirm the existing centralized badge and enum sources that can back status and outcome filter options.
  • Confirm the current guard and functional tests that should be extended rather than replaced.

Phase 1 — Design & Contracts (outputs: data-model.md, contracts/, quickstart.md)

See:

Design focus:

  • Model filter behavior as a contract over existing resource tables rather than as a new runtime subsystem.
  • Keep the standard resource-local and Filament-native, with only thin preset extraction for repeated mechanical patterns.
  • Make persistence mandatory on Tier 1 and Tier 2 resource lists while keeping relation managers, widgets, and pickers out of scope unless already justified. BackupItemsRelationManager is the explicit justified exception because the gap surfaced during real backup review, and BaselineSnapshotResource is the matching workspace-scoped follow-up.
  • Treat centralized status vocabularies as existing domain assets that may need thin option helpers rather than broad enum migrations everywhere.
  • Preserve query safety and tenancy/workspace boundaries while adding date-range and essential domain filters.

Phase 2 — Implementation Outline (tasks created in /speckit.tasks)

Persistence and guard foundation

  • Add persistFiltersInSession(), persistSearchInSession(), and persistSortInSession() to the missing Tier 1 and Tier 2 filtered resource lists.
  • Expand FilamentTableStandardsGuardTest so Tier 1 and Tier 2 persistence expectations are enforced consistently.

Essential filter rollout

  • Add the missing date-range and essential domain filters on RestoreRunResource, PolicyVersionResource, FindingResource, AlertDeliveryResource, InventoryItemResource, and BaselineProfileResource.
  • Reuse the existing OperationRunResource date-range pattern as the native model where feasible.

Consistency alignment

  • Replace prioritized manual status arrays with centralized option sources, starting with FindingResource and AlertDeliveryResource.
  • Keep archive visibility and recurring labels aligned with the documented filter standard.
  • Introduce only the small preset/helper layer already justified by repeated archived-filter, date-range, and centralized-option patterns.

Regression protection

  • Extend guard coverage for archive visibility and prioritized centralized status sourcing.
  • Add focused Livewire and feature tests that prove filters apply, clear, compose, and remain scope-safe on representative surfaces.

Verification

  • Run focused Pest suites for guards and changed resource table behavior.
  • Run Pint on dirty files through Sail.
  • Perform manual QA on refresh/navigation persistence, date-range indicators, and archive semantics on representative tenant and workspace lists.
  • Perform targeted follow-up QA on BaselineSnapshotResource and BackupItemsRelationManager once the core Tier 12 rollout is stable.

Constitution Check (Post-Design)

Re-check result: PASS. The design introduces no new routes, storage, authorization rules, background work, or asset requirements. It strengthens UX consistency through existing Filament-native table APIs, preserves current RBAC and tenancy boundaries, and keeps the implementation bounded to list behavior plus regression guards.