Public/Core/Update-EntraOps.ps1

<#
.SYNOPSIS
    Update of EntraOps PowerShell module and GitHub workflow files.

.DESCRIPTION
    Cmdlet is used to update the EntraOps PowerShell module and GitHub workflow files.
    If the config file's "AutomatedEntraOpsUpdate" section defines "Repository", "Branch" and/or
    "TargetUpdateFolders", those values are used instead of the built-in defaults, unless the
    corresponding -Repository, -Branch or -TargetUpdateFolders parameter is explicitly passed to
    this cmdlet. GitHub workflow definitions are excluded from the default targets. To update them
    interactively, explicitly select ./.github/workflows together with ./.github/actions and
    ./.github/scripts, then publish the reviewed local changes with an authorized user credential.

    The supported distribution repositories are declared once in the local EntraOpsUpdateContract.json:
    the public "EntraOps" release repository (default, no credentials) and the private
    "EntraOps-Insiders" repository, which requires -PersonalAccessToken or the ENTRAOPS_PAT
    environment variable (the EntraOpsUpdatePat secret in the workflow).

.PARAMETER TargetUpdateFolders
    Repository-relative targets to replace from the configured upstream ref. Workflow definitions
    are supported but excluded by default. Select ./.github/workflows together with
    ./.github/actions and ./.github/scripts for an interactive workflow refresh. Automated workflow
    publication additionally requires the GitHub App credentials documented in Docs/content/core.md.

.EXAMPLE
    This example updates EntraOps with default values of the main branch and the default target folders.
    Update-EntraOps

