Private/Get-NSPEntraHardMatchTenantState.ps1

function Get-NSPEntraHardMatchTenantState {
    <#
    .SYNOPSIS
        Reads what hard-match checks need from the whole tenant, once. Read-only.
    .DESCRIPTION
        Any directory role counts, at any scope, not only the ones Microsoft calls privileged: a
        role holder is never a routine match. Group-held roles are expanded to the group's members.
        A failed role read throws, because an unknown role holder must not read as none.
 
        Not covered: a user who is only eligible for membership of a role-assignable group through
        PIM for Groups. Entra's own hard-match check still applies at sync.
    #>

    [CmdletBinding()]
    param([switch]$AssumeNoRoleEligibility)

    $roles = Get-NSPEntraPairingRoleState -AssumeNoRoleEligibility:$AssumeNoRoleEligibility
    $roleHolders = $roles.RoleHolders
    $eligible = $roles.EligibleHolders
    $warnings = [System.Collections.Generic.List[string]]::new()
    $blocks = [System.Collections.Generic.List[string]]::new()
    foreach ($warning in $roles.Warnings) { $warnings.Add($warning) }
    foreach ($block in $roles.Blocks) { $blocks.Add($block) }
    $deletedAnchors = @{}
    foreach ($user in @(Invoke-NSPGraphCollection -Uri 'directory/deletedItems/microsoft.graph.user?$select=id,onPremisesImmutableId&$top=999')) {
        if ($null -ne $user -and $user['onPremisesImmutableId']) { $deletedAnchors[[string]$user['onPremisesImmutableId']] = [string]$user['id'] }
    }

    # Reading this needs Global Administrator. If it is unreadable the write is safe but may achieve
    # nothing, because Entra then refuses the match at sync. So that is a warning, not a block.
    try {
        $settings = @((Invoke-NSPGraphRequest -Uri 'directory/onPremisesSynchronization')['value'] | Where-Object { $null -ne $_ })
        if (-not $settings.Count) {
            $warnings.Add('The tenant has no on-premises synchronization settings yet, so its hard-match block could not be checked.')
        }
        foreach ($setting in $settings) {
            if ($setting['features']['blockCloudObjectTakeoverThroughHardMatchEnabled'] -eq $true) {
                $blocks.Add('The tenant has blockCloudObjectTakeoverThroughHardMatchEnabled on, so Entra would refuse every hard match. This module does not change that setting.')
            }
        }
    } catch {
        $warnings.Add('The tenant''s hard-match block could not be read; that needs Global Administrator. If it is on, Entra refuses the match at sync.')
    }

    [pscustomobject]@{
        RoleHolders = $roleHolders
        EligibleHolders = $eligible
        DeletedAnchors = $deletedAnchors
        Blocks = @($blocks)
        Warnings = @($warnings)
    }
}