# Implementation Plan: Intune RBAC Inventory & Backup v1

**Branch**: `127-rbac-inventory-backup` | **Date**: 2026-03-09 | **Spec**: `/specs/127-rbac-inventory-backup/spec.md`
**Input**: Feature specification from `/specs/127-rbac-inventory-backup/spec.md`

**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.

## Summary

Add Intune Role Definitions and Intune Role Assignments as first-class foundation types in the existing tenant inventory and backup/version architecture.

The implementation reuses the current config-driven foundation flow in `config/tenantpilot.php`, inventory sync persistence through `App\Services\Inventory\InventorySyncService`, foundation backup capture through `App\Services\Intune\FoundationSnapshotService` + `App\Services\Intune\BackupService`, version history capture through `App\Services\Intune\VersionService`, and normalized rendering through `App\Services\Intune\PolicyNormalizer` with new type-specific normalizers. Existing backup set detail and policy version history/detail surfaces will render the new RBAC history without adding a dedicated RBAC resource. To avoid regressions with existing RBAC health and onboarding paths, the plan uses new inventory-grade Graph contract keys for Intune RBAC objects while preserving the existing `directoryRoleDefinitions` and `rbacRoleAssignment` contract semantics already used elsewhere.

## Technical Context

**Language/Version**: PHP 8.4 (Laravel 12)  
**Primary Dependencies**: Filament v5, Livewire v4, Laravel Sail, Microsoft Graph provider stack  
**Storage**: PostgreSQL for tenant-owned inventory, backup items, versions, verification outcomes, and operation runs  
**Testing**: Pest v4 on PHPUnit 12  
**Target Platform**: Web app (tenant/admin Filament panel and tenant-scoped operational flows)
**Project Type**: Laravel monolith with config-driven inventory and backup services  
**Performance Goals**: preserve current inventory-sync and backup runtime characteristics; no additional render-time Graph calls; RBAC normalization remains deterministic and diff-safe for audit use  
**Constraints**: Graph access only via `GraphClientInterface` + contract registry; no write or restore-execution path; strict workspace and tenant isolation; preview-only restore semantics; graceful warning path for missing `DeviceManagementRBAC.Read.All`; metadata-only inventory storage with full payloads only in immutable snapshots/backups  
**Scale/Scope**: two new foundation types spanning config, Graph contracts, inventory sync, backup items, version history entries, normalized snapshot display, coverage, verification messaging, and focused regression tests

## Constitution Check

*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

- Inventory-first: PASS. RBAC inventory remains the “last observed” layer via `InventoryItem`; immutable payload history remains explicit in backup/version capture.
- Read/write separation: PASS. This feature is read-only; both RBAC types remain `preview-only` and no write path is introduced.
- Graph contract path: PASS. All RBAC reads will use `GraphClientInterface` and new config-backed contract entries in `config/graph_contracts.php`.
- Deterministic capabilities: PASS. Restore/risk/support metadata stays config-driven via `config('tenantpilot.foundation_types')` and `InventoryPolicyTypeMeta`.
- RBAC-UX plane separation: PASS. This stays in the Tenant/Admin plane and reuses existing tenant-scoped capability checks; no `/system` exposure is added.
- Workspace isolation: PASS. Inventory, backup items, versions, and verification results remain workspace-bound through existing tenant-owned models.
- RBAC-UX destructive confirmation: PASS by exemption. No new destructive action is introduced.
- RBAC-UX global search safety: PASS by non-expansion. No dedicated searchable RBAC resource is added.
- Tenant isolation: PASS. Existing tenant-scoped inventory, backup, version, and verification storage/queries are reused.
- Run observability: PASS. Existing inventory sync and backup/version flows already create `OperationRun` records and remain enqueue-only at start surfaces.
- Ops-UX 3-surface feedback: PASS. The feature reuses existing run types and must not add ad-hoc notifications.
- Ops-UX lifecycle: PASS. No direct `OperationRun` transition logic is added.
- Ops-UX summary counts: PASS. The feature adds coverage and counts through existing inventory and backup flows without changing the summary contract.
- Ops-UX guards: PASS. Existing regression guards remain in force; focused tests will confirm the reused flows still comply after RBAC types are added.
- Ops-UX system runs: PASS. Scheduled and initiator-null behavior is unchanged.
- Automation: PASS. Existing queue, dedupe, and retry behavior for inventory/backup flows is reused.
- Data minimization: PASS. `InventoryItem.meta_jsonb` stays sanitized and payload-heavy RBAC data is stored only in backup/version snapshots.
- Badge semantics (BADGE-001): PASS. Any new support/risk/restore badges must reuse existing badge domains or extend them centrally with tests.
- Filament UI Action Surface Contract / UX-001: PASS by extension-only scope. Existing coverage, backup set detail, and policy version history/detail surfaces are extended with new rows and labels only; no new Filament resource/page is introduced, and the spec references `docs/product/standards/list-surface-review-checklist.md` for the touched list surfaces.

**Result (pre-Phase 0)**: PASS.