.EXAMPLE
    This example explicitly refreshes GitHub workflow definitions and their required dependencies.
    Update-EntraOps -ConfigFile ./EntraOpsConfig.json -RunBrowserTests `
        -TargetUpdateFolders @('./.github/actions', './.github/scripts', './.github/workflows')
#>


function Update-EntraOps {
    [cmdletbinding()]
    param (
        [Parameter(Mandatory = $False)]
        [System.String]$Branch = "main"
        ,
        [Parameter(Mandatory = $False)]
        [System.String]$Repository = "EntraOps"
        ,        
        [Parameter(Mandatory = $False)]
        [System.String]$PersonalAccessToken
        ,
        [Parameter(Mandatory = $False)]
        [System.String]$ConfigFile = "./EntraOpsConfig.json"
        ,
        [Parameter(Mandatory = $False)]
        [ValidateSet("./.github/actions", "./.github/agents", "./.github/scripts", "./.github/workflows", "./Docs", "./EntraOps", "./Parsers", "./Queries", "./Reports", "./Samples", "./Tests", "./Workbooks", "./package.json", "./package-lock.json", "./playwright.config.mjs", "./CHANGELOG.md", "./EntraOpsUpdateContract.json")]
        [Object]$TargetUpdateFolders = @("./.github/actions", "./.github/agents", "./.github/scripts", "./Docs", "./EntraOps", "./Parsers", "./Queries", "./Reports", "./Samples", "./Tests", "./Workbooks", "./package.json", "./package-lock.json", "./playwright.config.mjs", "./CHANGELOG.md", "./EntraOpsUpdateContract.json")
        ,
        [Parameter(Mandatory = $False)]
        [System.String]$TemporaryUpdateFolder = "TmpUpdate"
        ,
        [Parameter(Mandatory = $False)]
        [switch]$RunBrowserTests
        ,
        [Parameter(Mandatory = $False)]
        [switch]$SkipCandidateValidation
        ,
        [Parameter(Mandatory = $False)]
        [string]$PreparedCandidatePath
        ,
        [Parameter(Mandatory = $False)]
        [ValidatePattern('^[0-9a-fA-F]{40}$')]
        [string]$ValidatedSourceCommit
        ,
        [Parameter(Mandatory = $False)]
        [switch]$BrowserTestsValidated
    )

    $ErrorActionPreference = "Stop"

    # Allow the config file's "AutomatedEntraOpsUpdate" section to override the default
    # Repository/Branch/TargetUpdateFolders used for self-update, unless the caller explicitly
    # passed -Repository, -Branch or -TargetUpdateFolders.
    if (Test-Path -Path $ConfigFile) {
        try {
            $UpdateConfig = (Get-Content -Path $ConfigFile | ConvertFrom-Json).AutomatedEntraOpsUpdate
            if (-not $PSBoundParameters.ContainsKey('Repository') -and -not [string]::IsNullOrWhiteSpace($UpdateConfig.Repository)) {
                Write-Verbose "Using Repository '$($UpdateConfig.Repository)' from config file '$ConfigFile'."
                $Repository = $UpdateConfig.Repository
            }
            if (-not $PSBoundParameters.ContainsKey('Branch') -and -not [string]::IsNullOrWhiteSpace($UpdateConfig.Branch)) {
                Write-Verbose "Using Branch '$($UpdateConfig.Branch)' from config file '$ConfigFile'."
                $Branch = $UpdateConfig.Branch
            }
            if (-not $PSBoundParameters.ContainsKey('TargetUpdateFolders') -and $UpdateConfig.TargetUpdateFolders) {
                Write-Verbose "Using TargetUpdateFolders '$($UpdateConfig.TargetUpdateFolders -join ', ')' from config file '$ConfigFile'."
                $TargetUpdateFolders = @($UpdateConfig.TargetUpdateFolders)
            }
        } catch {
            Write-Warning "Failed to read Repository/Branch/TargetUpdateFolders override from config file '$ConfigFile'. Falling back to defaults. Error: $_"
        }
    }

    # Validate config-derived targets explicitly. ValidateSet protects command-line arguments, but
    # values read from JSON bypass parameter binding and must not escape the intended repository
    # update boundary.
    $AllowedUpdateTargets = @('./.github/actions', './.github/agents', './.github/scripts', './.github/workflows', './Docs', './EntraOps', './Parsers', './Queries', './Reports', './Samples', './Tests', './Workbooks', './package.json', './package-lock.json', './playwright.config.mjs', './CHANGELOG.md', './EntraOpsUpdateContract.json')
    $TargetUpdateFolders = @($TargetUpdateFolders | ForEach-Object { [string]$_ } | Select-Object -Unique)
    if ($TargetUpdateFolders.Count -eq 0) {
        throw 'At least one TargetUpdateFolders entry is required.'
    }
    $InvalidUpdateTargets = @($TargetUpdateFolders | Where-Object { $AllowedUpdateTargets -notcontains $_ })
    if ($InvalidUpdateTargets.Count -gt 0) {
        throw "Unsupported TargetUpdateFolders value(s) in '$ConfigFile': $($InvalidUpdateTargets -join ', '). Use only repository targets exposed by Update-EntraOps."
    }
    if ($TargetUpdateFolders -contains './.github/workflows') {
        $MissingWorkflowDependencies = @(@('./.github/actions', './.github/scripts') | Where-Object { $TargetUpdateFolders -notcontains $_ })
        if ($MissingWorkflowDependencies.Count -gt 0) {
            throw "Updating './.github/workflows' also requires target(s): $($MissingWorkflowDependencies -join ', ')."
        }
        if ($SkipCandidateValidation) {
            throw "Candidate validation cannot be skipped when './.github/workflows' is updated."
        }
    }
    # The local contract is the single source of truth for which Cloud-Architekt repositories
    # distribute EntraOps and whether they need a Personal Access Token. Resolving it here, before
    # any clone, keeps the credential decision independent of the downloaded candidate.
    $Source = Resolve-EntraOpsUpdateSource -Repository $Repository -ContractPath (Join-Path $EntraOpsBaseFolder 'EntraOpsUpdateContract.json')
    $SourceRepository = $Source.Repository
    if ([string]::IsNullOrWhiteSpace($Branch) -or $Branch.StartsWith('-') -or $Branch -match '\s') {
        throw "Unsupported automated-update ref '$Branch'. Use a branch, release tag, or full commit SHA without whitespace or a leading dash."
    }
    if ($ValidatedSourceCommit -and -not $PreparedCandidatePath) {
        throw '-ValidatedSourceCommit requires -PreparedCandidatePath. Resolve and validate the candidate in a separate, credential-free job before applying it.'
    }

    if ([string]::IsNullOrWhiteSpace($PersonalAccessToken) -and -not [string]::IsNullOrWhiteSpace($env:ENTRAOPS_PAT)) {
        $PersonalAccessToken = $env:ENTRAOPS_PAT
    }
    $UsePersonalAccessToken = $false
    if ($Source.RequiresPersonalAccessToken) {
        if ([string]::IsNullOrWhiteSpace($PersonalAccessToken) -and [string]::IsNullOrWhiteSpace($PreparedCandidatePath)) {
            throw "Update source '$SourceRepository' is a private distribution repository and requires a Personal Access Token. Pass -PersonalAccessToken, set ENTRAOPS_PAT (the EntraOpsUpdatePat secret), or use the public 'EntraOps' release repository. No local folder was changed."
        }
        $UsePersonalAccessToken = -not [string]::IsNullOrWhiteSpace($PersonalAccessToken)
    } elseif (-not [string]::IsNullOrWhiteSpace($PersonalAccessToken)) {
        if ($Source.IsKnownDistributionRepository) {
            Write-Verbose "Update source '$SourceRepository' is public. The provided Personal Access Token is not used."
        } else {
            $UsePersonalAccessToken = $true
        }
    }

    # A branch name is mutable: whatever is on it at run time is installed and executed. Release tags
    # and full commit SHAs are immutable and are the supported choice for scheduled, unattended updates.
    if ($Branch -notmatch '^[0-9a-fA-F]{40}$' -and $Branch -notmatch '^v?\d+\.\d+') {
        Write-Warning "EntraOps is updated from the mutable ref '$Branch'. Any upstream commit is installed and executed on the next run without review. Pin 'AutomatedEntraOpsUpdate.Branch' in $ConfigFile to a release tag or a full commit SHA for unattended updates."
    }

    $CloneUpdateCandidate = {
        param([string]$RepositoryUrl)
        & git clone --filter=blob:none --no-checkout $RepositoryUrl $TemporaryUpdateFolder
        if ($LASTEXITCODE -ne 0) {
            throw "git clone failed with exit code $LASTEXITCODE. Verify the repository name and whether a Personal Access Token (secret: EntraOpsUpdatePat) is required."
        }
        & git -C $TemporaryUpdateFolder fetch --depth 1 origin -- $Branch
        if ($LASTEXITCODE -ne 0) {
            throw "git fetch failed for requested ref '$Branch' with exit code $LASTEXITCODE. Use an advertised branch, release tag, or reachable full commit SHA."
        }
        & git -C $TemporaryUpdateFolder checkout --detach FETCH_HEAD
        if ($LASTEXITCODE -ne 0) {
            throw "git checkout failed for requested ref '$Branch' with exit code $LASTEXITCODE."
        }
    }
    $RepositoryUrl = $Source.RepositoryUrl

    # Resolve relative paths against the PowerShell location. Set-Location does not move
    # [Environment]::CurrentDirectory, so [System.IO.Path]::GetFullPath would otherwise point at the
    # directory pwsh was started in while git clones into $PWD.
    $OwnCandidateCheckout = [string]::IsNullOrWhiteSpace($PreparedCandidatePath)
    if ($OwnCandidateCheckout) {
        $TemporaryUpdateFolder = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($TemporaryUpdateFolder)
    } else {
        $TemporaryUpdateFolder = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($PreparedCandidatePath)
    }

    try {
        if (-not $OwnCandidateCheckout) {
            if (-not (Test-Path -LiteralPath $TemporaryUpdateFolder -PathType Container)) {
                throw "Prepared update candidate '$TemporaryUpdateFolder' does not exist. No local file was changed."
            }
            Write-Output "Using prepared update candidate at '$TemporaryUpdateFolder'."
        } elseif ($UsePersonalAccessToken) {
            Write-Output "Cloning repository '$SourceRepository' ($($Source.Channel) channel, ref: $Branch) using Personal Access Token..."
            # Pass credentials via environment-based HTTP header to avoid exposing the PAT in process listings, logs, or error messages
            $PreviousConfigCount = $env:GIT_CONFIG_COUNT
            $PreviousConfigKey0 = $env:GIT_CONFIG_KEY_0
            $PreviousConfigValue0 = $env:GIT_CONFIG_VALUE_0
            try {
                $env:GIT_CONFIG_COUNT = "1"
                $env:GIT_CONFIG_KEY_0 = "http.https://github.com/.extraheader"
                $env:GIT_CONFIG_VALUE_0 = "AUTHORIZATION: basic $([Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("x-access-token:$PersonalAccessToken")))"
                & $CloneUpdateCandidate $RepositoryUrl
            } finally {
                # Restore previous env state
                if ($null -eq $PreviousConfigCount) { Remove-Item env:GIT_CONFIG_COUNT -ErrorAction SilentlyContinue } else { $env:GIT_CONFIG_COUNT = $PreviousConfigCount }
                if ($null -eq $PreviousConfigKey0) { Remove-Item env:GIT_CONFIG_KEY_0 -ErrorAction SilentlyContinue } else { $env:GIT_CONFIG_KEY_0 = $PreviousConfigKey0 }
                if ($null -eq $PreviousConfigValue0) { Remove-Item env:GIT_CONFIG_VALUE_0 -ErrorAction SilentlyContinue } else { $env:GIT_CONFIG_VALUE_0 = $PreviousConfigValue0 }
            }
        } else {
            Write-Output "Cloning repository '$SourceRepository' ($($Source.Channel) channel, ref: $Branch) without authentication..."
            & $CloneUpdateCandidate $RepositoryUrl
        }

        $SourceCommit = (& git -C $TemporaryUpdateFolder rev-parse HEAD).Trim()
        if ($LASTEXITCODE -ne 0 -or $SourceCommit -notmatch '^[0-9a-fA-F]{40}$') {
            throw 'Could not resolve the immutable commit SHA of the downloaded update candidate. No local folder was changed.'
        }

        if ($ValidatedSourceCommit -and $SourceCommit -ne $ValidatedSourceCommit) {
            throw "Prepared candidate commit '$SourceCommit' does not match separately validated commit '$ValidatedSourceCommit'. No local folder was changed."
        }

        Test-EntraOpsUpdateContract -CandidateRoot $TemporaryUpdateFolder -Repository $SourceRepository -TargetUpdateFolders $TargetUpdateFolders | Out-Null

        # The contract validator confirms every requested target exists before anything is removed,
        # so a stale or dishonest source contract cannot leave the deployment partially updated.

        if ($ValidatedSourceCommit) {
            Write-Output "Applying candidate $SourceRepository@$SourceCommit after validation completed in a separate credential-free job."
        } elseif (-not $SkipCandidateValidation) {
            $CandidateValidator = Join-Path $EntraOpsBaseFolder '.github/scripts/Test-EntraOpsUpdateCandidate.ps1'
            if (-not (Test-Path -LiteralPath $CandidateValidator -PathType Leaf)) {
                throw "Trusted update candidate validator not found at '$CandidateValidator'. No local folder was changed."
            }
            Write-Output "Validating update candidate $SourceRepository@$SourceCommit in a child process with a sanitized environment before changing local files..."
            # Allowlist (not denylist) so any credential variable is excluded by construction. The OS/profile
            # entries carry no secrets and are required for pwsh, git and npm to start on Windows.
            $AllowedEnvironmentNames = @(
                'PATH', 'PSModulePath', 'LANG', 'LC_ALL', 'TMPDIR', 'TEMP', 'TMP', 'CI',
                'HOME', 'USER', 'USERNAME', 'USERPROFILE', 'HOMEDRIVE', 'HOMEPATH', 'APPDATA', 'LOCALAPPDATA',
                'ProgramData', 'ProgramFiles', 'ProgramFiles(x86)', 'SystemRoot', 'SystemDrive', 'windir',
                'COMSPEC', 'PATHEXT', 'DOTNET_CLI_TELEMETRY_OPTOUT', 'POWERSHELL_TELEMETRY_OPTOUT'
            )
            $SavedEnvironment = @{}
            foreach ($Entry in Get-ChildItem Env:) { $SavedEnvironment[$Entry.Name] = $Entry.Value }
            try {
                foreach ($Entry in Get-ChildItem Env:) { Remove-Item -LiteralPath "Env:$($Entry.Name)" -ErrorAction SilentlyContinue }
                foreach ($Name in $AllowedEnvironmentNames) {
                    if ($SavedEnvironment.ContainsKey($Name)) { Set-Item -LiteralPath "Env:$Name" -Value $SavedEnvironment[$Name] }
                }
                $ValidatorArguments = @('-NoLogo', '-NoProfile', '-NonInteractive', '-File', $CandidateValidator, '-CandidateRoot', $TemporaryUpdateFolder)
                if ($RunBrowserTests) { $ValidatorArguments += '-RunBrowserTests' }
                & (Get-Process -Id $PID).Path @ValidatorArguments
                if ($LASTEXITCODE -ne 0) { throw "Candidate validation child process failed with exit code $LASTEXITCODE." }
            } finally {
                foreach ($Entry in Get-ChildItem Env:) { Remove-Item -LiteralPath "Env:$($Entry.Name)" -ErrorAction SilentlyContinue }
                foreach ($Name in $SavedEnvironment.Keys) { Set-Item -LiteralPath "Env:$Name" -Value $SavedEnvironment[$Name] }
            }
        } else {
            Write-Warning 'Candidate validation was explicitly skipped. Apply only candidates from a fully trusted source.'
        }

        foreach ($TargetUpdateFolder in $TargetUpdateFolders) {

            if (Test-Path -Path $TargetUpdateFolder) {
                Write-Output "Removing folder $TargetUpdateFolder..."
                try {
                    Remove-Item -Path $TargetUpdateFolder -Force -Recurse
                } catch {
                    throw "Failed to remove folder $($TargetUpdateFolder). Error: $_"
                }
            }

            Write-Output "Updating folder $TargetUpdateFolder..."
            try {
                Copy-item -Path "$($TemporaryUpdateFolder)/$($TargetUpdateFolder)" -Destination "$($TargetUpdateFolder)" -Force -Recurse
            } catch {
                throw "Failed to copy folder $($TemporaryUpdateFolder)/$($TargetUpdateFolder) to $($TargetUpdateFolder). The local folder is now incomplete and must be restored from source control. Error: $_"
            }
        }

        # Do not execute newly downloaded module code in the updater process. In automated runs a
        # later step receives a repository token; in interactive runs the caller can still have a PAT,
        # Azure context or other credentials in its environment. Load the module in a subsequent clean
        # process/session after reviewing the applied diff.
        Write-Output 'Updated module import deferred until a subsequent clean process or session.'

        if ($TargetUpdateFolders -contains './.github/workflows') {
            Write-Host "Re-adding workflow parameters in GitHub workflows after update..."
            try {
                Update-EntraOpsRequiredWorkflowParameters -ConfigFile $ConfigFile
            } catch {
                throw "Failed to update required workflow parameters. Error: $_"
            }
        }

        $UpdateManifest = [ordered]@{
            SchemaVersion       = 1
            Repository          = $SourceRepository
            Channel             = $Source.Channel
            RequestedRef        = $Branch
            SourceCommit        = $SourceCommit
            ValidatedBeforeApply = [bool]($ValidatedSourceCommit -or -not $SkipCandidateValidation)
            ValidationIsolation  = if ($ValidatedSourceCommit) { 'SeparateJob' } elseif ($SkipCandidateValidation) { 'Skipped' } else { 'SanitizedChildProcess' }
            BrowserTestsRun     = [bool]($RunBrowserTests -or $BrowserTestsValidated)
            AppliedDateTime     = (Get-Date).ToUniversalTime().ToString('o')
            TargetUpdateFolders = @($TargetUpdateFolders)
        }
        $UpdateManifestPath = Join-Path $EntraOpsBaseFolder '.EntraOpsUpdateManifest.json'
        $UpdateManifest | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $UpdateManifestPath -Encoding utf8
    } finally {
        # A caller-supplied -PreparedCandidatePath is left in place for inspection.
        if ($OwnCandidateCheckout -and (Test-Path -Path $TemporaryUpdateFolder)) {
            Write-Output "Cleaning up temporary folder $TemporaryUpdateFolder."
            Remove-Item -Path $TemporaryUpdateFolder -Force -Recurse -ErrorAction SilentlyContinue
        }
    }
}

# SIG # Begin signature block
# MIIniAYJKoZIhvcNAQcCoIIneTCCJ3UCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCA6joO/SPuii9qj
# iiE1jL7BJXOMxdKQzu0jM4WWx3AWm6CCIDwwggXJMIIEsaADAgECAhAbtY8lKt8j
# AEkoya49fu0nMA0GCSqGSIb3DQEBDAUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
# ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy
# dGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5l
# dHdvcmsgQ0EwHhcNMjEwNTMxMDY0MzA2WhcNMjkwOTE3MDY0MzA2WjCBgDELMAkG
# A1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAl
# BgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMb
# Q2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMIICIjANBgkqhkiG9w0BAQEFAAOC
# Ag8AMIICCgKCAgEAvfl4+ObVgAxknYYblmRnPyI6HnUBfe/7XGeMycxca6mR5rlC
# 5SBLm9qbe7mZXdmbgEvXhEArJ9PoujC7Pgkap0mV7ytAJMKXx6fumyXvqAoAl4Va
# qp3cKcniNQfrcE1K1sGzVrihQTib0fsxf4/gX+GxPw+OFklg1waNGPmqJhCrKtPQ
# 0WeNG0a+RzDVLnLRxWPa52N5RH5LYySJhi40PylMUosqp8DikSiJucBb+R3Z5yet
# /5oCl8HGUJKbAiy9qbk0WQq/hEr/3/6zn+vZnuCYI+yma3cWKtvMrTscpIfcRnNe
# GWJoRVfkkIJCu0LW8GHgwaM9ZqNd9BjuiMmNF0UpmTJ1AjHuKSbIawLmtWJFfzcV
# WiNoidQ+3k4nsPBADLxNF8tNorMe0AZa3faTz1d1mfX6hhpneLO/lv403L3nUlbl
# s+V1e9dBkQXcXWnjlQ1DufyDljmVe2yAWk8TcsbXfSl6RLpSpCrVQUYJIP4ioLZb
# MI28iQzV13D4h1L92u+sUS4Hs07+0AnacO+Y+lbmbdu1V0vc5SwlFcieLnhO+Nqc
# noYsylfzGuXIkosagpZ6w7xQEmnYDlpGizrrJvojybawgb5CAKT41v4wLsfSRvbl
# jnX98sy50IdbzAYQYLuDNbdeZ95H7JlI8aShFf6tjGKOOVVPORa5sWOd/7cCAwEA
# AaOCAT4wggE6MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLahVDkCw6A/joq8
# +tT4HKbROg79MB8GA1UdIwQYMBaAFAh2zcsH/yT2xc3tu5C84oQ3RnX3MA4GA1Ud
# DwEB/wQEAwIBBjAvBgNVHR8EKDAmMCSgIqAghh5odHRwOi8vY3JsLmNlcnR1bS5w
# bC9jdG5jYS5jcmwwawYIKwYBBQUHAQEEXzBdMCgGCCsGAQUFBzABhhxodHRwOi8v
# c3ViY2Eub2NzcC1jZXJ0dW0uY29tMDEGCCsGAQUFBzAChiVodHRwOi8vcmVwb3Np
# dG9yeS5jZXJ0dW0ucGwvY3RuY2EuY2VyMDkGA1UdIAQyMDAwLgYEVR0gADAmMCQG
# CCsGAQUFBwIBFhhodHRwOi8vd3d3LmNlcnR1bS5wbC9DUFMwDQYJKoZIhvcNAQEM
# BQADggEBAFHCoVgWIhCL/IYx1MIy01z4S6Ivaj5N+KsIHu3V6PrnCA3st8YeDrJ1
# BXqxC/rXdGoABh+kzqrya33YEcARCNQOTWHFOqj6seHjmOriY/1B9ZN9DbxdkjuR
# mmW60F9MvkyNaAMQFtXx0ASKhTP5N+dbLiZpQjy6zbzUeulNndrnQ/tjUoCFBMQl
# lVXwfqefAcVbKPjgzoZwpic7Ofs4LphTZSJ1Ldf23SIikZbr3WjtP6MZl9M7JYjs
# NhI9qX7OAo0FmpKnJ25FspxihjcNpDOO16hO0EoXQ0zF8ads0h5YbBRRfopUofbv
# n3l6XYGaFpAP4bvxSgD5+d2+7arszgowggZrMIIEU6ADAgECAhBX5gfP8LabvnxC
# XoItEBa/MA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhB
# c3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNp
# Z25pbmcgMjAyMSBDQTAeFw0yNjEwMDYwODI4MjNaFw0yNzEwMDYwODI4MjJaMIGQ
# MQswCQYDVQQGEwJERTEdMBsGA1UECAwUUmhpbmVsYW5kLVBhbGF0aW5hdGUxEjAQ
# BgNVBAcMCUxhaG5zdGVpbjEeMBwGA1UECgwVT3BlbiBTb3VyY2UgRGV2ZWxvcGVy
# MS4wLAYDVQQDDCVPcGVuIFNvdXJjZSBEZXZlbG9wZXIgVGhvbWFzIE5hdW5oZWlt
# MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAphp2ljSmVsRB6gvkEq7A
# DUMENpKZiDFoAfF1ktD1nCwaVyI+bJ0ROjHwAn4iJgS+vlBDPOUIw2GLHkiqUhOg
# HSwzg6gj45GNmt6zxsKP0zPlhMB/fb0zmz7/F7e3yfKCXLfhbHuk0Es9gJ+8Wmet
# 9StVwwSE/K0MpW06GKA9nPWyE4N/ADwigDIj9rsTKJR4cve9w8G1b3zohpUc/qMr
# onab+HVw5r9b3sOBnnaXC6zvrX4fovRz1ztwfWjRjILLoFG6mW/TuK5F2ICD3Rhl
# 9R2rJWWWhzTDMsQlzvX+/SaM74q3OFpIVNdhvtmWU9pKUBRAyYMijcDqKEFGSzrc
# 8JFmGMpP5TuroWF+N21d3px2eARvW1mV0DCfFAH+Og20SH/gVW6/ltQQEkH/z/Zt
# 49ARyJrgESLOQtlMCIYSoKISdkk4ml4VUS1E/PcbzXEYj3a7m6DOxcd3WuY03UT9
# cnk3p0LMN6LeLYAZgVY+HRloZlH+kW2SkOHNuWgtXvZhAgMBAAGjggF4MIIBdDAM
# BgNVHRMBAf8EAjAAMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jY3NjYTIwMjEu
# Y3JsLmNlcnR1bS5wbC9jY3NjYTIwMjEuY3JsMHMGCCsGAQUFBwEBBGcwZTAsBggr
# BgEFBQcwAYYgaHR0cDovL2Njc2NhMjAyMS5vY3NwLWNlcnR1bS5jb20wNQYIKwYB
# BQUHMAKGKWh0dHA6Ly9yZXBvc2l0b3J5LmNlcnR1bS5wbC9jY3NjYTIwMjEuY2Vy
# MB8GA1UdIwQYMBaAFN10XUwA23ufoHTKsW73PMAywHDNMB0GA1UdDgQWBBTBvGyH
# MXj1dMbVnxuof9oP4PY7cDBLBgNVHSAERDBCMAgGBmeBDAEEATA2BgsqhGgBhvZ3
# AgUBBDAnMCUGCCsGAQUFBwIBFhlodHRwczovL3d3dy5jZXJ0dW0ucGwvQ1BTMBMG
# A1UdJQQMMAoGCCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsF
# AAOCAgEAkC165c7/r6y3VeEEpNXas9bQs6ZpKPdJffHkf9xoPi4kWvAIWGc4ocG1
# DJLb18RXiDYShDmT5sb/6I08FeipKi2DNJkuOq6yOTJ3S7+hNFIZCyd6i7WKO8ea
# P5I+FAbyJP4+5coZoMg45bUa9JoocaJCm+5n7WiCfN7/EQpClW5Trm4+ZMbp7EMN
# F1uLJgGCMnN0SsoUarp7PHlqupMxMC4Uhhe+lAP2ytcSIU81L97/qjrADbLWqICk
# 9il5iGM+aZndguq/cmfH9rJj4GRZHWnG6WwnzYD9+KgYlRI6em+/9dq+IRiXe2Bs
# thUuIaFW7U2gWw8tBTEYm1UBLHdJx+L1gjJCLs5KT/wy5wU32wZxNDqPUQejUC1x
# GvU3cKqmLgRq+yNf3gFVfzqIoggyM3U9wQvnk7nBtCkpjXS2hdx4yxzcmrlWsDHr
# z6+6/jeyQySzbYUlFmKnc4n9Mw2soHOajEua5poFARVRS5KgUBuiiQ21YFNYzWBo
# qGuECaaAI/C5rGxapMJ3dAOBnHw6NLqBet+ZXBJEccX5y89MLlOQu+jDmJP8HieR
# qDLlwfhVZnw4RY8Rus43NZBwhNlVuOUXqocHKmJhKNlekda3qsJj93eQBQOxKJcc
# w5O08q9jukpH2+yzFAj+7ll33DuNUgWptogc4Awtbx3glzcEvJQwggaCMIIEaqAD
# AgECAhAo8HfBHDa9/l90MkdwJy4DMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYT
# AlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMT
# G0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAyMSBDQTAeFw0yNjAzMTEwNzM0NTRaFw0z
# NjAyMjcwNzM0NTRaMFAxCzAJBgNVBAYTAlBMMSEwHwYDVQQKDBhBc3NlY28gRGF0
# YSBTeXN0ZW1zIFMuQS4xHjAcBgNVBAMMFUNlcnR1bSBUaW1lc3RhbXAgMjAyNjCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALi9zfBw+xI12hi2F9uNQBNO
# STkTIi13fuh3DiWybI5392bBfJw6tO7zDs7UqP/rejVf4xFTU3XNOPsuOFkP5SPF
# snWwn3VJL+NhNhsuujvYsQtaQnvNo1wk46reTgws1L8OFEdKaxgyqT4zOQx81mLw
# NZSqXNU9Rrb9oAJWJF4Mydz+C1ebu0D0+vgM3tqAQ8TU203fqgKCPqIdHloaFqH9
# eyR+8tnpmy2hnnN59ZOtmsuHeRwf5iTOhlhf0d/qqquLOSIGPgGVL1Hj5XBUox2O
# E7tQRr+l/xxNbL6OuwBO4Aa2EbuxYg37cpXv5i2/lTL4NASB/duf9W4fjA3Ro+GP
# +bC54n2OYiM3Cq8z92ejx8F5HWO2e4/75eC95B9tMw/eq7109GDyW2+2ut5Bn0o8
# MXJTERkyystWbqcnUkomA97qfiDCwvpWuOMdfTOksXe9S+xDxOJaCbiyTivgPulx
# cT+tfQTRXBr5UwtPvc+INnafOEilzVHA11tv+pHcylryxBc08cUihf/ttqkZS0bm
# x3VxQay8uohaTp0//ECA9vYGW51SKdJMJhXvKyIdBLy8WYNchTt8yRITv9Adxg9J
# qGujh+TnP1bW3aQjFtlEl7SzgNeI8OVA/CJAWWUuRT3Au9ToOpHy/flrrknhN4he
# Ew7/6ILMv4HSsj0YZ4otAgMBAAGjggFQMIIBTDB1BggrBgEFBQcBAQRpMGcwOwYI
# KwYBBQUHMAKGL2h0dHA6Ly9zdWJjYS5yZXBvc2l0b3J5LmNlcnR1bS5wbC9jdHNj
# YTIwMjEuY2VyMCgGCCsGAQUFBzABhhxodHRwOi8vc3ViY2Eub2NzcC1jZXJ0dW0u
# Y29tMB8GA1UdIwQYMBaAFL5UAi+/QGxzQ86sCSVOnkNEGu7gMAwGA1UdEwEB/wQC
# MAAwOQYDVR0fBDIwMDAuoCygKoYoaHR0cDovL3N1YmNhLmNybC5jZXJ0dW0ucGwv
# Y3RzY2EyMDIxLmNybDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8E
# BAMCB4AwIgYDVR0gBBswGTAIBgZngQwBBAIwDQYLKoRoAYb2dwIFAQswHQYDVR0O
# BBYEFCM5aiirmhKnpKfyH/lFmr+N/oIDMA0GCSqGSIb3DQEBDAUAA4ICAQBm/pOb
# rAveTqYFPCSthxNVwBHTW4TfuBQY2KGCdMlH6ALjVPYf2XARNGMTXScR0JQ2/c2L
# xLpoHHhRwxFf3d933DhFS165rYj6iPSQKm41rc9AMpTCjMdmai1aK9o870pOzTzL
# RhWFVIxm+5Qf+t4V5z14tPoUsAWdfRKD1Zzvzfe5AHlE9rxOZcGROiULxs3Edf7Z
# J8RZI0jzD9juj2oEX2XS7BVKuNCK1W0h1mjapv028yqo8UtZh5/1Ib48Yyp88BDY
# Shh5PSGUUuS5tYXVfcduIPBe3PdNTYRYdT5VNxkwLgjMzIcr/6SH2fejFJDjnCxj
# vXLuarErJg/IdI+hXdGIBDVOGv1zrkF4ktoQvFZIp5DIAYh0GwyUhc87qqn5UaYT
# j2+iyiBDSNh7aGCrkuAnqg7Qh7frhX+QhMGeJ9SpLpnG76qN85hLyjvYR6gRYiLT
# j8G4fxjqV400/buPw0rBo9yJZyq/8cGdCOLPOYf9qpefTcrZKeO9pg+UJHx8UABb
# aTqizRxm8sUSEycccCCFhIit3AI/3wGuSOADeiA676NcQ7+dsP04YvzvdN7pTZNy
# g672WpBDJdg0eItHl4yomvNeIOWh1qs4QqOW6TI8Ocsi4uSDTLorxLUDnBTwKQzz
# pxd1YUctEgRh32R0J9FkFkeEruJU94RljFr1uDCCBrkwggShoAMCAQICEQCZo4AK
# JlU7ZavcboSms+o5MA0GCSqGSIb3DQEBDAUAMIGAMQswCQYDVQQGEwJQTDEiMCAG
# A1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVt
# IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3Rl
# ZCBOZXR3b3JrIENBIDIwHhcNMjEwNTE5MDUzMjE4WhcNMzYwNTE4MDUzMjE4WjBW
# MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu
# MSQwIgYDVQQDExtDZXJ0dW0gQ29kZSBTaWduaW5nIDIwMjEgQ0EwggIiMA0GCSqG
# SIb3DQEBAQUAA4ICDwAwggIKAoICAQCdI88EMCM7wUYs5zNzPmNdenW6vlxNur3r
# Lfi+5OZ+U3iZIB+AspO+CC/bj+taJUbMbFP1gQBJUzDUCPx7BNLgid1TyztVLn52
# NKgxxu8gpyTr6EjWyGzKU/gnIu+bHAse1LCitX3CaOE13rbuHbtrxF2tPU8f253Q
# gX6eO8yTbGps1Mg+yda3DcTsOYOhSYNCJiL+5wnjZ9weoGRtvFgMHtJg6i671OPX
# IciiHO4Lwo2p9xh/tnj+JmCQEn5QU0NxzrOiRna4kjFaA9ZcwSaG7WAxeC/xoZSx
# F1oK1UPZtKVt+yrsGKqWONoK6f5EmBOAVEK2y4ATDSkb34UD7JA32f+Rm0wsr5aj
# zftDhA5mBipVZDjHpwzv8bTKzCDUSUuUmPo1govD0RwFcTtMXcfJtm1i+P2UNXad
# PyYVKRxKQATHN3imsfBiNRdN5kiVVeqP55piqgxOkyt+HkwIA4gbmSc3hD8ke66t
# 9MjlcNg73rZZlrLHsAIV/nJ0mmgSjBI/TthoGJDydekOQ2tQD2Dup/+sKQptalDl
# ui59SerVSJg8gAeV7N/ia4mrGoiez+SqV3olVfxyLFt3o/OQOnBmjhKUANoKLYlK
# mUpKEFI0PfoT8Q1W/y6s9LTI6ekbi0igEbFUIBE8KDUGfIwnisEkBw5KcBZ3XwnH
# mfznwlKo8QIDAQABo4IBVTCCAVEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
# 3XRdTADbe5+gdMqxbvc8wDLAcM0wHwYDVR0jBBgwFoAUtqFUOQLDoD+Oirz61Pgc
# ptE6Dv0wDgYDVR0PAQH/BAQDAgEGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMDAGA1Ud
# HwQpMCcwJaAjoCGGH2h0dHA6Ly9jcmwuY2VydHVtLnBsL2N0bmNhMi5jcmwwbAYI
# KwYBBQUHAQEEYDBeMCgGCCsGAQUFBzABhhxodHRwOi8vc3ViY2Eub2NzcC1jZXJ0
# dW0uY29tMDIGCCsGAQUFBzAChiZodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwv
# Y3RuY2EyLmNlcjA5BgNVHSAEMjAwMC4GBFUdIAAwJjAkBggrBgEFBQcCARYYaHR0
# cDovL3d3dy5jZXJ0dW0ucGwvQ1BTMA0GCSqGSIb3DQEBDAUAA4ICAQB1iFgP5Y9Q
# KJpTnxDsQ/z0O23JmoZifZdEOEmQvo/79PQg9nLF/GJe6ZiUBEyDBHMtFRK0mXj3
# Qv3gL0sYXe+PPMfwmreJHvgFGWQ7XwnfMh2YIpBrkvJnjwh8gIlNlUl4KENTK5DL
# qsYPEtRQCw7R6p4s2EtWyDDr/M58iY2UBEqfUU/ujR9NuPyKk0bEcEi62JGxauFY
# zZ/yld13fHaZskIoq2XazjaD0pQkcQiIueL0HKiohS6XgZuUtCKA7S6CHttZEsOb
# QJ1j2s0urIDdqF7xaXFVaTHKtAuMfwi0jXtF3JJphrJfc+FFILgCbX/uYBPBlbBI
# P4Ht4xxk2GmfzMn7oxPITpigQFJFWuzTMUUgdRHTxaTSKRJ/6Uh7ki/pFjf9sUAS
# WgxT69QF9Ki4JF5nBIujxZ2sOU9e1HSCJwOfK07t5nnzbs1LbHuAIGJsRJiQ6HX/
# DW1XFOlXY1rc9HufFhWU+7Uk+hFkJsfzqBz3pRO+5aI6u5abI4Qws4YaeJH7H7M8
# X/YNoaArZbV4Ql+jarKsE0+8XvC4DJB+IVcvC9Ydqahi09mjQse4fxfef0L7E3hh
# o2O3bLDM6v60rIRUCi2fJT2/IRU5ohgyTch4GuYWefSBsp5NPJh4QRTP9DC3gc5Q
# EKtbrTY0Ka87Web7/zScvLmvQBm8JDFpDjCCBrkwggShoAMCAQICEQDn/2nHOzXO
# S5Em2HR8aKWHMA0GCSqGSIb3DQEBDAUAMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UE
# ChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
# cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBO
# ZXR3b3JrIENBIDIwHhcNMjEwNTE5MDUzMjA3WhcNMzYwNTE4MDUzMjA3WjBWMQsw
# CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQw
# IgYDVQQDExtDZXJ0dW0gVGltZXN0YW1waW5nIDIwMjEgQ0EwggIiMA0GCSqGSIb3
# DQEBAQUAA4ICDwAwggIKAoICAQDpEh8ENe25XXrFppVBvoplf0530W0lddNmjtv4
# YSh/f7eDQKFaIqc7tHj7ox+u8vIsJZlroakUeMS3i3T8aJRC+eQs4FF0GqvkM6+W
# ZO8kmzZfxmZaBYmMLs8FktgFYCzywmXeQ1fEExflee2OpbHVk665eXRHjH7MYZIz
# Nnjl2m8Hy8ulB9mR8wL/W0v0pjKNT6G0sfrx1kk+3OGosFUb7yWNnVkWKU4qSxLv
# 16kJ6oVJ4BSbZ4xMak6JLeB8szrK9vwGDpvGDnKCUMYL3NuviwH1x4gZG0JAXU3x
# 2pOAz91JWKJSAmRy/l0s0l5bEYKolg+DMqVhlOANd8Yh5mkQWaMEvBRE/kAGzIqg
# WhwzN2OsKIVtO8mf5sPWSrvyplSABAYa13rMYnzwfg08nljZHghquCJYCa/xHK9a
# cev9UD7Y+usr15d7mrszzxhF1JOr1Mpup2chNSBlyOObhlSO16rwrffVrg/SzaKf
# SndS5swRhr8bnDqNJY9TNyEYvBYpgF95K7p0g4LguR4A++Z1nFIHWVY5v0fNVZmg
# zxD9uVo/gta3onGOQj3JCxgYx0KrCXu4yc9QiVwTFLWbNdHFSjBCt5/8Q9pLuRhV
# ocdCunhcHudMS1CGQ/Rn0+7P+fzMgWdRKfEOh/hjLrnQ8BdJiYrZNxvIOhM2aa3z
# EDHNwwIDAQABo4IBVTCCAVEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUvlQC
# L79AbHNDzqwJJU6eQ0Qa7uAwHwYDVR0jBBgwFoAUtqFUOQLDoD+Oirz61PgcptE6
# Dv0wDgYDVR0PAQH/BAQDAgEGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMDAGA1UdHwQp
# MCcwJaAjoCGGH2h0dHA6Ly9jcmwuY2VydHVtLnBsL2N0bmNhMi5jcmwwbAYIKwYB
# BQUHAQEEYDBeMCgGCCsGAQUFBzABhhxodHRwOi8vc3ViY2Eub2NzcC1jZXJ0dW0u
# Y29tMDIGCCsGAQUFBzAChiZodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwvY3Ru
# Y2EyLmNlcjA5BgNVHSAEMjAwMC4GBFUdIAAwJjAkBggrBgEFBQcCARYYaHR0cDov
# L3d3dy5jZXJ0dW0ucGwvQ1BTMA0GCSqGSIb3DQEBDAUAA4ICAQC4k1l3yUwV/ZQH
# CKCneqAs8EGTnwEUJLdDpokN/dMhKjK0rR5qX8nIIHzxpQR3TAw2IRw1Uxsr2Pli
# G3bCFqSdQTUbfaTq6V3vBzEebDru9QFjqlKnxCF2h1jhLNFFplbPJiW+JSnJTh1f
# KEqEdKdxgl9rVTvlxfEJ7exOn25MGbd/wGPwuSmMxRJVO0wnqgS7kmoJjNF9zqee
# hFSDDP8ZVkWg4EZ2tIS0M3uZmByRr+1Lkwjjt8AtW83mVnZTyTsOb+FNfwJY7DS4
# FmWhkRbgcHRetreoTirPOr/ozyDKhT8MTSTf6Lttg6s6T/u08mDWw6HK04ZRDfQ9
# sb77QV8mKgO44WGP31vXnVKoWVJpFBjPvjL8/Zck/5wXX2iqjOaLStFOR/IQki+E
# hn4zlcgVm22ZVCBPF+l8nAwUUShCtKuSU7GmZLKCmmxQMkSiWILTm8EtVD6AxnJh
# oq8EnhjEEyUoflkeRF2WhFiVQOmWTwZRr44IxWGkNJC6tTorW5rl2Zl+2e9JLPYf
# 3pStAPMDoPKIjVXd6NW2+fZrNUBeDo2eOa5Fn7Brs/HLQff5Xgris5MeUbdVgDrF
# 8uxO6cLPvZPo63j62SsNg55pTWk9fUIF9iPoRbb4QurjoY/woI1RAOKtYtTic6aA
# Jq3u83RIPpGXBSJKwx4KJAOZnCDCtTGCBqIwggaeAgEBMGowVjELMAkGA1UEBhMC
# UEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEkMCIGA1UEAxMb
# Q2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBAhBX5gfP8LabvnxCXoItEBa/MA0G
# CWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZI
# hvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcC
# ARUwLwYJKoZIhvcNAQkEMSIEIKw469YxfHDIvm5I/JyVMmMfQ939CQTiYkDLH0HW
# QKiXMA0GCSqGSIb3DQEBAQUABIIBgCvyLnA/86pVW37lBB65GCleI3h+/zDGBakd
# EX+G19ZapBEP49TxwLbQGAklb+BaCebXQUsvytlpjOOZ+CAQSYRCmsTMZzuo69XQ
# U7q1T/QYgB0qYCFRKZsofpbUXmTru8frmRnn2Ayp203QmqDkJxWZW2ghSYCVZcUB
# +QGsu4uoFc00CGWexvrmM901Ku5ztD2w4wrM0gqd1uSw5pBbqxdrr3MM1mu8/AEd
# gzRUD6c9xTWAzd4wWos6QFC7z7B7r83u1m/Nd9VI3khIz+eNhXwC5Snon1sz9Bsf
# c3s6pTAhPnWeS82d8ixTgtM0IR9AYwxbf4b4LJUq7ezA/trAhIA5OMoQAFkKQT7t
# 10ZGyHhpa51thMujjfpQyxqbU+36wFC1yll4fCxN1/Ju713zaaZLmDTl9f8SRXP9
# IHyZnlIrUtcA2rpGj5BY3J5X0+Oghq5C8quJQVrHRwT4JmHh3CwRI2tfB3rG+yrG
# 9j2znO4jJ3IRMSuTu9bc9wFnSHtJe6GCBAIwggP+BgkqhkiG9w0BCQYxggPvMIID
# 6wIBATBqMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0
# ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAyMSBDQQIQ
# KPB3wRw2vf5fdDJHcCcuAzANBglghkgBZQMEAgIFAKCCAVYwGgYJKoZIhvcNAQkD
# MQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNjEwMTMwOTQwNTNaMDcG
# CyqGSIb3DQEJEAIvMSgwJjAkMCIEIIW+kOEK0kONfMkotq9IsJqyCBd87PiwEmxY
# 05EFJcQ8MD8GCSqGSIb3DQEJBDEyBDBKFg8H7WPUt7txZaetz5kTW3Uv87I/a8FQ
# OE1s2rKzhnubQoTHDQuJi3VMAgWWKnQwgZ8GCyqGSIb3DQEJEAIMMYGPMIGMMIGJ
# MIGGBBRXFGhBDKha80JO+RZKUTYQ9NONmDBuMFqkWDBWMQswCQYDVQQGEwJQTDEh
# MB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQDExtDZXJ0
# dW0gVGltZXN0YW1waW5nIDIwMjEgQ0ECECjwd8EcNr3+X3QyR3AnLgMwDQYJKoZI
# hvcNAQEBBQAEggIAZ/38qhNfzsD/wqBC09IvR6Gjush1V2w4zS+BeqnGom3EqKtE
# PS7lNG9l3efXuf1rQl8tPPZ6y2aZ8IsdQkDH3nlrNrJsdd/xVzaDapw9istMA1Ay
# qqlxbm+SQ36EG1qcHAHLGfeWcF0W/+P1aVEgKxKTdMlYc9okyKcsxg7f7ShyZgBY
# 8gDsYwePwZQafl6HyXU/2I5CdOdCgE+yqRkESezQZklnyhFYLeHjCOi7bks+AL72
# hdHYzf+ydVW5Uv+JJV1TuJbzBx3UPO4hnKmodKSv3BbcA2U9yqM3MVHev178J0Xt
# wrhUBsQmEru7qb0mzzPIzxmMDp3k2oC7Q0CXBzn9zwre54e35pbTgg0hil9O54CR
# wqaEabzvRECTLyC59Vaw1loEjm8CxQW6KlCW70Oe9iRz31NKE11Cs7z3x2AhAth7
# p4kHTEPYXEyCtLe24vJW1scNRgSrvcXje2PddaXR3mJA22/8MJ8199wMNQ9OB66Q
# q/vqy3USuhnkcPKXmB3df+3GXmVSpXNvjfhegHbmbQGqTEWcb5sKq/7agWwGQe6i
# hvnmIPm39MMIjRJbhYP73tZUBveLol8uprcJ/XCmfs4J/J0m+Uwlzn2x684xFeMU
# lBuXr1HCHHT9CYGdkdGbZe8edqJHVd3+eDgXqeCXlIOa2q9s7ottmXM/R+M=
# SIG # End signature block