213 lines
20 KiB
Markdown
213 lines
20 KiB
Markdown
#+#+#+#+--------------------------------------------------------------------------
|
||
# 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.
|