Modules/businessdev.ALbuild.Core/Private/Test-BcGitPushPermissionDenied.ps1

function Test-BcGitPushPermissionDenied {
    <#
    .SYNOPSIS
        Decides whether a failed git push failed because the pushing identity lacks write permission.
    .DESCRIPTION
        Internal, pure helper. Inspects git push stderr and returns $true when the remote rejected the
        push for an authorization reason - the build service account is authenticated but does not hold
        the repository's contribute right (Azure DevOps 'TF401027 ... GenericContribute', or an HTTP 403
        / Forbidden from the remote). This is distinct from an authentication failure (missing/expired
        credentials, e.g. 'Authentication failed'), which is a real misconfiguration and must still
        throw. Callers use this to degrade the optional build-branch claim to a stamp-only build rather
        than failing a pipeline whose identity simply cannot create branches.
    .PARAMETER StdErr
        The standard error captured from the git push.
    .OUTPUTS
        System.Boolean
    #>

    [CmdletBinding()]
    [OutputType([bool])]
    param(
        [AllowNull()] [AllowEmptyString()] [string] $StdErr
    )

    if ([string]::IsNullOrWhiteSpace($StdErr)) { return $false }

    $patterns = @(
        'TF40102[0-9]',            # Azure DevOps permission errors (TF401027 = needs GenericContribute)
        'GenericContribute',       # the specific Git contribute permission
        "You need the Git '",      # AzDO 'You need the Git '<perm>' permission to perform this action'
        'returned error: 403',     # HTTP 403 from the remote
        '\bForbidden\b',           # HTTP 403 Forbidden
        'protected branch',        # push blocked by a branch protection / policy
        'pre-receive hook declined'
    )
    foreach ($p in $patterns) {
        if ($StdErr -match $p) { return $true }
    }
    return $false
}