Public/Resolve-NSPEntraPairingSourceAnchor.ps1

function Resolve-NSPEntraPairingSourceAnchor {
    <#
    .SYNOPSIS
        Collects source-anchor evidence locally or from a chosen sync server, with JSON as a fallback.
    .DESCRIPTION
        Automatically tries the local sync-rule reader first. If this is not the sync server,
        guides a confirmed read on an operator-named server using existing PowerShell remoting.
        Installs nothing on that server, never configures remoting, starts sync or guesses anchors.
        Evidence stays in memory until the pairing queue saves it in its private local state.
    .EXAMPLE
        Resolve-NSPEntraPairingSourceAnchor
    .EXAMPLE
        Resolve-NSPEntraPairingSourceAnchor -ComputerName sync01.example.test
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [ValidatePattern('\A[A-Za-z0-9][A-Za-z0-9.-]{0,252}\z')][string]$ComputerName,
        [pscredential]$Credential
    )
    if (-not $PSCmdlet.ShouldProcess('source-anchor diagnostic', 'Collect sync-rule evidence')) { return }
    if ($Credential -and -not $ComputerName) { throw 'Credential requires ComputerName.' }
    Import-NSPToolkitModule -Name NSP.Console -MinimumVersion 0.1.5
    if ($ComputerName) {
        if (-not (Read-NSPConfirm -Prompt "Read effective sync rules on $ComputerName? No sync or directory change will run.")) { return }
        $options = @{ ComputerName = $ComputerName }
        if ($Credential) { $options.Credential = $Credential }
        return Get-NSPEntraConnectSourceAnchor @options
    }
    Write-NSPConsoleLine -Message 'Checking this computer for Entra Connect sync-rule evidence...'
    try { return Get-NSPEntraConnectSourceAnchor -ErrorAction Stop }
    catch { Write-NSPConsoleLine -Message ('Local collection unavailable: ' + $_.Exception.Message) -Role Warning }
    while ($true) {
        $choice = Read-NSPMenu -Prompt 'Where should source-anchor evidence come from?' -Choices @(
            [pscustomobject]@{ Label = 'Read from the Entra Connect Sync server (current sign-in)'; Value = 'remote' }
            [pscustomobject]@{ Label = 'Read from the sync server with another credential'; Value = 'credential' }
            [pscustomobject]@{ Label = 'Import an existing source-anchor diagnostic JSON'; Value = 'file' }
            [pscustomobject]@{ Label = 'Retry this computer'; Value = 'local' }
        ) -CancelLabel 'Back'
        if ($null -eq $choice) { return }
        try {
            if ($choice -eq 'file') {
                $file = Read-NSPFilePath -Prompt 'Source-anchor diagnostic JSON (keep outside Git)' -Filter 'JSON files (*.json)|*.json|All files (*.*)|*.*' -AllowBack
                if (-not $file -or (Test-NSPBackSignal $file)) { continue }
                return Get-Content -LiteralPath $file -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
            }
            if ($choice -eq 'local') { return Get-NSPEntraConnectSourceAnchor -ErrorAction Stop }
            if ($choice -notin @('remote', 'credential')) { throw 'Choose one of the displayed collection routes.' }
            $server = Read-NSPNonEmpty -Prompt 'Entra Connect Sync server hostname' -AllowBack
            if (Test-NSPBackSignal $server) { continue }
            if ($server -notmatch '\A[A-Za-z0-9][A-Za-z0-9.-]{0,252}\z') { throw 'Enter a server hostname or DNS name.' }
            $options = @{ ComputerName = $server; ErrorAction = 'Stop' }
            if ($choice -eq 'credential') {
                Write-NSPConsoleLine -Message 'The Windows credential prompt may appear behind this console. Cancel returns to collection choices.'
                $selectedCredential = Get-Credential -Message 'Credential for read-only sync-rule collection'
                if (-not $selectedCredential) { continue }
                $options.Credential = $selectedCredential
            }
            if (-not (Read-NSPConfirm -Prompt "Read effective sync rules on $server? No sync or directory change will run.")) { continue }
            return Get-NSPEntraConnectSourceAnchor @options
        } catch {
            Write-NSPConsoleLine -Message ('Collection failed: ' + $_.Exception.Message + ' Check the server name, read permissions and existing WinRM access, or use the JSON fallback.') -Role Warning
        }
    }
}