Private/Get-IntuneAccessUpdateComplianceEvidence.ps1

function Get-IntuneAccessUpdateComplianceEvidence {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] [AllowEmptyCollection()] [object[]] $Workload,
        [Parameter(Mandatory)] [AllowEmptyCollection()] [object[]] $Assignment,
        [Parameter(Mandatory)] [AllowEmptyCollection()] [object[]] $ManagedDevice,
        [AllowEmptyCollection()] [object[]] $DeploymentOutcome = @(),
        [datetimeoffset] $AsOf = [DateTimeOffset]::Now
    )

    $investigations = [System.Collections.Generic.List[object]]::new()
    $updateWorkloads = @($Workload | Where-Object { (Get-IntuneAccessProperty $_ 'WorkloadType') -eq 'Updates' -or (Get-IntuneAccessProperty $_ 'SourceCollection') -match '(?i)update' })
    $complianceWorkloads = @($Workload | Where-Object WorkloadType -EQ 'Compliance')
    $apiVersions = @($updateWorkloads + $complianceWorkloads | ForEach-Object {
        [string] (Get-IntuneAccessProperty $_ 'SourceApiVersion' 'NotReturned')
    } | Select-Object -Unique)
    foreach ($device in $ManagedDevice) {
        $lastSync = ConvertTo-IntuneAccessDateTimeOffset $device.LastSyncDateTime
        $age = if ($null -eq $lastSync) { $null } else { [math]::Max(0, [math]::Floor(($AsOf - $lastSync).TotalDays)) }
        foreach ($item in @($updateWorkloads + $complianceWorkloads)) {
            $outcomes = @($DeploymentOutcome | Where-Object { $_.WorkloadId -eq $item.Id -and $_.DeviceId -eq $device.Id })
            $assignments = @($Assignment | Where-Object WorkloadId -EQ $item.Id)
            $returnedState = if ($outcomes.Count -eq 0) { 'NoReportedEvidence' } elseif (@($outcomes | Where-Object Category -EQ 'Error').Count -gt 0) { 'ReturnedFailure' } elseif (@($outcomes | Where-Object Category -EQ 'Success').Count -gt 0) { 'ReportedSuccess' } else { [string] $outcomes[0].Category }
            $targetVersion = [string] (Get-IntuneAccessProperty $item 'TargetVersion')
            $patchState = 'NotEvaluated'
            $reason = 'No dependable target version and supported device result were available together.'
            if ($item.WorkloadType -eq 'Compliance') {
                $patchState = switch -Regex ([string] $device.ComplianceState) {
                    '^compliant$' { 'ReportedCompliant'; break }
                    '^noncompliant$' { 'ReportedNonCompliant'; break }
                    default { 'NotEvaluated' }
                }
                $reason = 'This state comes from the managed-device compliance summary; setting-level evidence can differ.'
            }
            elseif (-not [string]::IsNullOrWhiteSpace($targetVersion) -and -not [string]::IsNullOrWhiteSpace([string] $device.OsVersion)) {
                $patchState = if ([string] $device.OsVersion -match [regex]::Escape($targetVersion)) { 'TargetVersionObserved' } else { 'OutsideObservedTargetVersion' }
                $reason = 'The current OS version was compared with the version label returned by the update workload. This does not prove update eligibility or deadline state.'
            }
            if ($returnedState -eq 'ReturnedFailure') { $patchState = 'ReturnedFailure'; $reason = 'A supported Microsoft Graph outcome endpoint returned an error-category result.' }
            elseif ($age -ge 30 -and $patchState -notin @('ReturnedFailure')) { $patchState = 'StaleReporting'; $reason = "The latest managed-device check-in evidence is $age days old." }

            if ($assignments.Count -gt 0 -or $outcomes.Count -gt 0 -or $item.WorkloadType -eq 'Compliance') {
                $investigations.Add([PSCustomObject] @{
                    PSTypeName         = 'IntuneAccess.UpdateComplianceInvestigation'
                    DeviceId           = [string] $device.Id
                    DeviceName         = [string] $device.DeviceName
                    UserPrincipalName  = [string] $device.UserPrincipalName
                    OperatingSystem    = [string] $device.OperatingSystem
                    OsVersion          = [string] $device.OsVersion
                    WorkloadId         = [string] $item.Id
                    WorkloadName       = [string] $item.Name
                    WorkloadType       = [string] $item.WorkloadType
                    SourceCollection   = [string] (Get-IntuneAccessProperty $item 'SourceCollection' 'NotReturned')
                    TargetVersion      = $targetVersion
                    ConfiguredTargets  = $assignments
                    ReportedOutcomes   = $outcomes
                    ReportedState      = $returnedState
                    InvestigationState = $patchState
                    Explanation        = $reason
                    EvidenceAgeDays    = $age
                    EvidenceTimestamp  = $lastSync
                    EvidenceBoundary   = 'Configured targeting, reporting delay, stale evidence, returned failure and unavailable evidence are separate states. A configured target is not proof of applicability or delivery.'
                })
            }
        }
    }

    [PSCustomObject] @{
        PSTypeName           = 'IntuneAccess.UpdateComplianceEvidence'
        Investigations       = $investigations.ToArray()
        UpdateWorkloads      = $updateWorkloads
        ComplianceWorkloads  = $complianceWorkloads
        CollectionStatus     = [PSCustomObject] @{ State = if ($ManagedDevice.Count -eq 0) { 'NoDeviceEvidence' } else { 'Available' }; RecordCount = $investigations.Count; ApiVersions = $apiVersions }
        Warnings             = @('Update and compliance reporting availability varies by workload. NotEvaluated is retained where the collected evidence cannot support a conclusion.')
        GraphPermissionsUsed = @('DeviceManagementConfiguration.Read.All', 'DeviceManagementManagedDevices.Read.All')
        GeneratedAt          = $AsOf
        ToolVersion          = $script:IntuneAccessVersion
    }
}