# 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.
