src/Connect-CciGet.ps1

function Connect-CciGet {
<#
.SYNOPSIS
    Register configured CCI feeds as PSResource repositories and prepare credentials.
.DESCRIPTION
    For each enabled feed in Get-CciGetConfig, Connect-CciGet:
      - Ensures the Azure Artifacts Credential Provider is installed (one-time
        bootstrap on Windows; uses the Microsoft installer at
        https://github.com/microsoft/artifacts-credprovider).
      - Calls Register-PSResourceRepository for the feed (idempotent).
    After Connect-CciGet succeeds, Find-CciModule / Install-CciModule will
    transparently use the user's Entra identity (or, in CI, a workload identity)
    to authenticate to the feed. No PATs are required.
.PARAMETER Tenant
    Optional. Limit registration to the named feed only.
.PARAMETER SkipCredentialProvider
    Skip the credential-provider bootstrap (use when you have managed it
    centrally or are running in CI with a different auth strategy).
#>

    [CmdletBinding()]
    param(
        [string]$Tenant,
        [switch]$SkipCredentialProvider
    )

    if (-not (Get-Module -ListAvailable -Name Microsoft.PowerShell.PSResourceGet)) {
        throw "cciget: Microsoft.PowerShell.PSResourceGet is required but not installed. Run: Install-Module Microsoft.PowerShell.PSResourceGet -Scope CurrentUser"
    }
    Import-Module Microsoft.PowerShell.PSResourceGet -ErrorAction Stop

    if (-not $SkipCredentialProvider) {
        $pluginRoot = Join-Path $env:USERPROFILE '.nuget\plugins\netcore'
        if (-not (Test-Path $pluginRoot) -or -not (Get-ChildItem $pluginRoot -Filter 'CredentialProvider.Microsoft.dll' -Recurse -ErrorAction SilentlyContinue)) {
            Write-Host "cciget: installing Azure Artifacts Credential Provider..."
            try {
                $script = (New-Object System.Net.WebClient).DownloadString('https://aka.ms/install-artifacts-credprovider.ps1')
                Invoke-Expression $script
            } catch {
                Write-Warning "cciget: credential provider install failed: $_. You may need to install manually from https://github.com/microsoft/artifacts-credprovider."
            }
        }
    }

    $feeds = _Resolve-CciGetFeed -Tenant $Tenant
    $authFailed = @()

    foreach ($feed in $feeds) {
        $repoName = _Get-CciGetRepositoryName -FeedName $feed.name

        # Configure credential provider for this feed's tenant.
        # Enable device-code flow so auth works on machines where WIA is unavailable.
        if ($feed.tenantId) {
            $env:NUGET_CREDENTIALPROVIDER_MSAL_AUTHORITY = "https://login.microsoftonline.com/$($feed.tenantId)"
        }
        $env:NUGET_CREDENTIALPROVIDER_MSAL_ALLOW_DEVICECODEFLOW = 'true'

        $existing = Get-PSResourceRepository -Name $repoName -ErrorAction SilentlyContinue
        if ($existing) {
            if ($existing.Uri -ne $feed.url) {
                Set-PSResourceRepository -Name $repoName -Uri $feed.url -Trusted
                Write-Verbose "cciget: updated $repoName URL."
            }
        } else {
            Register-PSResourceRepository -Name $repoName -Uri $feed.url -Trusted
            Write-Host "cciget: registered repository '$repoName' -> $($feed.url)"
        }

        # Verify auth by probing the feed. This triggers the credential provider
        # now (at connect time) so auth issues surface here, not in Find-CciModule.
        Write-Host "cciget: authenticating to '$repoName'..."
        $probeOk = $false
        try {
            # A probe for a name that will never exist. If auth succeeds, we get
            # a "no match" error (which is fine). If auth fails, we get a
            # different error (401, credential-provider stderr, etc.).
            $null = Find-PSResource -Name '_cciget_auth_probe_' -Repository $repoName -ErrorAction Stop
            # If no error at all, auth worked (unexpected match or empty result).
            $probeOk = $true
        } catch {
            $msg = $_.Exception.Message
            if ($msg -match 'No match was found') {
                # Auth succeeded — feed simply has nothing matching the probe name.
                $probeOk = $true
            } else {
                Write-Warning "cciget: authentication failed for '$repoName'."
                Write-Warning " Error: $msg"
                $authFailed += $repoName
            }
        }

        if ($probeOk) {
            Write-Host "cciget: '$repoName' authenticated and ready."
        }
    }

    if ($authFailed.Count -gt 0) {
        Write-Warning "cciget: $($authFailed.Count) feed(s) failed authentication: $($authFailed -join ', ')"
        Write-Warning "cciget: You may need to run Connect-CciGet again. If prompted for a device code, complete the sign-in in your browser."
    }

    Get-PSResourceRepository -Name (_Get-CciGetRepositoryName -FeedName '*')
}