---

description: "Task list for RBAC UI Enforcement Helper v2"

---

# Tasks: RBAC UI Enforcement Helper v2 (Suite-wide, Mixed Visibility, Record-Scoped)

**Input**: Design documents from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/`  
**Prerequisites**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/plan.md` (required), `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/spec.md` (required), `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/research.md`, `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/data-model.md`, `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/contracts/`, `/Users/ahmeddarrazi/Documents/projects/TenantAtlas-066-rbac-ui-enforcement-helper-v2/specs/066-rbac-ui-enforcement-helper/quickstart.md`

**Tests**: REQUIRED (Pest) for runtime behavior changes  
**RBAC**: Tenant plane only (`/admin/t/{tenant}`); non-member is deny-as-not-found (404); member without capability is disabled + tooltip and cannot execute; destructive actions require confirmation  
**Organization**: Tasks are grouped by user story (US1–US4) to enable independent delivery.

## Phase 1: Setup (Shared Infrastructure)

**Purpose**: Prepare local environment + validate baseline

- [X] T001 Start containers with `./vendor/bin/sail up -d` (script: `./vendor/bin/sail`)
- [X] T002 Run baseline guard suite with `./vendor/bin/sail artisan test tests/Feature/Guards --compact` (folder: `tests/Feature/Guards`)
- [X] T003 Run baseline tenant RBAC suite with `./vendor/bin/sail artisan test tests/Feature/Rbac --compact` (folder: `tests/Feature/Rbac`)

---

## Phase 2: Foundational (Blocking Prerequisites)

**Purpose**: Shared helper + guardrails required by all story migrations

**Checkpoint**: `UiEnforcement` supports mixed visibility, record-scoped tenant resolution, and bulk preflight; guard exists and is allowlist-driven

- [X] T004 Create `UiTooltips` with the v2 default disabled tooltip copy in `app/Support/Auth/UiTooltips.php`
- [X] T005 Create/verify v1 baseline `UiEnforcement` helper in `app/Support/Auth/UiEnforcement.php` (apply hidden/disabled/tooltip + server-side guard using `Capabilities::*`)
- [X] T006 [P] Add mixed visibility APIs (`preserveVisibility()` tenant-scoped only, `andVisibleWhen()`, `andHiddenWhen()`) in `app/Support/Auth/UiEnforcement.php`
- [X] T007 [P] Add tenant resolver APIs (`tenantFromFilament()`, `tenantFromRecord()`, `tenantFrom(callable)`) in `app/Support/Auth/UiEnforcement.php`
- [X] T008 [P] Add bulk preflight APIs (`preflightSelection()`, `preflightByTenantMembership()`, `preflightByCapability()`) with authorization-only all-or-nothing default in `app/Support/Auth/UiEnforcement.php`
- [X] T009 [P] Add helper unit tests (mixed visibility restriction + tenant resolvers + preflight decisions) in `tests/Unit/Auth/UiEnforcementTest.php`
- [X] T010 [P] Add query-count regression test for bulk preflight (no N+1 membership lookups) in `tests/Unit/Auth/UiEnforcementBulkPreflightQueryCountTest.php`
- [X] T011 Add CI-failing allowlist-driven guard for ad-hoc Filament auth patterns in `tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php`
- [X] T012 Run the new guard test with `./vendor/bin/sail artisan test tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php --compact` (test: `tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php`)

---

## Phase 3: User Story 1 — Mixed Visibility (Backup/Restore) (Priority: P1) 🎯 MVP

**Goal**: Backup/Restore actions preserve business visibility while enforcing RBAC UX (hidden/disabled + standard tooltip) via `UiEnforcement`

**Independent Test**: A non-member cannot access tenant routes (404); a member without capability sees actions disabled with the standard tooltip and cannot execute; a member with capability can execute (with confirmation for destructive actions)

### Tests for User Story 1

