#+#+#+#+--------------------------------------------------------------------------
# Spec 065 Enforcement Hitlist — role-ish helpers sweep
#+#+#+#+--------------------------------------------------------------------------

Generated: 2026-01-28 (updated)

----------------------------------------------------------------------------
Step-2 (T024) — Filament mutation and operation entry points
----------------------------------------------------------------------------

Goal: Enumerate every Filament action/page hook that (a) mutates tenant-scoped state or (b) dispatches jobs / operation runs.
This is the authoritative checklist for the enforcement sweep in T025–T033.

Legend:
- kind: mutate | dispatch | destructive | secret
- capability (target):
	- Use existing App\Support\Auth\Capabilities constants where available.
	- Mark missing ones as NEW for addition/mapping in T025/T026.

Tenant (tenant-plane)

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M001 | app/Filament/Resources/TenantResource.php | syncTenant | dispatch | visible() checks Gate::allows(Capabilities::TENANT_SYNC, record) | Capabilities::TENANT_SYNC | Uses OperationRunService to dispatch SyncPoliciesJob. |
| M002 | app/Filament/Resources/TenantResource.php | syncSelected (bulk) | dispatch | visible()+authorize() checks rolesWithCapability(Capabilities::TENANT_SYNC) | Capabilities::TENANT_SYNC | Dispatches BulkTenantSyncJob. |
| M003 | app/Filament/Resources/TenantResource.php | makeCurrent | mutate | none obvious | NEW | Sets current tenant context; should be capability-gated. |
| M004 | app/Filament/Resources/TenantResource.php | archive / deactivate | destructive | none obvious | Capabilities::TENANT_DELETE (or NEW) | Soft-deletes tenant; confirmation already present. |
| M005 | app/Filament/Resources/TenantResource.php | forceDelete | destructive | none obvious | Capabilities::TENANT_DELETE | Permanent delete; confirmation already present. |
| M006 | app/Filament/Resources/TenantResource.php | verify | mutate/dispatch | none obvious | Capabilities::TENANT_MANAGE | May update status fields; should be capability-gated. |
| M007 | app/Filament/Resources/TenantResource.php | setup_rbac | mutate/dispatch | none obvious | Capabilities::TENANT_MANAGE | Intune RBAC setup; should be capability-gated + confirmed (confirmation present). |

Tenant membership

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M010 | app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php | add member | mutate | relation manager auth + server-side manager guards | Capabilities::TENANT_MEMBERSHIP_MANAGE | Uses TenantMembershipManager (audited). |
| M011 | app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php | change role | mutate | relation manager auth + last-owner protection | Capabilities::TENANT_MEMBERSHIP_MANAGE | Privilege change; requires confirmation. |
| M012 | app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php | remove member | destructive | relation manager auth + last-owner protection | Capabilities::TENANT_MEMBERSHIP_MANAGE | Requires confirmation; blocked attempts are audited. |

Providers (provider-plane)

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M020 | app/Filament/Resources/ProviderConnectionResource.php | check_connection | dispatch | Gate::allows(Capabilities::PROVIDER_RUN_OPERATIONS, record) | Capabilities::PROVIDER_RUN_OPERATIONS | Dispatches ProviderConnectionHealthCheckJob via OperationRunService. |
| M021 | app/Filament/Resources/ProviderConnectionResource.php | inventory_sync | dispatch | Gate::allows(Capabilities::PROVIDER_RUN_OPERATIONS, record) | Capabilities::PROVIDER_RUN_OPERATIONS | Dispatches ProviderInventorySyncJob. |
| M022 | app/Filament/Resources/ProviderConnectionResource.php | compliance_snapshot | dispatch | Gate::allows(Capabilities::PROVIDER_RUN_OPERATIONS, record) | Capabilities::PROVIDER_RUN_OPERATIONS | Dispatches ProviderComplianceSnapshotJob. |
| M023 | app/Filament/Resources/ProviderConnectionResource.php | set_default | mutate | Gate::allows(Capabilities::PROVIDER_MANAGE, record) | Capabilities::PROVIDER_MANAGE | Changes default provider; audited. |
| M024 | app/Filament/Resources/ProviderConnectionResource.php | update_credentials | secret | Gate::allows(Capabilities::PROVIDER_MANAGE, record) | Capabilities::PROVIDER_MANAGE | Credential/secret handling; audited. |
| M025 | app/Filament/Resources/ProviderConnectionResource.php | enable / disable | mutate | Gate::allows(Capabilities::PROVIDER_MANAGE, record) | Capabilities::PROVIDER_MANAGE | Connection state change; audited. |