- The main design constraint is compatibility: existing `directoryRoleDefinitions` and `rbacRoleAssignment` contracts already serve RBAC health/onboarding flows, so inventory-grade RBAC capture must use separate contract keys instead of silently repurposing those existing keys.
- The feature reuses existing tenant inventory and backup operations; no additional `OperationRun` types, UI workflows, or write gates are needed.

## Project Structure

### Documentation (this feature)

```text
specs/127-rbac-inventory-backup/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
└── tasks.md
```

### Source Code (repository root)

```text
app/
├── Filament/
│   ├── Pages/
│   ├── Resources/
│   └── Widgets/
├── Models/
├── Providers/
├── Services/
│   ├── Graph/
│   ├── Intune/
│   ├── Inventory/
│   └── Providers/
├── Support/
│   ├── Badges/
│   ├── Inventory/
│   ├── Providers/
│   └── Verification/
└── Jobs/

config/
tests/
specs/
```

Expected additions or edits during implementation:

```text
config/tenantpilot.php
config/graph_contracts.php
config/intune_permissions.php
app/Services/Intune/IntuneRoleDefinitionNormalizer.php
app/Services/Intune/IntuneRoleAssignmentNormalizer.php
app/Services/Intune/FoundationSnapshotService.php
app/Services/Intune/VersionService.php
app/Services/Inventory/InventorySyncService.php
app/Support/Inventory/InventoryPolicyTypeMeta.php
app/Support/Verification/TenantPermissionCheckClusters.php
app/Providers/AppServiceProvider.php
app/Filament/Resources/PolicyVersionResource.php
tests/Feature/Inventory/*
tests/Feature/Filament/*
tests/Feature/FoundationBackupTest.php
tests/Feature/BackupServiceVersionReuseTest.php
tests/Feature/Notifications/OperationRunNotificationTest.php
tests/Feature/OpsUx/OperationRunSummaryCountsIncrementTest.php
tests/Unit/*GraphContract*Test.php
tests/Unit/FoundationSnapshotServiceTest.php
tests/Unit/Badges/*
```

**Structure Decision**: Laravel monolith. The feature extends existing config, service, and Filament presentation layers without introducing new top-level directories or a dedicated RBAC resource.

## Phase 0 — Outline & Research

Deliverable: `research.md` with implementation decisions resolved.

Key questions answered in research:

- How to extend foundation registration and coverage classification while keeping deterministic metadata resolution.
- How to add full-fidelity RBAC Graph contracts without breaking current RBAC onboarding and health-check helpers.
- Which storage path should carry immutable RBAC payloads in v1 and how that differs from the sanitized `InventoryItem.meta_jsonb` record.
- Which existing `VersionService` capture and `PolicyVersionResource` surfaces should carry foundation-backed RBAC history alongside backup set detail.
- Which existing verification and provider-reason patterns should handle missing `DeviceManagementRBAC.Read.All` as a soft warning rather than an opaque failure.
- Which existing tests and patterns for foundations, inventory coverage, preview-only restore, and Graph contract sanitization should be reused.

## Phase 1 — Design & Contracts

Deliverables: `data-model.md`, `contracts/*`, `quickstart.md`.

- Data model defines the tenant-owned inventory, backup, version, and verification artifacts affected by `intuneRoleDefinition` and `intuneRoleAssignment`.
- Contracts define the conceptual tenant inventory, coverage, verification, and backup/view behaviors extended by the new RBAC foundation types.
- Quickstart defines the smallest local verification loop using Sail, Pint, and focused Pest tests.

## Phase 2 — Planning

Implementation sequence (high-level):

1. Extend `config/tenantpilot.php` foundation metadata with `intuneRoleDefinition` and `intuneRoleAssignment`, category `RBAC`, and `restore: preview-only`.
2. Add inventory-grade RBAC Graph contracts in `config/graph_contracts.php`, preserving existing health/onboarding contract keys.
3. Wire the new contract keys into foundation inventory and snapshot capture paths, including any Graph contract registry helpers needed for full RBAC reads.
4. Add `IntuneRoleDefinitionNormalizer` and `IntuneRoleAssignmentNormalizer`, then register them in `AppServiceProvider`.
5. Extend coverage and presentation metadata so the RBAC category and both foundation types appear consistently in inventory coverage, backup set detail, and policy version history/detail surfaces.
6. Wire RBAC foundation snapshots into the existing `VersionService` capture and reuse paths so backup capture and version history stay aligned.
7. Add graceful permission-warning behavior for missing `DeviceManagementRBAC.Read.All` in verification/provider messaging and capture failure metadata.
8. Add focused Pest coverage for config registration, Graph contract sanitization, inventory sync, foundation backup capture, version capture/detail, normalized output, coverage visibility, preview-only restore behavior, permission-warning handling, and reused `OperationRun` notification and summary-count invariants.

**Constitution re-check (post-design)**: PASS.

- Inventory remains the observed-state layer; payload-heavy RBAC data remains in immutable backup/version artifacts.
- No write or restore-execution path is added.
- All Graph access remains contract-driven.
- Tenant/workspace isolation and 404/403 rules remain unchanged.
- Existing `OperationRun` flows are reused without adding non-canonical feedback surfaces.

## Complexity Tracking

> **Fill ONLY if Constitution Check has violations that must be justified**

| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| None | N/A | N/A |