- [X] T013 [P] [US1] Add BackupSet RBAC UX integration tests (include `Http::preventStrayRequests()`) in `tests/Feature/Filament/BackupSetUiEnforcementTest.php`
- [X] T014 [P] [US1] Add RestoreRun RBAC UX integration tests (include `Http::preventStrayRequests()`) in `tests/Feature/Filament/RestoreRunUiEnforcementTest.php`

### Implementation for User Story 1

- [X] T015 [US1] Migrate mixed-visibility actions + bulk actions to `UiEnforcement` in `app/Filament/Resources/BackupSetResource.php`
- [X] T016 [US1] Migrate relation manager actions (incl. standardized tooltip copy via `UiTooltips`) in `app/Filament/Resources/BackupSetResource/RelationManagers/BackupItemsRelationManager.php`
- [X] T017 [US1] Migrate mixed-visibility actions + bulk actions to `UiEnforcement` in `app/Filament/Resources/RestoreRunResource.php`
- [X] T018 [US1] Replace `Gate`/`abort_*` access checks with `UiEnforcement` (tenant-scoped: non-member 404, member without cap 403) in `app/Filament/Resources/RestoreRunResource/Pages/CreateRestoreRun.php`
- [X] T019 [US1] Remove allowlist entries for migrated Backup/Restore files in `tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php`
- [X] T020 [US1] Run story tests with `./vendor/bin/sail artisan test tests/Feature/Filament/BackupSetUiEnforcementTest.php tests/Feature/Filament/RestoreRunUiEnforcementTest.php --compact` (tests: `tests/Feature/Filament/BackupSetUiEnforcementTest.php`)

---

## Phase 4: User Story 2 — Record-Scoped Tenant (TenantResource actions) (Priority: P1)

**Goal**: Tenant list row actions are enforced per-tenant record (record-scoped tenancy) with non-member deny-as-not-found (404) and standardized member disabled UX

**Independent Test**: A user sees only tenants they are a member of; direct access to another tenant record denies 404; row actions for permitted tenants are disabled/enabled per capability with standard tooltip

### Tests for User Story 2

- [X] T021 [P] [US2] Extend tenant row action tests to assert disabled + tooltip + no-exec (include `Http::preventStrayRequests()`) in `tests/Feature/Filament/TenantActionsAuthorizationTest.php`
- [X] T022 [P] [US2] Add record-scoped non-member 404 tests for tenant view/edit routes in `tests/Feature/Filament/TenantPortfolioContextSwitchTest.php`

### Implementation for User Story 2

- [X] T023 [US2] Migrate TenantResource row actions to `UiEnforcement` using `tenantFromRecord()` (remove ad-hoc `Gate`/`abort_*`) in `app/Filament/Resources/TenantResource.php`
- [X] T024 [US2] Migrate record-scoped edit-page destructive actions to `UiEnforcement` (remove ad-hoc `Gate`/`abort_*`) in `app/Filament/Resources/TenantResource/Pages/EditTenant.php`
- [X] T025 [US2] Remove allowlist entries for migrated TenantResource files in `tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php`
- [X] T026 [US2] Run story tests with `./vendor/bin/sail artisan test tests/Feature/Filament/TenantActionsAuthorizationTest.php tests/Feature/Filament/TenantPortfolioContextSwitchTest.php --compact` (tests: `tests/Feature/Filament/TenantActionsAuthorizationTest.php`)

---

## Phase 5: User Story 3 — Bulk Preflight (All-or-Nothing Authorization) (Priority: P2)

**Goal**: Bulk actions disable deterministically when selection contains any unauthorized record; no partial execution

**Independent Test**: Selecting tenants with mixed authorization disables the bulk action; selecting only authorized tenants executes; business-ineligible records may be skipped with clear feedback

### Tests for User Story 3

- [X] T027 [P] [US3] Update bulk sync tests to assert all-or-nothing authorization disable (include `Http::preventStrayRequests()`) in `tests/Feature/Filament/TenantPortfolioContextSwitchTest.php`

### Implementation for User Story 3

