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