200 lines
7.6 KiB
Markdown
200 lines
7.6 KiB
Markdown
# Data Model — Intune RBAC Inventory & Backup v1 (127)
|
|
|
|
## Entities
|
|
|
|
### Foundation Type Metadata
|
|
Config-defined support metadata for RBAC foundations.
|
|
|
|
- Source: `config/tenantpilot.php`
|
|
- New keys:
|
|
- `intuneRoleDefinition`
|
|
- `intuneRoleAssignment`
|
|
- Required attributes:
|
|
- `type`
|
|
- `label`
|
|
- `category = RBAC`
|
|
- `platform = all`
|
|
- `endpoint`
|
|
- `backup`
|
|
- `restore = preview-only`
|
|
- `risk`
|
|
|
|
### Graph Contract Definition
|
|
Config-defined Graph fetch contract for inventory-grade RBAC capture.
|
|
|
|
- Source: `config/graph_contracts.php`
|
|
- New contract keys:
|
|
- `intuneRoleDefinition`
|
|
- `intuneRoleAssignment`
|
|
- Required fields:
|
|
- `resource`
|
|
- `allowed_select`
|
|
- `allowed_expand`
|
|
- `type_family` when available
|
|
- optional `hydration` or follow-up fetch hints if full assignment fidelity requires them
|
|
- Compatibility rule:
|
|
- Existing `directoryRoleDefinitions` and `rbacRoleAssignment` keys remain unchanged for current health/onboarding flows.
|
|
|
|
### InventoryItem (tenant-owned observed state)
|
|
Represents the latest observed RBAC inventory row per tenant and external object.
|
|
|
|
- Existing model/table: `InventoryItem`
|
|
- Ownership:
|
|
- `workspace_id` NOT NULL
|
|
- `tenant_id` NOT NULL
|
|
- Identity:
|
|
- unique by `tenant_id + policy_type + external_id`
|
|
- Relevant fields for RBAC:
|
|
- `policy_type` = `intuneRoleDefinition` or `intuneRoleAssignment`
|
|
- `external_id`
|
|
- `display_name`
|
|
- `category = RBAC`
|
|
- `platform = all`
|
|
- `meta_jsonb` sanitized, metadata-only
|
|
- `last_seen_at`
|
|
- `last_seen_operation_run_id`
|
|
- `meta_jsonb` for Role Definitions should include only safe observed metadata such as:
|
|
- OData type
|
|
- built-in versus custom state
|
|
- summary counts or identifiers needed for inventory surfaces
|
|
- `meta_jsonb` for Role Assignments should include only safe observed metadata such as:
|
|
- linked role definition identifier or display name if available
|
|
- assignment target counts or scope counts
|
|
- warnings and sanitized support-state metadata
|
|
|
|
### Inventory Coverage Payload
|
|
Canonical coverage status written into `OperationRun.context.inventory.coverage.foundation_types`.
|
|
|
|
- Existing source: `App\Support\Inventory\InventoryCoverage`
|
|
- New keys:
|
|
- `foundation_types.intuneRoleDefinition`
|
|
- `foundation_types.intuneRoleAssignment`
|
|
- Per-type fields:
|
|
- `status` in `succeeded | failed | skipped`
|
|
- optional `item_count`
|
|
- optional `error_code`
|
|
|
|
### BackupItem (tenant-owned immutable RBAC payload snapshot)
|
|
Represents a captured RBAC foundation snapshot inside a backup set.
|
|
|
|
- Existing model/table: `BackupItem`
|
|
- Ownership:
|
|
- `tenant_id` NOT NULL
|
|
- workspace derived via tenant relationship
|
|
- RBAC foundation shape:
|
|
- `policy_id` = synthetic tenant-scoped policy anchor for `intuneRoleDefinition` and `intuneRoleAssignment`
|
|
- `policy_version_id` = immutable snapshot row created or reused for the captured RBAC payload
|
|
- `policy_type` = `intuneRoleDefinition` or `intuneRoleAssignment`
|
|
- `policy_identifier` = source Graph object id
|
|
- `payload` = full immutable RBAC payload
|
|
- `metadata.displayName`
|
|
- `metadata.kind`
|
|
- `metadata.graph.resource`
|
|
- additional metadata warnings or capture details
|
|
|
|
### Policy / PolicyVersion linkage for RBAC foundations
|
|
RBAC foundations reuse the existing policy-version review surfaces by creating synthetic policy anchors.
|
|
|
|
- Existing models/tables: `Policy`, `PolicyVersion`
|
|
- RBAC anchor shape:
|
|
- `Policy.external_id` = RBAC source Graph object id
|
|
- `Policy.policy_type` = `intuneRoleDefinition` or `intuneRoleAssignment`
|
|
- `Policy.metadata.foundation_anchor = true`
|
|
- `Policy.metadata.capture_mode = immutable_backup`
|
|
- RBAC version shape:
|
|
- `PolicyVersion.snapshot` = immutable RBAC payload
|
|
- `PolicyVersion.capture_purpose = backup`
|
|
- identical protected snapshots are reused for the same synthetic policy instead of creating duplicate versions
|
|
|
|
### Normalized RBAC Snapshot View Model
|
|
Human-readable representation produced for backup/version display and future diff-safe reuse.
|
|
|
|
#### Role Definition normalized fields
|
|
- `name`
|
|
- `description`
|
|
- `is_built_in`
|
|
- `role_permissions`
|
|
- normalized permission blocks
|
|
- ordered for diff stability
|
|
- optional warnings when payload is incomplete or partially expanded
|
|
|
|
#### Role Assignment normalized fields
|
|
- `assignment_name`
|
|
- `role_definition`
|
|
- preferred: readable name + stable id
|
|
- `members`
|
|
- readable names when known, ids as fallback
|
|
- `scope_members`
|
|
- readable names when known, ids as fallback
|
|
- `resource_scopes`
|
|
- stable ordered values
|
|
- optional warnings when referenced objects are unresolved
|
|
|
|
### Verification Check Row
|
|
Provider or tenant verification result describing RBAC permission readiness.
|
|
|
|
- Existing source pattern: `TenantPermissionCheckClusters`
|
|
- Relevant fields:
|
|
- `key`
|
|
- `title`
|
|
- `status = pass | warn | fail`
|
|
- `severity`
|
|
- `blocking`
|
|
- `reason_code`
|
|
- `message`
|
|
- `evidence[]`
|
|
- `next_steps[]`
|
|
- RBAC v1 target behavior:
|
|
- Missing `DeviceManagementRBAC.Read.All` produces a clear warning or failure reason with actionable next steps.
|
|
- The rest of the inventory pipeline remains able to complete partially.
|
|
|
|
## Relationships
|
|
|
|
- A `Tenant` has many `InventoryItem` rows, including RBAC foundation rows.
|
|
- A `Tenant` has many `BackupSet` rows.
|
|
- A `BackupSet` has many `BackupItem` rows, including RBAC foundation payload snapshots.
|
|
- A synthetic RBAC `Policy` has many immutable `PolicyVersion` rows and can be referenced by RBAC `BackupItem` rows.
|
|
- An `OperationRun` for inventory sync carries coverage status for RBAC foundation types in `context.inventory.coverage.foundation_types`.
|
|
- Verification rows and provider reason codes describe permission posture for the same tenant and workspace scope.
|
|
|
|
## Invariants
|
|
|
|
- `intuneRoleDefinition` and `intuneRoleAssignment` are separate foundation types everywhere: config, contracts, inventory, backup, coverage, and normalization.
|
|
- Inventory rows remain metadata-only and tenant-scoped.
|
|
- Full RBAC payloads are stored only in immutable backup/version artifacts.
|
|
- Restore mode for both RBAC foundation types is always `preview-only` in v1.
|
|
- Non-members must not be able to infer RBAC object existence across workspace or tenant boundaries.
|
|
- Missing `DeviceManagementRBAC.Read.All` must produce a stable reason path rather than an opaque exception.
|
|
- Role Definitions and Role Assignments must normalize in a stable, ordered, diff-safe manner.
|
|
|
|
## State Transitions
|
|
|
|
### Inventory coverage state
|
|
- `skipped`
|
|
- when foundations are excluded from a run or a type is not attempted
|
|
- `failed`
|
|
- when the RBAC fetch for that type fails or returns a permission/problem reason
|
|
- `succeeded`
|
|
- when the RBAC type is fetched and inventory rows are updated successfully
|
|
|
|
### Backup capture state for RBAC foundations
|
|
- not present in backup set
|
|
- created as immutable `BackupItem` plus synthetic `Policy` / `PolicyVersion` linkage for version-detail review
|
|
- restored from soft-delete if already present in the same backup set and previously archived
|
|
|
|
### Verification state for RBAC permission readiness
|
|
- `pass`
|
|
- all required RBAC read permissions are present
|
|
- `warn`
|
|
- delegated refresh or adjacent non-blocking permission posture issue exists
|
|
- `fail`
|
|
- required application permission is missing or permission fetch errored in a blocking way
|
|
|
|
## Validation Rules
|
|
|
|
- Foundation type config rows must include deterministic `restore` and `risk` metadata.
|
|
- RBAC Graph contracts must only request fields allowed by the contract registry.
|
|
- Inventory updates require non-empty Graph `id` values.
|
|
- Backup foundation snapshots require non-empty `source_id` values.
|
|
- Normalizers must preserve identifiers when readable expansions are absent.
|