- [X] T028 [US3] Add authorization-only bulk preflight for `syncSelected` (disable when any selected tenant lacks `Capabilities::TENANT_SYNC`) in `app/Filament/Resources/TenantResource.php`
- [X] T029 [US3] Ensure bulk action feedback cleanly separates authorization vs eligibility (skip inactive with notification; do not partially execute unauthorized) in `app/Filament/Resources/TenantResource.php`
- [X] T030 [US3] Run story tests with `./vendor/bin/sail artisan test tests/Feature/Filament/TenantPortfolioContextSwitchTest.php --compact` (test: `tests/Feature/Filament/TenantPortfolioContextSwitchTest.php`)

---

## Phase 6: User Story 4 — Guard Allowlist Shrink + Tier 2 Migrations (Priority: P2)

**Goal**: CI fails for new ad-hoc auth patterns in `app/Filament/**`; allowlist count shrinks measurably by migrating remaining targets

**Independent Test**: Guard fails if a new forbidden pattern is introduced; allowlist removes entries as files are migrated; each migrated Tier 2 surface has a focused RBAC UX test

### Tests for User Story 4

- [X] T031 [P] [US4] Extend inventory resource RBAC UX tests (include `Http::preventStrayRequests()`) in `tests/Feature/Filament/InventoryItemResourceTest.php` and `tests/Feature/Filament/InventorySyncRunResourceTest.php`
- [X] T032 [P] [US4] Extend Entra group runs RBAC UX tests (include `Http::preventStrayRequests()`) in `tests/Feature/Filament/EntraGroupSyncRunResourceTest.php`
- [X] T033 [P] [US4] Add provider connections RBAC UX tests for mixed visibility (include `Http::preventStrayRequests()`) in `tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php`

### Implementation for User Story 4

- [X] T034 [US4] Migrate inventory resources away from ad-hoc `Gate`/`abort_*` to `UiEnforcement` in `app/Filament/Resources/InventoryItemResource.php`, `app/Filament/Resources/InventoryItemResource/Pages/ListInventoryItems.php`, and `app/Filament/Resources/InventorySyncRunResource.php`
- [X] T035 [US4] Migrate Entra group list/run start surfaces away from ad-hoc `Gate`/`abort_*` to `UiEnforcement` in `app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php` and `app/Filament/Resources/EntraGroupSyncRunResource/Pages/ListEntraGroupSyncRuns.php`
- [X] T036 [US4] Migrate provider connection mixed-visibility actions away from ad-hoc `Gate`/`abort_*` to `UiEnforcement` in `app/Filament/Resources/ProviderConnectionResource.php`, `app/Filament/Resources/ProviderConnectionResource/Pages/ListProviderConnections.php`, and `app/Filament/Resources/ProviderConnectionResource/Pages/EditProviderConnection.php`
- [X] T037 [US4] Remove allowlist entries for migrated Tier 2 files and note the allowlist count reduction in `tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php`
- [X] T038 [US4] Run story tests with `./vendor/bin/sail artisan test tests/Feature/Filament/InventoryItemResourceTest.php tests/Feature/Filament/InventorySyncRunResourceTest.php tests/Feature/Filament/EntraGroupSyncRunResourceTest.php tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php --compact` (tests: `tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php`)
- [X] T039 [US4] Run guard suite with `./vendor/bin/sail artisan test tests/Feature/Guards --compact` (folder: `tests/Feature/Guards`)

---

## Phase 7: Polish & Cross-Cutting Concerns

**Purpose**: Reduce regressions and ensure suite-wide consistency

- [X] T040 [P] Ensure all destructive actions touched in v2 include `->requiresConfirmation()` in `app/Filament/Resources/BackupSetResource.php`, `app/Filament/Resources/RestoreRunResource.php`, and `app/Filament/Resources/TenantResource/Pages/EditTenant.php`
- [X] T041 Run formatting with `./vendor/bin/sail bin pint --dirty` (script: `./vendor/bin/pint`)
- [X] T042 Run focused test suites with `./vendor/bin/sail artisan test tests/Unit/Auth tests/Feature/Filament tests/Feature/Guards tests/Feature/Rbac --compact` (folders: `tests/Feature/Filament`)