Backup schedules

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M030 | app/Filament/Resources/BackupScheduleResource.php | create/edit/delete | mutate/destructive | Resource can* + policy guard | Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE | Already mapped in Step-1. |
| M031 | app/Filament/Resources/BackupScheduleResource.php | run now / retry (row + bulk) | dispatch | visible()+abort_unless guards | Capabilities::TENANT_BACKUP_SCHEDULES_RUN | Already mapped in Step-1. |

Backup sets

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M040 | app/Filament/Resources/BackupSetResource.php | restore | dispatch | none obvious | NEW | Starts restore workflow from a backup set; uses OperationRunService. |
| M041 | app/Filament/Resources/BackupSetResource.php | archive / delete (bulk) | destructive | none obvious | NEW (or Capabilities::TENANT_DELETE) | Bulk job: BulkBackupSetDeleteJob. |
| M042 | app/Filament/Resources/BackupSetResource.php | restore (bulk) | dispatch | none obvious | NEW | BulkBackupSetRestoreJob. |
| M043 | app/Filament/Resources/BackupSetResource.php | force delete (row + bulk) | destructive | none obvious | NEW | Bulk job: BulkBackupSetForceDeleteJob. |

Restore runs

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M050 | app/Filament/Resources/RestoreRunResource/Pages/CreateRestoreRun.php | create/queue restore run | dispatch | tenant match + non-dry-run confirmation | NEW | Dispatches ExecuteRestoreRunJob; emits restore.queued audit. |
| M051 | app/Filament/Resources/RestoreRunResource.php | rerun | dispatch | none obvious | NEW | Starts restore rerun. |
| M052 | app/Filament/Resources/RestoreRunResource.php | archive / restore / forceDelete | destructive | none obvious | NEW (or Capabilities::TENANT_DELETE) | Row-level destructive actions; confirmations exist. |
| M053 | app/Filament/Resources/RestoreRunResource.php | bulk delete / restore / force delete | destructive | none obvious | NEW | Bulk jobs: BulkRestoreRunDeleteJob, BulkRestoreRunRestoreJob, BulkRestoreRunForceDeleteJob. |

Drift

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M060 | app/Filament/Pages/DriftLanding.php | auto enqueue findings generation (mount) | dispatch | Gate::allows(Capabilities::TENANT_SYNC, tenant) | Capabilities::TENANT_SYNC | Dispatches GenerateDriftFindingsJob when no findings exist. |

Findings

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M070 | app/Filament/Resources/FindingResource.php | acknowledge (row + bulk) | mutate | policy + tenant scoping | NEW (or policy-only) | Local mutation; decide in T025 whether to require a dedicated capability. |

Policies

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M080 | app/Filament/Resources/PolicyResource.php | ignore / unignore (row + bulk) | mutate | mixed (some Gate checks) | NEW | Local policy lifecycle; bulk jobs include BulkPolicyDeleteJob / BulkPolicyUnignoreJob (verify naming). |
| M081 | app/Filament/Resources/PolicyResource.php | sync (row + bulk) | dispatch | requires Capabilities::TENANT_SYNC in places | Capabilities::TENANT_SYNC (or NEW) | Dispatches SyncPoliciesJob; ensure all entry points have server-side authorization. |
| M082 | app/Filament/Resources/PolicyResource.php | export (row + bulk) | dispatch | none obvious | NEW | BulkPolicyExportJob; capability needed to prevent data exfil. |
| M083 | app/Filament/Resources/PolicyResource/RelationManagers/VersionsRelationManager.php | restore_to_intune | dispatch | none obvious | NEW | Calls RestoreService::executeFromPolicyVersion. |

Entra groups

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M090 | app/Filament/Resources/EntraGroupSyncRunResource/Pages/ListEntraGroupSyncRuns.php | sync_groups (header) | dispatch | abort(403) when role cannot sync | Capabilities::TENANT_SYNC | Execution guard already present. |
| M091 | app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php | sync_groups (header) | dispatch | abort(403) when role cannot sync | Capabilities::TENANT_SYNC | Execution guard already present. |

Inventory

| ID  | Location | Action | Kind | Current guard | Capability (target) | Notes |
|-----|----------|--------|------|---------------|---------------------|-------|
| M100 | app/Filament/Resources/InventorySyncRunResource.php | view runs | read | relies on tenant scoping | Capabilities::TENANT_VIEW (or NEW) | Decide whether listing historical runs needs explicit capability in T025. |

Scope: discovery only (phase 1). This file enumerates every remaining occurrence matched by the stop-regex:

`TenantRole::|->tenantRole\(|currentTenantRole\(|canManage|canRun|canSync`

