Private/InteropMatrixHelpers.ps1

# Copyright (c) 2026 Broadcom. All Rights Reserved.
# Broadcom Confidential. The term "Broadcom" refers to Broadcom Inc.
# and/or its subsidiaries.
#
# =============================================================================
#
# SOFTWARE LICENSE AGREEMENT
#
# Copyright (c) CA, Inc. All rights reserved.
#
# You are hereby granted a non-exclusive, worldwide, royalty-free license
# under CA, Inc.'s copyrights to use, copy, modify, and distribute this
# software in source code or binary form for use in connection with CA, Inc.
# products.
#
# This copyright notice shall be included in all copies or substantial
# portions of the software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# =============================================================================
#region InteropMatrixHelpers

$Script:VcfCheckInteropMatrixProductIds = @{
    'SDDC_MANAGER' = 851; 'VCENTER' = 2; 'ESX' = 1; 'NSX' = 912
    'VRA' = 114; 'VROPS' = 116; 'VRNI' = 285; 'VRO' = 13; 'VRSLCM' = 337; 'VRLI' = 88; 'VIDM' = 140
}
$Script:VcfCheckMarketingVersionAliasCache = @{}
function Get-VcfCheckMarketingVersionAliasMap {

    <#
        .SYNOPSIS
        Loads and caches one component's marketing-version alias data
        (Data/MarketingVersionAliases/EsxMarketingVersionAliases.json / Data/MarketingVersionAliases/VcenterMarketingVersionAliases.json).

        .PARAMETER Component
        'ESX' or 'VCENTER'.

        .OUTPUTS
        [Hashtable] marketing name -> @{ Version; ReleaseDate }, or an empty hashtable if the
        file is missing or fails to parse.
    #>


    [CmdletBinding()]
    [OutputType([Hashtable])]
    Param (
        [Parameter(Mandatory = $true)] [ValidateSet('ESX', 'VCENTER')] [String]$Component
    )

    if (-not $Script:VcfCheckMarketingVersionAliasCache.ContainsKey($Component)) {
        $fileName = if ($Component -eq 'ESX') { 'EsxMarketingVersionAliases.json' } else { 'VcenterMarketingVersionAliases.json' }
        $path = Join-Path -Path $PSScriptRoot -ChildPath (Join-Path -Path '..' -ChildPath (Join-Path -Path 'Data' -ChildPath (Join-Path -Path 'MarketingVersionAliases' -ChildPath $fileName)))
        $map = @{}
        if (Test-Path -LiteralPath $path -PathType Leaf) {
            try {
                $map = Get-Content -LiteralPath $path -Raw -ErrorAction Stop | ConvertFrom-Json -AsHashtable -ErrorAction Stop
            } catch {
                Write-LogMessage -Type WARNING -Message "Could not parse marketing version alias file `"$path`": $($_.Exception.Message)"
                $map = @{}
            }
        }
        $Script:VcfCheckMarketingVersionAliasCache[$Component] = $map
    }

    return $Script:VcfCheckMarketingVersionAliasCache[$Component]
}
function Resolve-VcfCheckMarketingVersionAliasKeyFromBuild {

    <#
        .SYNOPSIS
        Resolves a live component's raw installed version string to its Broadcom Interop Matrix
        marketing release name (e.g. "8.0U3k"), so that name can be used as the Interop Matrix row
        key for a real compatibility-verdict lookup
        (Get-VcfCheckInteropMatrixCompatibilityVerdict).

        .DESCRIPTION
        A live vCenter/ESX self-reports a raw build number (e.g. "8.0.3.00600-24853646"), never a
        marketing name - matches by extracting the trailing digit run (the real public build
        number, same extraction Test-VcfCheckBomVersionMatch relies on for the same
        reason: separators before the build number are inconsistent, e.g. a period instead of a
        hyphen on some components) and searching the shipped alias data
        (Get-VcfCheckMarketingVersionAliasMap's backing file) for the marketing entry whose
        canonical version ends in that same build number.

        .PARAMETER Component
        'ESX' or 'VCENTER'.

        .PARAMETER RawVersion
        The raw version string as reported live by the component.

        .OUTPUTS
        [String] the matching marketing name (e.g. "8.0U3k"), or $null if RawVersion has no
        trailing digit run, or no alias entry's build number matches it.
    #>


    [CmdletBinding()]
    [OutputType([String])]
    Param (
        [Parameter(Mandatory = $true)] [ValidateSet('ESX', 'VCENTER')] [String]$Component,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$RawVersion
    )

    $build = [Regex]::Match($RawVersion, '(\d+)$').Value
    if ([String]::IsNullOrEmpty($build)) { return $null }

    foreach ($kvp in (Get-VcfCheckMarketingVersionAliasMap -Component $Component).GetEnumerator()) {
        $entryBuild = [Regex]::Match([String]$kvp.Value.Version, '(\d+)$').Value
        if ($entryBuild -and $entryBuild -eq $build) {
            return $kvp.Key
        }
    }
    return $null
}

$Script:VcfCheckInteropMatrixDataFileNames = @{
    851 = 'SddcManager'; 1 = 'Esx'; 2 = 'Vcenter'; 912 = 'Nsx'
    114 = 'Vra'; 116 = 'Vrops'; 285 = 'Vrni'; 13 = 'Vro'; 337 = 'Vrslcm'; 88 = 'Vrli'; 140 = 'Vidm'
}
$Script:VcfCheckInteropMatrixDataCache = @{}
function Invoke-VcfCheckInteropMatrixUpgrades {

    <#
        .SYNOPSIS
        Loads one product's shipped Interop Matrix upgrade-path snapshot.

        .DESCRIPTION
        Reads Data/Interoperability/<ProductName>.json - a snapshot of the same public JSON
        endpoint the https://interopmatrix.broadcom.com "Download CSV" button reads from
        (POST /external/upgrades), captured at release-prep time by
        InternalTools/Update-VcfInteropMatrixData.ps1 and shipped with the product. That live endpoint
        requires a static x-auth-key header embedded in the site's own public JavaScript bundle -
        not a secret, but a value Broadcom could rotate or remove without notice, so calling it
        live from every precheck run would make a shipped product silently depend on it. Reading
        a shipped snapshot instead means a key rotation only ever affects the next scheduled
        regeneration, never a customer's live run.

        Returns only same-product upgrade-path data (which versions of this one product exist,
        and which can upgrade directly from which) - it does not expose cross-product
        compatibility (e.g. "is vCenter version A compatible with NSX version B"); no such public
        endpoint exists on this API (interoptype values other than 'upgrade' and 'database'
        return HTTP 400, and every release's 'components' field is consistently empty).

        .PARAMETER ProductId
        The interop matrix product ID, e.g. 851 (SDDC Manager), 1 (ESX), 2 (vCenter Server),
        912 (VMware NSX).

        .OUTPUTS
        [PSObject] the shipped snapshot (.name, .upgradeProducts[]), or $null if the file is
        missing or fails to parse - callers treat that as "could not confirm," never as "not
        compatible."
    #>


    [CmdletBinding()]
    [OutputType([PSObject])]
    Param (
        [Parameter(Mandatory = $true)] [Int]$ProductId
    )

    if (-not $Script:VcfCheckInteropMatrixDataCache.ContainsKey($ProductId)) {
        $data = $null
        $fileName = $Script:VcfCheckInteropMatrixDataFileNames[$ProductId]
        if (-not $fileName) {
            Write-LogMessage -Type WARNING -Message "No shipped Interop Matrix data file is mapped to product ID ${ProductId}"
        } else {
            $path = Join-Path -Path $PSScriptRoot -ChildPath (Join-Path -Path '..' -ChildPath (Join-Path -Path 'Data' -ChildPath (Join-Path -Path 'Interoperability' -ChildPath "$fileName.json")))
            if (Test-Path -LiteralPath $path -PathType Leaf) {
                try {
                    $data = Get-Content -LiteralPath $path -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
                } catch {
                    Write-LogMessage -Type WARNING -Message "Could not parse Interop Matrix data file `"$path`": $($_.Exception.Message)"
                    $data = $null
                }
            } else {
                Write-LogMessage -Type WARNING -Message "No shipped Interop Matrix data file for product ID ${ProductId}: `"$path`" not found"
            }
        }
        $Script:VcfCheckInteropMatrixDataCache[$ProductId] = $data
    }

    return $Script:VcfCheckInteropMatrixDataCache[$ProductId]
}
function Test-VcfCheckInteropMatrixVersionPublished {

    <#
        .SYNOPSIS
        Confirms whether a version string is a real, published release of a product, per
        Broadcom's public Interop Matrix.

        .DESCRIPTION
        Used only as a fallback sanity check when a destination VCF release could not be resolved
        against SDDC Manager's own release catalog (Get-VcfCheckReleaseBom) - e.g. an
        air-gapped/offline SDDC Manager whose local catalog hasn't synced that release yet. This
        cannot validate compatibility (see Invoke-VcfCheckInteropMatrixUpgrades), only whether
        the requested version string corresponds to something Broadcom has actually shipped, so a
        typo'd or fictitious destination release doesn't silently fall through to
        minimum-version thresholds unnoticed.

        .PARAMETER ProductId
        The interop matrix product ID to check the version against.

        .PARAMETER Version
        The version string to look for, e.g. '9.1.0.0'.

        .OUTPUTS
        [Nullable[Boolean]] $true if the version was found, $false if the API responded but the
        version was not among any product/release version it returned, or $null if the API call
        itself failed (unknown, not a negative result).
    #>


    [CmdletBinding()]
    [OutputType([Nullable[Boolean]])]
    Param (
        [Parameter(Mandatory = $true)] [Int]$ProductId,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$Version
    )

    $response = Invoke-VcfCheckInteropMatrixUpgrades -ProductId $ProductId
    if (-not $response -or -not $response.upgradeProducts) {
        return $null
    }

    $knownVersions = [System.Collections.Generic.HashSet[String]]::new()
    foreach ($upgradeProduct in @($response.upgradeProducts)) {
        [void]$knownVersions.Add($upgradeProduct.version)
        foreach ($release in @($upgradeProduct.releases)) {
            [void]$knownVersions.Add($release.version)
        }
    }

    return $knownVersions.Contains($Version)
}
function Resolve-VcfCheckInteropMatrixSourceProduct {

    <#
        .SYNOPSIS
        Resolves one component's shipped Interop Matrix snapshot to the top-level upgradeProducts
        entry matching an installed version, shared by
        Get-VcfCheckInteropMatrixCompatibilityVerdict and
        Get-VcfCheckInteropMatrixFailureReason so the marketing-name-vs-parsed-version
        resolution rule (see Get-VcfCheckInteropMatrixCompatibilityVerdict's .DESCRIPTION)
        lives in exactly one place.

        .PARAMETER Component
        'SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI',
        or 'VIDM'.

        .PARAMETER InstalledVersion
        The component's raw installed version string, as reported live.

        .OUTPUTS
        [PSObject] the matching upgradeProducts entry (carrying that release's own .genGuided /
        .techGuided / .releases[]), or $null if the snapshot is unreachable or no entry matches.
    #>


    [CmdletBinding()]
    [OutputType([PSObject])]
    Param (
        [Parameter(Mandatory = $true)] [ValidateSet('SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI', 'VIDM')] [String]$Component,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$InstalledVersion
    )

    $response = Invoke-VcfCheckInteropMatrixUpgrades -ProductId $Script:VcfCheckInteropMatrixProductIds[$Component]
    if (-not $response -or -not $response.upgradeProducts) { return $null }

    $installedMajor = [Regex]::Match($InstalledVersion, '\d+')
    $useMarketingName = ($Component -in @('ESX', 'VCENTER')) -and $installedMajor.Success -and ([Int]$installedMajor.Value -lt 9)

    if ($useMarketingName) {
        $marketingKey = Resolve-VcfCheckMarketingVersionAliasKeyFromBuild -Component $Component -RawVersion $InstalledVersion
        if (-not $marketingKey) { return $null }
        return $response.upgradeProducts | Where-Object { $_.version -eq $marketingKey } | Select-Object -First 1
    }

    $installedParsed = ConvertTo-VcfCheckSimpleVersion -VersionString $InstalledVersion
    if (-not $installedParsed) { return $null }
    return $response.upgradeProducts | Where-Object { (ConvertTo-VcfCheckSimpleVersion -VersionString $_.version) -eq $installedParsed } | Select-Object -First 1
}
function Get-VcfCheckInteropMatrixFailureReason {

    <#
        .SYNOPSIS
        Builds a human-readable reason a component's installed-to-destination upgrade pair is not
        ready to upgrade, per Broadcom's public Interop Matrix.

        .DESCRIPTION
        Distinguishes the two failure shapes the matrix actually reports for failure reason reporting:
        - An explicit release-date-based (or similar) incompatibility for this exact pair
          (status 2) - returned as "Incompatible - <Broadcom's own footnote text>".
        - The installed release itself being past its own support window (its .genGuided /
          .techGuided flags), independent of any specific destination - returned as
          "Not Supported - Past End of General Support" or "...Technical Guidance".

        .PARAMETER Component
        'SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI',
        or 'VIDM'.

        .PARAMETER InstalledVersion
        The component's raw installed version string, as reported live.

        .PARAMETER DestinationVersion
        The destination VCF release version, e.g. '9.1.0.0'.

        .OUTPUTS
        [String] the failure reason, or $null if the pair could not be resolved in the shipped
        snapshot (unknown - callers should fall back to their own minimum-version message) or the
        pair is actually compatible.
    #>


    [CmdletBinding()]
    [OutputType([String])]
    Param (
        [Parameter(Mandatory = $true)] [ValidateSet('SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI', 'VIDM')] [String]$Component,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$InstalledVersion,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$DestinationVersion
    )

    $sourceProduct = Resolve-VcfCheckInteropMatrixSourceProduct -Component $Component -InstalledVersion $InstalledVersion
    if (-not $sourceProduct) { return $null }

    $destinationParsed = ConvertTo-VcfCheckSimpleVersion -VersionString $DestinationVersion
    if (-not $destinationParsed) { return $null }
    $releaseEntry = $sourceProduct.releases | Where-Object { (ConvertTo-VcfCheckSimpleVersion -VersionString $_.version) -eq $destinationParsed } | Select-Object -First 1

    if ($releaseEntry -and [Int]$releaseEntry.status -eq 2) {
        $footnote = if ([String]::IsNullOrWhiteSpace($releaseEntry.footnotes)) { "Broadcom's Interop Matrix flags this direct upgrade path unsupported, you may need to perform a data migration instead" } else { $releaseEntry.footnotes }
        return "Incompatible - $footnote"
    }
    if ($sourceProduct.genGuided -eq $false -and $sourceProduct.techGuided -eq $false) {
        return 'Not Supported - Past End of General Support'
    }
    if ($sourceProduct.genGuided -eq $false) {
        return 'Not Supported - Past End of Technical Guidance'
    }
    return $null
}
function Get-VcfCheckInteropMatrixCompatibilityVerdict {

    <#
        .SYNOPSIS
        Looks up the real, specific upgrade-path compatibility verdict for one component between
        an installed version and a destination version, from Broadcom's public Interop Matrix -
        the primary data source for BOM compliance decisions.

        .DESCRIPTION
        A floor (>=) comparison only approximates compatibility and misses Broadcom's real
        upgrade-path exceptions - confirmed live: ESX "8.0U2f" to VCF ESX release 9.1.0.0100 is
        flagged Incompatible by the matrix (a release-date-based exception: 8.0U2f's own release
        date is later than 9.1.0.0100's) despite clearing any numeric floor. This function reads
        that matrix's own per-version-pair status field directly instead of approximating it.

        Resolution: for ESX/vCenter, InstalledVersion is first resolved to its Interop Matrix
        marketing-name row (Resolve-VcfCheckMarketingVersionAliasKeyFromBuild) since the matrix
        labels pre-VCF9 releases that way and no live API ever reports a marketing name. For
        NSX/SDDC Manager, and for any VCF9+ installed version (already in the matrix's own
        unified numeric format), InstalledVersion is matched by parsed-version equality instead -
        exact string matching would be brittle against formatting differences like a missing
        leading zero (e.g. "9.1.0.100" vs the matrix's own "9.1.0.0100").

        DestinationVersion is always matched by parsed-version equality against that row's
        releases[] entries, since a chosen destination is always a VCF9+ unified numeric release
        (the default destination-release floor is 9.0.0.0).

        .PARAMETER Component
        'SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI',
        or 'VIDM'. The Aria Suite components (VRA/VROPS/VRNI/VRO/VRSLCM/VRLI/VIDM) always report a
        unified numeric build live, so - unlike ESX/VCENTER - they are matched by parsed-version
        equality, never a marketing-name lookup.

        .PARAMETER InstalledVersion
        The component's raw installed version string, as reported live.

        .PARAMETER DestinationVersion
        The destination VCF release version, e.g. '9.1.0.0'.

        .OUTPUTS
        [String] 'Compatible' or 'Incompatible' when the matrix has a real verdict for this exact
        pair; otherwise $null (unknown - could not resolve a row, the pair isn't listed, or the
        shipped snapshot couldn't be read), meaning the caller should fall back to a floor
        comparison instead of treating $null as either a pass or a fail.
    #>


    [CmdletBinding()]
    [OutputType([String])]
    Param (
        [Parameter(Mandatory = $true)] [ValidateSet('SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI', 'VIDM')] [String]$Component,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$InstalledVersion,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$DestinationVersion
    )

    $sourceProduct = Resolve-VcfCheckInteropMatrixSourceProduct -Component $Component -InstalledVersion $InstalledVersion
    if (-not $sourceProduct) { return $null }

    $destinationParsed = ConvertTo-VcfCheckSimpleVersion -VersionString $DestinationVersion
    if (-not $destinationParsed) { return $null }
    $releaseEntry = $sourceProduct.releases | Where-Object { (ConvertTo-VcfCheckSimpleVersion -VersionString $_.version) -eq $destinationParsed } | Select-Object -First 1
    if (-not $releaseEntry -or $null -eq $releaseEntry.status) { return $null }

    switch ([Int]$releaseEntry.status) {
        { $_ -in @(1, 3) } { return 'Compatible' }
        2 { return 'Incompatible' }
        default { return $null }
    }
}
function Get-VcfCheckInteropMatrixMinimumCompatibleVersion {

    <#
        .SYNOPSIS
        Resolves one component's lowest installed version that Broadcom's public Interop Matrix
        marks Compatible for direct upgrade to a given destination version.

        .DESCRIPTION
        Callers use a minimum-version floor only as a fallback when
        Get-VcfCheckInteropMatrixCompatibilityVerdict cannot resolve a real per-pair verdict for
        the component's own actual installed version. That floor must itself come from the same
        shipped snapshot (Invoke-VcfCheckInteropMatrixUpgrades), never a hardcoded literal - a
        literal silently drifts out of sync with the matrix (e.g. VROPS 8.18.0-8.18.5 are flagged
        Incompatible for VCF 9.1.1.0, with 8.18.6 the actual floor). This scans every
        upgradeProducts entry, keeps the ones whose releases[] row for DestinationVersion has
        status 1 or 3 (Compatible - see Get-VcfCheckInteropMatrixCompatibilityVerdict), and
        returns the lowest such source version.

        .PARAMETER Component
        'SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI',
        or 'VIDM'.

        .PARAMETER DestinationVersion
        The destination VCF release version, e.g. '9.1.1.0'.

        .OUTPUTS
        [String] the lowest compatible source version string, or $null if the shipped snapshot is
        unreachable, has no resolvable status for DestinationVersion on any source version, or
        DestinationVersion itself doesn't parse - callers should fall back to their own last-resort
        floor default, never treat $null as "any version is compatible."
    #>


    [CmdletBinding()]
    [OutputType([String])]
    Param (
        [Parameter(Mandatory = $true)] [ValidateSet('SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI', 'VIDM')] [String]$Component,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$DestinationVersion
    )

    $response = Invoke-VcfCheckInteropMatrixUpgrades -ProductId $Script:VcfCheckInteropMatrixProductIds[$Component]
    if (-not $response -or -not $response.upgradeProducts) { return $null }

    $destinationParsed = ConvertTo-VcfCheckSimpleVersion -VersionString $DestinationVersion
    if (-not $destinationParsed) { return $null }

    $compatibleSources = [System.Collections.Generic.List[PSCustomObject]]::new()
    foreach ($upgradeProduct in @($response.upgradeProducts)) {
        $releaseEntry = @($upgradeProduct.releases) | Where-Object { (ConvertTo-VcfCheckSimpleVersion -VersionString $_.version) -eq $destinationParsed } | Select-Object -First 1
        if (-not $releaseEntry -or $null -eq $releaseEntry.status -or [Int]$releaseEntry.status -notin @(1, 3)) { continue }
        $parsedSource = ConvertTo-VcfCheckSimpleVersion -VersionString $upgradeProduct.version
        if ($parsedSource) { $compatibleSources.Add([PSCustomObject]@{ Raw = $upgradeProduct.version; Parsed = $parsedSource }) }
    }
    if ($compatibleSources.Count -eq 0) { return $null }

    return ($compatibleSources | Sort-Object -Property Parsed | Select-Object -First 1).Raw
}
function Resolve-VcfCheckInteropMatrixReleaseInFamily {

    <#
        .SYNOPSIS
        Resolves a destination release family (major.minor.patch, e.g. '9.1.0') - or the literal
        'latest' - to one component's own newest concrete published release within that family,
        per its shipped Interop Matrix snapshot.

        .DESCRIPTION
        The top-level "VCF destination release" selector lets a user pick a release family rather
        than a specific 4th-digit patch build, since two components in the same VCF release train
        can ship a different newest patch (e.g. NSX 9.1.0.0300 while vCenter is still at
        9.1.0.0100) - a single shared concrete version would either miss a component's real
        latest patch or invent one it never shipped. Resolving independently per component
        against its own shipped snapshot (Invoke-VcfCheckInteropMatrixUpgrades) instead
        returns each component's real newest release in that family.

        Every version string appearing anywhere in the snapshot (both top-level upgradeProducts
        entries and their nested releases[]) is a real published release of this component, so
        the candidate pool is the union of both.

        .PARAMETER Component
        'SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI',
        or 'VIDM'.

        .PARAMETER Family
        A major.minor.patch string (e.g. '9.1.0'), or 'latest' for this component's overall
        newest known release regardless of family.

        .OUTPUTS
        [String] the resolved concrete version string (e.g. '9.1.0.0300'), or $null if the
        snapshot is unreachable/unparsable, or no release matches the requested family.
    #>


    [CmdletBinding()]
    [OutputType([String])]
    Param (
        [Parameter(Mandatory = $true)] [ValidateSet('SDDC_MANAGER', 'VCENTER', 'ESX', 'NSX', 'VRA', 'VROPS', 'VRNI', 'VRO', 'VRSLCM', 'VRLI', 'VIDM')] [String]$Component,
        [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [String]$Family
    )

    $response = Invoke-VcfCheckInteropMatrixUpgrades -ProductId $Script:VcfCheckInteropMatrixProductIds[$Component]
    if (-not $response -or -not $response.upgradeProducts) { return $null }

    $candidates = @($response.upgradeProducts | ForEach-Object { $_.version }) +
        @($response.upgradeProducts | ForEach-Object { $_.releases } | Where-Object { $_ } | ForEach-Object { $_.version })

    $parsedCandidates = @($candidates | Where-Object { $_ } | Select-Object -Unique | ForEach-Object {
        $parsed = ConvertTo-VcfCheckSimpleVersion -VersionString $_
        if ($parsed) { [PSCustomObject]@{ Raw = $_; Parsed = $parsed } }
    })
    if ($parsedCandidates.Count -eq 0) { return $null }

    if ($Family -eq 'latest') {
        return ($parsedCandidates | Sort-Object -Property Parsed -Descending | Select-Object -First 1).Raw
    }

    $familyParsed = ConvertTo-VcfCheckSimpleVersion -VersionString $Family
    if (-not $familyParsed) { return $null }

    $inFamily = @($parsedCandidates | Where-Object {
        $_.Parsed.Major -eq $familyParsed.Major -and $_.Parsed.Minor -eq $familyParsed.Minor -and $_.Parsed.Build -eq $familyParsed.Build
    })
    if ($inFamily.Count -eq 0) { return $null }

    return ($inFamily | Sort-Object -Property Parsed -Descending | Select-Object -First 1).Raw
}

#endregion