---

## Dependencies & Execution Order

### User Story Dependency Graph

```text
Phase 1 (Setup)
  ↓
Phase 2 (Foundation: UiEnforcement v2 + guard baseline)
  ↓
US1 (Backup/Restore mixed visibility) ─┬─→ US4 (Tier 2 migrations + allowlist shrink)
                                      ├─→ US2 (TenantResource record-scoped actions)
                                      └─→ US3 (Bulk preflight all-or-nothing)
```

### Parallel Opportunities

- Phase 2 tasks marked `[P]` can run in parallel (different files).
- Within US1, BackupSet and RestoreRun migrations can be done in parallel (different resources) if coordinated to avoid conflicting changes in `app/Support/Auth/UiEnforcement.php`.
- Within US4, Inventory vs EntraGroup vs ProviderConnection migrations can be parallelized (different files), but coordinate allowlist edits in `tests/Feature/Guards/NoAdHocFilamentAuthPatternsTest.php`.

---

## Parallel Example: User Story 1

```bash
Task: "Add BackupSet RBAC UX integration tests in tests/Feature/Filament/BackupSetUiEnforcementTest.php"
Task: "Add RestoreRun RBAC UX integration tests in tests/Feature/Filament/RestoreRunUiEnforcementTest.php"
Task: "Migrate BackupSet mixed-visibility actions to UiEnforcement in app/Filament/Resources/BackupSetResource.php"
Task: "Migrate RestoreRun mixed-visibility actions to UiEnforcement in app/Filament/Resources/RestoreRunResource.php"
```

---

## Parallel Example: User Story 2

```bash
Task: "Extend tenant row action tests to assert disabled + tooltip + no-exec in tests/Feature/Filament/TenantActionsAuthorizationTest.php"
Task: "Add record-scoped non-member 404 tests for tenant view/edit routes in tests/Feature/Filament/TenantPortfolioContextSwitchTest.php"
Task: "Migrate TenantResource row actions to UiEnforcement using tenantFromRecord() in app/Filament/Resources/TenantResource.php"
Task: "Migrate record-scoped edit-page destructive actions to UiEnforcement in app/Filament/Resources/TenantResource/Pages/EditTenant.php"
```

---

## Parallel Example: User Story 3

```bash
Task: "Update bulk sync tests to assert all-or-nothing authorization disable in tests/Feature/Filament/TenantPortfolioContextSwitchTest.php"
Task: "Add authorization-only bulk preflight for syncSelected in app/Filament/Resources/TenantResource.php"
```

---

## Parallel Example: User Story 4

```bash
Task: "Extend inventory resource RBAC UX tests in tests/Feature/Filament/InventoryItemResourceTest.php"
Task: "Extend Entra group runs RBAC UX tests in tests/Feature/Filament/EntraGroupSyncRunResourceTest.php"
Task: "Add provider connections RBAC UX tests for mixed visibility in tests/Feature/Filament/ProviderConnectionsUiEnforcementTest.php"
Task: "Migrate Entra group run list surfaces to UiEnforcement in app/Filament/Resources/EntraGroupSyncRunResource.php"
Task: "Migrate provider connection pages/actions to UiEnforcement in app/Filament/Resources/ProviderConnectionResource/Pages/ListProviderConnections.php"
```

---

## Implementation Strategy

### MVP First (User Story 1)

1. Complete Phase 1 + Phase 2
2. Complete US1 (BackupSet + RestoreRun mixed visibility enforcement)
3. Validate with `tests/Feature/Filament/BackupSetUiEnforcementTest.php` and `tests/Feature/Filament/RestoreRunUiEnforcementTest.php`

### Incremental Delivery

1. US1 → migrate highest-risk backup/restore surfaces + tests + allowlist reduction
2. US2 → record-scoped tenant actions enforced per row + 404 non-member on direct access
3. US3 → bulk preflight all-or-nothing authorization
4. US4 → Tier 2 migrations + measurable allowlist shrink + guard stability