Notes:
- `rg` (ripgrep) is not available in this environment, so discovery uses GNU/BSD `grep`.
- The “allowed” exclusions for sweep progress reporting are:
	- `app/Services/Auth/RoleCapabilityMap.php`
	- `app/Services/Auth/CapabilityResolver.php`
	- `app/Support/Auth/Capabilities.php`
	- `app/Support/TenantRole.php`

## Discovery commands + counts

### Total matches (all of app/)

```bash
grep -RInE --include='*.php' 'TenantRole::|->tenantRole\(|currentTenantRole\(|canManage|canRun|canSync' app | wc -l
```

Result: **31**

### Remaining matches (excluding mapping/registry/TenantRole enum definition)

```bash
grep -RInE --include='*.php' 'TenantRole::|->tenantRole\(|currentTenantRole\(|canManage|canRun|canSync' app \
	| grep -vE '^app/Services/Auth/RoleCapabilityMap\.php:|^app/Services/Auth/CapabilityResolver\.php:|^app/Support/Auth/Capabilities\.php:|^app/Support/TenantRole\.php:' \
	| wc -l
```

Result: **21**

### Top files by remaining match count

```bash
grep -RInE --include='*.php' 'TenantRole::|->tenantRole\(|currentTenantRole\(|canManage|canRun|canSync' app \
	| grep -vE '^app/Services/Auth/RoleCapabilityMap\.php:|^app/Services/Auth/CapabilityResolver\.php:|^app/Support/Auth/Capabilities\.php:|^app/Support/TenantRole\.php:' \
	| cut -d: -f1 | sort | uniq -c | sort -nr | head -n 20
```

Result:

```text
	10 app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php
	 6 app/Services/Auth/TenantMembershipManager.php
	 2 app/Models/User.php
	 2 app/Filament/Pages/Tenancy/RegisterTenant.php
	 1 app/Filament/Resources/TenantResource/Pages/CreateTenant.php
```

## Full remaining match list (excluding mapping/registry/TenantRole enum definition)

