# Research — Provider Access Hardening v1 (Intune Write Gate) ## Repository Reality Check (existing implementation surfaces) ### Write start surfaces - Restore execution start (wizard submit / create path): `App\Filament\Resources\RestoreRunResource::createRestoreRun()` - Creates a queued `RestoreRun` and a corresponding `OperationRun` of type `restore.execute`. - Dispatches `App\Jobs\ExecuteRestoreRunJob` with the `OperationRun` instance. - Restore rerun path (action path inside `RestoreRunResource`): also enqueues `restore.execute` and dispatches `ExecuteRestoreRunJob`. ### Job execution layer (defense-in-depth insertion points) - `App\Jobs\ExecuteRestoreRunJob::handle()` - Calls `RestoreService::executeForRun(...)` (this is the Graph-mutation path). - `App\Jobs\RestoreAssignmentsJob::handle()` - Calls `AssignmentRestoreService::restore(...)` (Graph-mutation path for assignments). ### Tenant view RBAC UX surfaces - Tenant view page: `App\Filament\Resources\TenantResource::infolist()` currently renders a full "RBAC" section with many raw fields. - Tenant view header actions: `App\Filament\Resources\TenantResource\Pages\ViewTenant::getHeaderActions()` includes `TenantResource::rbacAction()`. - RBAC setup surface already exists: `App\Filament\Resources\TenantResource::rbacAction()` creates the "Setup Intune RBAC" action (no new wizard page required). ### Existing gating and observability primitives - Operation dedupe + provider connection blocking: `App\Services\Providers\ProviderOperationStartGate` (existing pattern for start surfaces). - Long-running work visibility: `OperationRun` is the canonical monitoring primitive. - Audit logging: `App\Models\AuditLog` exists and `Tenant` already relates to it. ## Decisions (resolved clarifications) ### Gate evaluation during health check - Decision: Gate evaluates persisted Tenant state only; an in-progress health check has no special effect. - Rationale: Keeps the gate DB-only and deterministic; avoids introducing locks/sentinels. - Alternatives considered: - Block all writes while health check is running (safer but adds operational friction and requires tracking “running” state). ### "Setup Intune RBAC" CTA destination - Decision: CTA deep-links to the existing Tenant view RBAC section / surfaces (no new wizard page in this feature). - Rationale: Minimizes scope and leverages `TenantResource::rbacAction()` which already exists. - Alternatives considered: - Build a dedicated setup wizard page for RBAC (adds navigation, testing, and more UX requirements). ### Audit logging for blocked attempts - Decision: Use existing `AuditLog` model for UI-level blocked write attempts (P3), in addition to OperationRun failures. - Rationale: Meets compliance intent without introducing new schema. - Alternatives considered: - Create a new audit log table (unnecessary; model already exists). ### Config toggle behavior - Decision: `tenantpilot.hardening.intune_write_gate.enabled=false` causes writes to proceed, but logs a warning per evaluation that the gate is bypassed. - Rationale: Rollback safety without silent loss of protection. - Alternatives considered: - Silent bypass (bad observability). - Startup-only warning (can be missed; per-evaluation warning is explicit). ## Key constraints reaffirmed - No synchronous Graph calls in the gate. - Start surface must block before job enqueue. - Job-level must block before any Graph mutation call. - Reason codes are stable and sanitized.