```text
app/Models/User.php:116:        return TenantRole::tryFrom($role);
app/Models/User.php:119:    public function canSyncTenant(Tenant $tenant): bool
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:66:                                TenantRole::Owner->value => 'Owner',
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:67:                                TenantRole::Manager->value => 'Manager',
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:68:                                TenantRole::Operator->value => 'Operator',
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:69:                                TenantRole::Readonly->value => 'Readonly',
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:100:                                role: TenantRole::from((string) $data['role']),
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:135:                                TenantRole::Owner->value => 'Owner',
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:136:                                TenantRole::Manager->value => 'Manager',
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:137:                                TenantRole::Operator->value => 'Operator',
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:138:                                TenantRole::Readonly->value => 'Readonly',
app/Filament/Resources/TenantResource/RelationManagers/TenantMembershipsRelationManager.php:162:                                newRole: TenantRole::from((string) $data['role']),
app/Filament/Resources/TenantResource/Pages/CreateTenant.php:23:            $this->record->getKey() => ['role' => TenantRole::Owner->value],
app/Filament/Pages/Tenancy/RegisterTenant.php:79:                    'role' => TenantRole::Owner->value,
app/Filament/Pages/Tenancy/RegisterTenant.php:91:                        'role' => TenantRole::Owner->value,
app/Services/Auth/TenantMembershipManager.php:178:            role: TenantRole::Owner,
app/Services/Auth/TenantMembershipManager.php:203:        if ($membership->role !== TenantRole::Owner->value) {
app/Services/Auth/TenantMembershipManager.php:209:            ->where('role', TenantRole::Owner->value)
app/Services/Auth/TenantMembershipManager.php:219:        if ($membership->role !== TenantRole::Owner->value) {
app/Services/Auth/TenantMembershipManager.php:223:        if ($newRole === TenantRole::Owner) {
app/Services/Auth/TenantMembershipManager.php:229:            ->where('role', TenantRole::Owner->value)
```
| H003 | app/Filament/Resources/EntraGroupSyncRunResource/Pages/ListEntraGroupSyncRuns.php:62 | `if (! ($role?->canSync() ?? false)) abort(403);` | Header action execution: `sync_groups` | `Capabilities::TENANT_SYNC` | Execution guard. |
| H004 | app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php:50 | `$role?->canSync() ?? false` | Header action visibility: `sync_groups` | `Capabilities::TENANT_SYNC` | Visible guard only. |
| H005 | app/Filament/Resources/EntraGroupResource/Pages/ListEntraGroups.php:71 | `if (! ($role?->canSync() ?? false)) abort(403);` | Header action execution: `sync_groups` | `Capabilities::TENANT_SYNC` | Execution guard. |
| H006 | app/Filament/Resources/BackupScheduleResource.php:86 | `static::currentTenantRole()?->canManageBackupSchedules() ?? false` | Resource ability: `canCreate()` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H007 | app/Filament/Resources/BackupScheduleResource.php:91 | `static::currentTenantRole()?->canManageBackupSchedules() ?? false` | Resource ability: `canEdit()` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H008 | app/Filament/Resources/BackupScheduleResource.php:96 | `static::currentTenantRole()?->canManageBackupSchedules() ?? false` | Resource ability: `canDelete()` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H009 | app/Filament/Resources/BackupScheduleResource.php:101 | `static::currentTenantRole()?->canManageBackupSchedules() ?? false` | Resource ability: `canDeleteAny()` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H010 | app/Filament/Resources/BackupScheduleResource.php:303 | `static::currentTenantRole()?->canRunBackupSchedules() ?? false` | Table row action visibility: `runNow` | `Capabilities::TENANT_BACKUP_SCHEDULES_RUN` | New capability added in Option-1 patch. |
| H011 | app/Filament/Resources/BackupScheduleResource.php:305 | `abort_unless(static::currentTenantRole()?->canRunBackupSchedules() ?? false, 403);` | Table row action execution: `runNow` | `Capabilities::TENANT_BACKUP_SCHEDULES_RUN` | New capability added in Option-1 patch. |
| H012 | app/Filament/Resources/BackupScheduleResource.php:427 | `static::currentTenantRole()?->canRunBackupSchedules() ?? false` | Table row action visibility: `retry` | `Capabilities::TENANT_BACKUP_SCHEDULES_RUN` | New capability added in Option-1 patch. |
| H013 | app/Filament/Resources/BackupScheduleResource.php:429 | `abort_unless(static::currentTenantRole()?->canRunBackupSchedules() ?? false, 403);` | Table row action execution: `retry` | `Capabilities::TENANT_BACKUP_SCHEDULES_RUN` | New capability added in Option-1 patch. |
| H014 | app/Filament/Resources/BackupScheduleResource.php:548 | `static::currentTenantRole()?->canManageBackupSchedules() ?? false` | Table row action visibility: `EditAction` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H015 | app/Filament/Resources/BackupScheduleResource.php:550 | `static::currentTenantRole()?->canManageBackupSchedules() ?? false` | Table row action visibility: `DeleteAction` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H016 | app/Filament/Resources/BackupScheduleResource.php:559 | `static::currentTenantRole()?->canRunBackupSchedules() ?? false` | Bulk action visibility: `bulk_run_now` | `Capabilities::TENANT_BACKUP_SCHEDULES_RUN` | New capability added in Option-1 patch. |
| H017 | app/Filament/Resources/BackupScheduleResource.php:561 | `abort_unless(static::currentTenantRole()?->canRunBackupSchedules() ?? false, 403);` | Bulk action execution: `bulk_run_now` | `Capabilities::TENANT_BACKUP_SCHEDULES_RUN` | New capability added in Option-1 patch. |
| H018 | app/Filament/Resources/BackupScheduleResource.php:688 | `static::currentTenantRole()?->canRunBackupSchedules() ?? false` | Bulk action visibility: `bulk_retry` | `Capabilities::TENANT_BACKUP_SCHEDULES_RUN` | New capability added in Option-1 patch. |
| H019 | app/Filament/Resources/BackupScheduleResource.php:690 | `abort_unless(static::currentTenantRole()?->canRunBackupSchedules() ?? false, 403);` | Bulk action execution: `bulk_retry` | `Capabilities::TENANT_BACKUP_SCHEDULES_RUN` | New capability added in Option-1 patch. |
| H020 | app/Filament/Resources/BackupScheduleResource.php:814 | `static::currentTenantRole()?->canManageBackupSchedules() ?? false` | Bulk action visibility: `DeleteBulkAction` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H021 | app/Policies/BackupSchedulePolicy.php:34 | `$this->resolveRole($user)?->canManageBackupSchedules() ?? false` | Policy: `create()` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H022 | app/Policies/BackupSchedulePolicy.php:39 | `$this->resolveRole($user)?->canManageBackupSchedules() ?? false` | Policy: `update()` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |
| H023 | app/Policies/BackupSchedulePolicy.php:44 | `$this->resolveRole($user)?->canManageBackupSchedules() ?? false` | Policy: `delete()` | `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE` | New capability added in Option-1 patch. |

## Step-1 conclusion (guardrails)

- `canSync()` has a clear mapping: `Capabilities::TENANT_SYNC`.
- `canManageBackupSchedules()` now maps to `Capabilities::TENANT_BACKUP_SCHEDULES_MANAGE`.
- `canRunBackupSchedules()` now maps to `Capabilities::TENANT_BACKUP_SCHEDULES_RUN`.
- No unmapped `TenantRole::can*()` usages remain in this hitlist.
