Engines/Terraform/Invoke-AvmTerraformCheckPolicy.ps1

function Invoke-AvmTerraformPolicyExample {
    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory)]
        $Example,

        [Parameter(Mandatory)]
        $Options
    )

    Set-StrictMode -Version 3.0
    $ErrorActionPreference = 'Stop'

    $envVars = @{}
    $primaryError = $null
    $issues = [System.Collections.Generic.List[object]]::new()
    $evaluated = 0

    try {
        $Example.CleanupStarted = $true
        Invoke-AvmScriptHook `
            -HookPath (Join-Path $Example.StagedPath 'pre.ps1') `
            -WorkingDirectory $Example.StagedPath `
            -Label ("policy {0} pre.ps1" -f $Example.Name)

        $envVars = ConvertFrom-AvmDotEnv -Path (Join-Path $Example.StagedPath '.env')
        $terraformEnv = Get-AvmTerraformPolicyEnvironment -StageRoot $Example.StageRoot -Environment $envVars

        $terraformLock = Lock-AvmTerraformPluginCache `
            -WorkingDirectory $Example.StagedPath `
            -EnvVars $terraformEnv
        try {
            Initialize-AvmTerraformPolicyStage `
                -TerraformPath $Options.TerraformPath `
                -ConftestPath $Options.ConftestPath `
                -WorkingDirectory $Example.StagedPath `
                -StageRoot $Example.StageRoot `
                -EnvVars $terraformEnv

            $null = Invoke-AvmProcess `
                -FilePath $Options.TerraformPath `
                -ArgumentList @('plan', '-out=tfplan', '-input=false', '-no-color') `
                -WorkingDirectory $Example.StagedPath `
                -EnvVars $terraformEnv `
                -Label ("terraform plan ({0})" -f $Example.Name)

            $showResult = Invoke-AvmProcess `
                -FilePath $Options.TerraformPath `
                -ArgumentList @('show', '-json', 'tfplan') `
                -WorkingDirectory $Example.StagedPath `
                -EnvVars $terraformEnv `
                -Label ("terraform show ({0})" -f $Example.Name)
        }
        finally {
            if ($null -ne $terraformLock) {
                $terraformLock.Dispose()
            }
        }

        $planJsonPath = Join-Path $Example.StagedPath 'tfplan.json'
        [System.IO.File]::WriteAllText(
            $planJsonPath,
            [string]$showResult.StdOut,
            [System.Text.UTF8Encoding]::new($false))

        $localExceptions = Join-Path $Example.StagedPath 'exceptions'
        $policyRuns = @(
            [pscustomobject]@{ Name = 'APRL'; Path = $Options.AprlPath }
            [pscustomobject]@{ Name = 'AVMSEC'; Path = $Options.AvmsecPath }
        )

        foreach ($policyRun in $policyRuns) {
            $arguments = [System.Collections.Generic.List[string]]::new()
            $arguments.Add('test')
            $arguments.Add('--all-namespaces')
            $arguments.Add('--policy')
            $arguments.Add([string]$policyRun.Path)
            $arguments.Add('--policy')
            $arguments.Add($Options.DefaultExceptions)
            if (Test-Path -LiteralPath $localExceptions -PathType Container) {
                $arguments.Add('--policy')
                $arguments.Add($localExceptions)
            }
            $arguments.Add('--output')
            $arguments.Add('json')
            $arguments.Add('tfplan.json')

            $policyResult = Invoke-AvmProcess `
                -FilePath $Options.ConftestPath `
                -ArgumentList $arguments.ToArray() `
                -WorkingDirectory $Example.StagedPath `
                -EnvVars $envVars `
                -Label ("conftest {0} ({1})" -f $policyRun.Name, $Example.Name) `
                -IgnoreExitCode

            $parsed = ConvertFrom-AvmPolicyResult `
                -Result $policyResult `
                -ExamplePath $Example.RelativePath `
                -PolicyName $policyRun.Name
            $evaluated += $parsed.Evaluated
            foreach ($issue in $parsed.Issues) {
                $issues.Add($issue)
            }
        }
    }
    catch {
        $primaryError = $_
    }

    try {
        Invoke-AvmScriptHook `
            -HookPath (Join-Path $Example.StagedPath 'post.ps1') `
            -WorkingDirectory $Example.StagedPath `
            -EnvVars $envVars `
            -Label ("policy {0} post.ps1" -f $Example.Name)
        $Example.CleanupCompleted = $true
    }
    catch {
        if ($null -eq $primaryError) {
            throw
        }
        $primaryError.Exception.Data['AvmPolicyPostError'] = $_
        Write-AvmLog `
            -Level Warning `
            -File (Join-Path $Example.RelativePath 'post.ps1') `
            -Message ("Policy post hook also failed ({0}); preserving the primary error and attaching the post error as AvmPolicyPostError." -f $_.Exception.GetType().Name)
    }

    if ($null -ne $primaryError) {
        throw $primaryError
    }

    return [pscustomobject]@{
        Evaluated = $evaluated
        Issues    = $issues.ToArray()
    }
}

function Get-AvmConftestOverrideWarning {
    [CmdletBinding()]
    [OutputType([object[]])]
    param(
        [Parameter(Mandatory)]
        [string] $Root,

        [Parameter(Mandatory)]
        [string[]] $ExamplePath
    )

    $rootFull = (Resolve-Path -LiteralPath $Root).ProviderPath
    $warnings = [System.Collections.Generic.List[object]]::new()
    $seen = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)

    foreach ($example in $ExamplePath) {
        $exceptionsPath = Join-Path $example 'exceptions'
        if (-not (Test-Path -LiteralPath $exceptionsPath -PathType Container)) {
            continue
        }

        $exceptionFiles = @(
            Get-ChildItem `
                -LiteralPath $exceptionsPath `
                -Filter '*.rego' `
                -File `
                -Recurse `
                -ErrorAction SilentlyContinue |
                Sort-Object FullName
        )
        foreach ($exceptionFile in $exceptionFiles) {
            $file = [System.IO.Path]::GetRelativePath($rootFull, $exceptionFile.FullName).Replace('\', '/')
            $text = [System.IO.File]::ReadAllText($exceptionFile.FullName)
            $rules = @(
                @(
                    foreach ($exceptionMatch in [regex]::Matches($text, '(?ms)\bexception\s+contains\s+rules\s+if\s*\{(?<block>[^{}]*)\}')) {
                        foreach ($ruleListMatch in [regex]::Matches($exceptionMatch.Groups['block'].Value, '(?ms)\brules\s*(?::=|=)\s*\[(?<body>.*?)\]')) {
                            foreach ($ruleMatch in [regex]::Matches($ruleListMatch.Groups['body'].Value, '["''](?<rule>[^"'']+)["'']')) {
                                [string]$ruleMatch.Groups['rule'].Value
                            }
                        }
                    }
                ) | Select-Object -Unique
            )

            if ($rules.Count -gt 0) {
                foreach ($rule in $rules) {
                    $key = "$file`0$rule"
                    if (-not $seen.Add($key)) {
                        continue
                    }
                    $warnings.Add([pscustomobject][ordered]@{
                            File    = $file
                            Rule    = $rule
                            Message = ("Conftest override exempts rule '{0}'." -f $rule)
                        })
                }
            }
            elseif ($text -cmatch '\bexception\s+contains\s+rules\s+if\b') {
                $key = "$file`0"
                if ($seen.Add($key)) {
                    $warnings.Add([pscustomobject][ordered]@{
                            File    = $file
                            Rule    = ''
                            Message = 'Conftest override file found, but no exempted rules could be parsed.'
                        })
                }
            }
        }
    }

    return $warnings.ToArray()
}

function Invoke-AvmTerraformCheckPolicy {
    <#
    .SYNOPSIS
        Evaluate Terraform examples against the pinned APRL and AVMSEC policies.

    .DESCRIPTION
        Implements the legacy AVM pr-check policy lifecycle without mutating the
        repository. The module is copied beneath the AVM cache, then every direct
        examples/* directory is evaluated independently with bounded parallelism:

          - examples carrying .e2eignore are skipped
          - pre.ps1 runs when present; pre.sh is rejected with migration guidance
          - .env is loaded into Terraform and Conftest subprocesses
          - terraform init, plan, and show produce a plan-JSON input
          - APRL and AVMSEC run separately with all namespaces enabled
          - the pinned AVMSEC exemptions and that example's local exceptions/
            directory are included in both evaluations
          - post.ps1 runs after the example; post.sh is rejected likewise

        The staging directory is deliberately beneath the policy bundle cache.
        Conftest strips the drive letter from --policy paths on Windows;
        keeping the working tree and bundles on one volume preserves resolution.
        If any example's post hook fails or cleanup is interrupted, the staging
        tree is retained in place for recovery. Diagnostics identify its path
        without printing state, plans, environment values, or hook errors.

        Conftest output is captured as JSON rather than streamed. The legacy
        command used --quiet; omitting that switch here has the same user-visible
        silence while retaining success records needed for the Evaluated count.

    .PARAMETER Context
        Terraform module context produced by Get-AvmModuleContext.

    .PARAMETER AllowPathFallback
        Allow Terraform and Conftest to resolve from PATH.

    .PARAMETER ThrottleLimit
        Maximum number of independent examples to evaluate at once. Defaults to
        one for direct engine calls.

    .OUTPUTS
        A Terraform engine result with Status, Evaluated, and Issues.
    #>

    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory)]
        $Context,

        [switch] $AllowPathFallback,

        [ValidateRange(1, 32)]
        [int] $ThrottleLimit = 1
    )

    Set-StrictMode -Version 3.0
    $ErrorActionPreference = 'Stop'

    if ($Context.Ecosystem -ne 'terraform') {
        throw [System.ArgumentException]::new(
            "Invoke-AvmTerraformCheckPolicy requires a terraform context (got Ecosystem='$($Context.Ecosystem)').")
    }

    $conftest = Resolve-AvmTool -Name 'conftest' -ModuleRoot $Context.Root -AllowPathFallback:$AllowPathFallback
    $terraform = Resolve-AvmTool -Name 'terraform' -ModuleRoot $Context.Root -AllowPathFallback:$AllowPathFallback
    $aprlAsset = Resolve-AvmPolicyBundle -Name 'avm-policy-aprl'
    $avmsecAsset = Resolve-AvmPolicyBundle -Name 'avm-policy-avmsec'

    $defaultExceptionSource = Join-Path $avmsecAsset.Path 'avm_exceptions.rego.bak'
    if (-not (Test-Path -LiteralPath $defaultExceptionSource -PathType Leaf)) {
        throw [AvmConfigurationException]::new(
            "The pinned AVMSEC bundle does not contain the default exemption policy: '$defaultExceptionSource'.")
    }

    $examplesRoot = Join-Path $Context.Root 'examples'
    $examplePaths = @()
    if (Test-Path -LiteralPath $examplesRoot -PathType Container) {
        $examplePaths = @(Get-ChildItem -LiteralPath $examplesRoot -Directory -ErrorAction Stop |
                ForEach-Object FullName)
        [System.Array]::Sort($examplePaths, [System.StringComparer]::Ordinal)
    }

    $activeExamples = @($examplePaths | Where-Object {
            -not (Test-Path -LiteralPath (Join-Path $_ '.e2eignore') -PathType Leaf)
        })
    if ($activeExamples.Count -eq 0) {
        return [pscustomobject][ordered]@{
            Engine     = 'terraform'
            Tool       = ('{0}/{1}' -f $conftest.Name, $conftest.Version)
            ToolPath   = $conftest.Path
            ToolSource = $conftest.Source
            Status     = 'skipped'
            Evaluated  = 0
            Issues     = @()
        }
    }

    foreach ($warning in (Get-AvmConftestOverrideWarning -Root $Context.Root -ExamplePath $activeExamples)) {
        Write-AvmLog `
            -Message $warning.Message `
            -Level Warning `
            -File $warning.File
    }

    $shellHooks = [System.Collections.Generic.List[string]]::new()
    foreach ($sourceExample in $activeExamples) {
        $exampleName = Split-Path -Path $sourceExample -Leaf
        foreach ($hookName in @('pre.sh', 'post.sh')) {
            if (Test-Path -LiteralPath (Join-Path $sourceExample $hookName) -PathType Leaf) {
                $shellHooks.Add(('examples/{0}/{1}' -f $exampleName, $hookName))
            }
        }
    }
    if ($shellHooks.Count -gt 0) {
        throw [AvmConfigurationException]::new(
            ("The terraform policy engine runs PowerShell hooks only. Refactor these shell hooks to '.ps1': {0}" -f ($shellHooks -join ', ')))
    }

    $stageParent = Join-Path (Get-AvmFolder -Kind Cache) 'policy-stage'
    $stageRoot = Join-Path $stageParent ('avm-policy-' + [guid]::NewGuid().ToString('N'))
    $issues = [System.Collections.Generic.List[object]]::new()
    $evaluated = 0
    $streamOutput = Test-AvmVerboseEnabled
    $effectiveThrottle = if ($streamOutput) { 1 } else { $ThrottleLimit }
    $examples = [System.Collections.Generic.List[object]]::new()
    $policyError = $null

    try {
        $defaultExceptions = Join-Path `
            -Path $stageRoot `
            -ChildPath 'policy' `
            -AdditionalChildPath 'default_exceptions'
        $null = New-Item -ItemType Directory -Path $defaultExceptions -Force -ErrorAction Stop
        Copy-Item `
            -LiteralPath $defaultExceptionSource `
            -Destination (Join-Path $defaultExceptions 'avm_exceptions.rego') `
            -Force `
            -ErrorAction Stop

        for ($exampleIndex = 0; $exampleIndex -lt $activeExamples.Count; $exampleIndex++) {
            $sourceExample = $activeExamples[$exampleIndex]
            $relativeExample = [System.IO.Path]::GetRelativePath($Context.Root, $sourceExample)
            $caseRoot = Join-Path $stageRoot ([string]$exampleIndex)
            $moduleStage = Join-Path $caseRoot 'module'
            Copy-AvmTerraformModuleTree `
                -SourceRoot $Context.Root `
                -DestinationRoot $moduleStage `
                -IncludeDependencyLocks
            $stagedExample = Join-Path $moduleStage $relativeExample
            $null = Copy-AvmTerraformModuleCache `
                -SourceWorkingDirectory $sourceExample `
                -DestinationWorkingDirectory $stagedExample `
                -DestinationDataDirectory (Join-Path $caseRoot 'data')
            $exampleName = Split-Path -Path $sourceExample -Leaf
            Write-AvmLog `
                -Level Info `
                -Message ("policy: example {0}/{1} = {2}" -f ($exampleIndex + 1), $activeExamples.Count, $exampleName) |
                Out-Null
            $examples.Add([pscustomobject]@{
                    Name             = $exampleName
                    RelativePath     = $relativeExample
                    StagedPath       = $stagedExample
                    StageRoot        = $caseRoot
                    CleanupStarted   = $false
                    CleanupCompleted = $false
                })
        }

        Write-AvmLog `
            -Level Verbose `
            -Message ("policy: processing examples with {0} worker(s)" -f $effectiveThrottle) |
            Out-Null
        $options = [pscustomobject]@{
            TerraformPath     = $terraform.Path
            ConftestPath      = $conftest.Path
            AprlPath          = $aprlAsset.Path
            AvmsecPath        = $avmsecAsset.Path
            DefaultExceptions = $defaultExceptions
        }
        $exampleResults = @(
            Invoke-AvmParallel `
                -InputObject $examples.ToArray() `
                -FunctionName 'Invoke-AvmTerraformPolicyExample' `
                -Argument $options `
                -ThrottleLimit $effectiveThrottle
        )
        foreach ($exampleResult in $exampleResults) {
            $evaluated += $exampleResult.Evaluated
            foreach ($issue in $exampleResult.Issues) {
                $issues.Add($issue)
            }
        }
    }
    catch {
        $policyError = $_
        throw
    }
    finally {
        if (Test-Path -LiteralPath $stageRoot) {
            if (@($examples | Where-Object { $_.CleanupStarted -and -not $_.CleanupCompleted }).Count -gt 0) {
                if ($null -ne $policyError) {
                    $policyError.Exception.Data['AvmPolicyStagePath'] = $stageRoot
                }
                Write-AvmLog `
                    -Level Warning `
                    -Message ("Policy cleanup is incomplete. Recovery staging is retained at '{0}'. It may contain sensitive state, plans, and environment files; do not upload it. Recover resources before manually removing this directory." -f $stageRoot)
            }
            else {
                try {
                    Remove-Item `
                        -LiteralPath $stageRoot `
                        -Recurse `
                        -Force `
                        -ErrorAction Stop `
                        -ProgressAction SilentlyContinue
                }
                catch {
                    if ($null -eq $policyError) {
                        $_.Exception.Data['AvmPolicyStagePath'] = $stageRoot
                        Write-AvmLog `
                            -Level Warning `
                            -Message ("Policy staging removal failed ({0}). Remaining staging is at '{1}'; do not upload it." -f $_.Exception.GetType().Name, $stageRoot)
                        throw
                    }
                    $policyError.Exception.Data['AvmPolicyStageCleanupError'] = $_
                    $policyError.Exception.Data['AvmPolicyStagePath'] = $stageRoot
                    Write-AvmLog `
                        -Level Warning `
                        -Message ("Policy staging removal also failed ({0}); preserving the primary error. Remaining staging is at '{1}'; do not upload it." -f $_.Exception.GetType().Name, $stageRoot)
                }
            }
        }
    }

    $status = if (@($issues | Where-Object { $_.Severity -eq 'error' }).Count -gt 0) { 'fail' } else { 'pass' }
    return [pscustomobject][ordered]@{
        Engine     = 'terraform'
        Tool       = ('{0}/{1}' -f $conftest.Name, $conftest.Version)
        ToolPath   = $conftest.Path
        ToolSource = $conftest.Source
        Status     = $status
        Evaluated  = $evaluated
        Issues     = $issues.ToArray()
    }
}

function ConvertFrom-AvmPolicyResult {
    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory)]
        $Result,

        [Parameter(Mandatory)]
        [string] $ExamplePath,

        [Parameter(Mandatory)]
        [string] $PolicyName
    )

    if ($Result.ExitCode -notin @(0, 1)) {
        $summary = "conftest $PolicyName exited with code $($Result.ExitCode)."
        $message = Add-AvmProcessFailureDetail `
            -Message $summary `
            -StdOut $Result.StdOut `
            -StdErr $Result.StdErr
        if ($message -ceq $summary) {
            $message += [Environment]::NewLine + ' conftest produced no diagnostic.'
        }
        throw [AvmProcessException]::new(
            $message)
    }

    $payload = if ($Result.StdOut) { $Result.StdOut.Trim() } else { '' }
    if ($Result.ExitCode -eq 1 -and [string]::IsNullOrWhiteSpace($payload)) {
        $summary = "conftest $PolicyName exited before evaluating a policy."
        $message = Add-AvmProcessFailureDetail `
            -Message $summary `
            -StdOut $Result.StdOut `
            -StdErr $Result.StdErr
        if ($message -ceq $summary) {
            $message += [Environment]::NewLine + ' conftest produced no result.'
        }
        throw [AvmProcessException]::new(
            $message)
    }

    $records = @()
    if (-not [string]::IsNullOrWhiteSpace($payload)) {
        try {
            $records = @($payload | ConvertFrom-Json -ErrorAction Stop)
        }
        catch {
            throw [AvmProcessException]::new(
                "Could not parse conftest $PolicyName JSON output: $($_.Exception.Message)")
        }
    }

    $issues = [System.Collections.Generic.List[object]]::new()
    $evaluated = 0
    $issueFile = [System.IO.Path]::Combine($ExamplePath, 'tfplan.json').Replace('\', '/')
    foreach ($record in $records) {
        if (-not $record) { continue }
        $namespace = if ($record.PSObject.Properties['namespace']) {
            [string]$record.namespace
        }
        else {
            $PolicyName.ToLowerInvariant()
        }

        if ($record.PSObject.Properties['successes']) {
            $evaluated += [int]$record.successes
        }
        foreach ($bucket in @('failures', 'warnings', 'exceptions')) {
            if ($record.PSObject.Properties[$bucket] -and $record.$bucket) {
                $evaluated += @($record.$bucket).Count
            }
        }

        foreach ($bucket in @(
                [pscustomobject]@{ Name = 'failures'; Severity = 'error' }
                [pscustomobject]@{ Name = 'warnings'; Severity = 'warning' }
            )) {
            if (-not $record.PSObject.Properties[$bucket.Name] -or -not $record.($bucket.Name)) {
                continue
            }
            foreach ($finding in @($record.($bucket.Name))) {
                $message = if ($finding.PSObject.Properties['msg']) { [string]$finding.msg } else { '' }
                $issues.Add([pscustomobject][ordered]@{
                        File     = $issueFile
                        Line     = 0
                        Column   = 0
                        Severity = $bucket.Severity
                        Code     = $namespace
                        Message  = $message
                    })
            }
        }
    }

    return [pscustomobject][ordered]@{
        Evaluated = $evaluated
        Issues    = $issues.ToArray()
    }
}

# SIG # Begin signature block
# MIInQQYJKoZIhvcNAQcCoIInMjCCJy4CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAMHAcQr9XmEQUD
# hQ5+Al95qkqA/I5trqZoATyLPaqb9qCCDLowggX1MIID3aADAgECAhMzAAACHU0Z
# yE7XD1dIAAAAAAIdMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD
# b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQzWhcNMjcwNDE1MTg1
# OTQzWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD
# VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB
# DwAwggEKAoIBAQDQvewXxx9gZZFC6Ys1WBay8BJ8kGA4JQnH5CMafqOASlTpK9H8
# o5ZXTXt0caVQTNMUPt445wXYD+dFtaKWTwDn1I52oUSrC9vJin1Gsqt+zyKJL5Dg
# 3eQXbQNR61DmMy20GLTIO3SFed9Rfi/ophgCLGFLDR3r0KvHjwMb/jYWS0celV/4
# Lz27LfAekm8v9E5IXaeiXbAUYZKK090n4CVl3JBtbN+9DtI9SNu/yjvozW52/u7R
# X/Ttpa/KDlpuokZ+Zcbvmtd9ur9gFLvZzh41o9MsE/clQtdaFWGvuo6Jua/ntpgk
# ey3E5/vBFe+MJPG6phdnuo6r57ZudCudiI1bAgMBAAGjggGbMIIBlzAOBgNVHQ8B
# Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O
# BBYEFH6QuMwqcPG0hQlQ6c5jCtTTLrVeMEUGA1UdEQQ+MDykOjA4MR4wHAYDVQQL
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xFjAUBgNVBAUTDTIzMDAxMis1MDc1NTkw
# HwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEwYAYDVR0fBFkwVzBVoFOg
# UYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0
# JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNybDBtBggrBgEFBQcBAQRh
# MF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
# Y2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy
# dDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQBKTbYOjzwTG/DXGaz9
# s6+fQeaTtDcFmMY+5UyVFCyj7Pv+5i37qfX8lSL/tBIfYQfWsMuBQlfZurJD6r4H
# VJ2CeH+1fgiq8dcHdVKoZ3Sa2qXoX3cq9iS8cVb06B7+5/XJ7I0OxHH9fDsvJ3T3
# w5V/ZtAIFmLrl+P0CtG+92uzRsn0nTbdFjOkLMLWPLAU3THohKRlSEMgFJpPkm5n
# 5UAZ35xX6FWCrDLsSKb555bTifwa8mJBwdlof0bmfYidH+dxZ1FdDxvLnNl9zeKs
# A4kejaaIqqIPguhwAti5Ql7BlTNoJNwxCvBmqW2MQLnCkYN/VVUsR3V2x/rcTNzo
# Bf/Z/SpROvdaA2ZOOd1uioXJt3tdLQ7vHpqpib0KfWr/FWXW10q38VxfCnRQBqzb
# SuztR7nEMuzX7Ck+B/XaPDXd1qh72+QYyB0Z2VzWmO9zsnb9Uq/dwu8LGeQqnyu6
# 7SDGACvnXii2fb9+US492VTnXSnFKyqwgzUyFMtZK1/sHYTv6bG4TtQUygQxTN+Z
# V+aJIlKO2MqZ7bKrAnOzS9m6NgoTdWOq11bTOZwKlIEV/EhV9SWkDmdpR/hPPT2v
# 6TEj4F8PT/zHjRezIU5c/DGlt/VhY/pK0XkJtEyMmmS1BMtjU/rqBZVMIm3dnxQs
# /TBByr+Cf8Z1r7aifQVQ+WSqzjCCBr0wggSloAMCAQICEzMAAAA5O7Y3Gb8GHWcA
# AAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRl
# IEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoXDTM2MDMyMjIyMTMwNFow
# VzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEo
# MCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAyNDCCAiIwDQYJ
# KoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeqlRYHNa265v4IY9fH8TKh
# emHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo0dtS/EW6I/yEL/bLSY8h
# KpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATvQVL4tcf03aTycsz8QeCd
# M0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a1uv1zerOYMnsneRRwCbp
# yW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1FyQfK0fVkaya8SmVHQ/t
# Of23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfOGSWHIIV4YrTJTT6PNty5
# REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7ttOu1bVnXfHaqPYl2rPs
# 20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJuz2MXMCt7iw7lFPG9LXK
# Gjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxSCwyoGIq0PhaA7Y+VPct5
# pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOmVQop36wUVUYklUy++vDW
# eEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3SkE/xIkgpfl22MM1itkZ
# 35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGC
# NxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPXLQaUEggxMBkGCSsGAQQB
# gjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU
# ci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2Ny
# bC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0MjAx
# MV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAwTgYIKwYBBQUHMAKGQmh0
# dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0MjAx
# MV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOCAgEAFJQfOChP7onn6fLI
# MKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D5W4wMwYeLystcEqfkjz4
# NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBYnbu0+THSuVHTe0VTTPVh
# ily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSIvgn0JksVBVMYVI5QFu/q
# hnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6aR9y34aiM1qmxaxBi6OU
# nyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4wPKC5OmHm1DQIt/MNokbb
# H3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7RTX8AdBPo0I6OEojf39z
# uFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK/fg8B2qjW88MT/WF5V5u
# vZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSKYBv0VisCzfxgeU+dquXW
# 9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkwYTu/9dLeH2pDqeJZAABV
# DWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVTQl0v4q8J/AUmQN5W4n10
# 1cY2L4A7GTQG1h32HHAvfQESWP0xghndMIIZ2QIBATBuMFcxCzAJBgNVBAYTAlVT
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jv
# c29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIdTRnITtcPV0gAAAAAAh0w
# DQYJYIZIAWUDBAIBBQCggZAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwLwYJ
# KoZIhvcNAQkEMSIEIGe8EoaxUTiqlAFaKgef32Ct3xl5Nwgj8anNAO6NxVWFMEIG
# CisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8v
# d3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEAsVgbvksH642FHz2Q
# yT5GwV8y3AoniuGmXVK6Utf6LeZFmop/NjDUtljcVs3ClPH++B+bM5QnAvzOMgHK
# uUPHBolJ/kGBW397VjzdRqkgDV6MYRNk8A/xBrtATYWEbh265RzqSGeBvMnlr7y2
# CQP0rFlloy/MF0Sw9Kzm2lfzlVV2Yl4Hv3aNKbZzPixAA82yo8PrcsOxZlJGGScM
# m0HcBZ996ro27XYTnx3lpvFJB0JdogyLzEKb3FDpj/eqFTf867L2Rj9rVTu7h2TD
# dV/TjfMqS4CnNnUm7gOd2CbUt64kjufI8QezkibplHU4xpG/ASrOdcJEYy55L/v4
# 8LvwL6GCF60wghepBgorBgEEAYI3AwMBMYIXmTCCF5UGCSqGSIb3DQEHAqCCF4Yw
# gheCAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsqhkiG9w0BCRABBKCCAUkEggFF
# MIIBQQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUABCBjJ4z5oug2Jutd
# fpKIBlzYUKqS4e6QPjjVPzQ4QKva9AIGaq5iqxdxGBMyMDI2MTAxNTE5MDMyMS44
# MDFaMASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExp
# bWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo0QzFBLTA1RTAtRDk0NzEl
# MCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEfswggcoMIIF
# EKADAgECAhMzAAACGCXZkgXi5+XkAAEAAAIYMA0GCSqGSIb3DQEBCwUAMHwxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv
# c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI1MDgxNDE4NDgyNVoXDTI2MTEx
# MzE4NDgyNVowgdMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw
# DgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# LTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJhdGlvbnMgTGltaXRlZDEn
# MCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjRDMUEtMDVFMC1EOTQ3MSUwIwYDVQQD
# ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG9w0BAQEF
# AAOCAg8AMIICCgKCAgEAsdzo6uuQJqAfxLnvEBfIvj6knK+p6bnMXEFZ/QjPOFyw
# lcjDfzI8Dg1nzDlxm7/pqbvjWhyvazKmFyO6qbPwClfRnI57h5OCixgpOOCGJJQI
# ZSTiMgui3B8DPiFtJPcfzRt3FsnxjLXwBIjGgnjGfmQl7zejA1WoYL/qBmQhw/FD
# FTWebxfo4m0RCCOxf2qwj31aOjc2aYUePtLMXHsXKPFH0tp5SKIF/9tJxRSg0NYE
# vQqVilje8aQkPd3qzAux2Mc5HMSK4NMTtVVCYAWDUZ4p+6iDI9t5BNCBIsf5ooFN
# UWtxCqnpFYiLYkHfFfxhVUBZ8LGGxYsA36snD65s2Hf4t86k0e8WelH/usfhYqOM
# 3z2yaI8rg08631IkwqUzyQoEPqMsHgBem1xpmOGSIUnVvTsAv+lmECL2RqrcOZlZ
# ax8K0aiij8h6UkWBN2IA/ikackTSGVRBQmWWZuLFWV/T4xuNzscC0X7xo4fetgps
# qaEA0jY/QevkTvLv4OlNN9eOL8LNh7Vm0R65P7oabOQDqtUFAwCgjgPJ0iV/jQCa
# MAcO3SYpG5wSAYiJkk4XLjNSlNxU2Idjs1sORhl7s7LC6hOb7bVAHVwON74GxfFN
# iEIA6BfudANjpQJ0nUc/ppEXpT4pgDBHsYtV8OyKSjKsIxOdFR7fIJIjDc8DvUkC
# AwEAAaOCAUkwggFFMB0GA1UdDgQWBBQkLqHEXDobY7dHuoQCBa4sX7aL0TAfBgNV
# HSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSgUqBQhk5o
# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBU
# aW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEEYDBeMFwG
# CCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRz
# L01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNydDAMBgNV
# HRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIH
# gDANBgkqhkiG9w0BAQsFAAOCAgEAnkjRhjwPgdoIpvt4YioT/j0LWuBxF3ARBKXD
# ENggraKvC0oRPwbjAmsXnPEmtuo5MD8uJ9Xw9eYrxqqkK4DF9snZMrHMfooxCa++
# 1irLz8YoozC4tci+a4N37Sbke1pt1xs9qZtvkPgZGWn5BcwVfmAwSZLHi2CuZ06Y
# 0/X+t6fNBnrbMVovNaDX4WPdyI9GEzxfIggDsck2Ipo4VXL/Arcz7p2F7bEZGRuy
# xjgMC+woCkDJaH/yk/wcZpAsixe4POdN0DW6Zb35O3Dg3+a6prANMc3WIdvfKDl7
# 5P0aqcQbQAR7b0f4gH4NMkUct0Wm4GN5KhsE1YK7V/wAqDKmK4jx3zLz3a8Hsxa9
# HB3GyitlmC5sDhOl4QTGN5kRi6oCoV4hK+kIFgnkWjHhSRNomz36QnbCSG/BHLEm
# 2GRU9u3/I4zUd9E1AC97IJEGfwb+0NWb3QEcrkypdGdWwl0LEObhrQR9B1V7+edc
# yNmsX0p2BX0rFpd1PkXJSbxf8IcEiw/bkNgagZE+VlDtxXeruLdo5k3lGOv7rPYu
# OEaoZYxDvZtpHP9P36wmW4INjR6NInn2UM+krP/xeLnRbDBkm9RslnoDhVraliKD
# H62BxhcgL9tiRgOHlcI0wqvVWLdv8yW8rxkawOlhCRqT3EKECW8ktUAPwNbBULkT
# +oWcvBcwggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0GCSqGSIb3
# DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
# A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIw
# MAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAx
# MDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYTAlVT
# MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK
# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1l
# LVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
# 5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/
# XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZrBxTzxXb1
# hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7
# M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxRnOlwaQ3K
# Ni1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uDRedGbsoy
# 1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGaRnXNxF80
# 3RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fzpk03dJQc
# NIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9ahha
# YQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGUlNi5UPkL
# iWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV
# 2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0wggHZMBIG
# CSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUp
# zxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNVHSAEVTBT
# MFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jv
# c29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0lBAwwCgYI
# KwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGG
# MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9lJBb186a
# GMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br
# aS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoGCCsG
# AQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3NvZnQuY29t
# L3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcN
# AQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEGk5c9MTO1
# OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYA
# A7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7ndn/OOPcbz
# aN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6L
# GYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy87JGA0j3m
# Sj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0
# SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2fpCjcZxko
# JLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz/gq77EFm
# PWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJC482
# 2rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAxM328y+l7
# vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDVjCC
# Aj4CAQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExp
# bWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo0QzFBLTA1RTAtRDk0NzEl
# MCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsO
# AwIaAxUAnWtGrXWiuNE8QrKfm4CtGr57z+mggYMwgYCkfjB8MQswCQYDVQQGEwJV
# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE
# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt
# ZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAO57JTkwIhgPMjAyNjEw
# MTUxMDExMDVaGA8yMDI2MTAxNjEwMTEwNVowdDA6BgorBgEEAYRZCgQBMSwwKjAK
# AgUA7nslOQIBADAHAgEAAgIFzDAHAgEAAgIUQDAKAgUA7nx2uQIBADA2BgorBgEE
# AYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYag
# MA0GCSqGSIb3DQEBCwUAA4IBAQBShR7QhG8wyLs/aXenY3icx0+iutQ1yPc//wJ6
# 3ER8T2hx1LQdUW2p8/iYHOdAROkaN8E+lG8RU9RVSP9+3jdXb6tOvamBuNMm2l3e
# uDKd+thZti256uzDqVlrAYMZmY1Tvsgn7LQGKrIu55bLy9N/RpKfQq+g2Q+g+mvy
# RwBM8e501kcBf8Sx6D2E6x4HryqooEziDVwjOaB6Z1V7hMQPwR0ZxyF9et26Csx1
# /oZuhkerLwnVj0OjITYw0JpgXMGXEww4sfoP8DLoz+WIJWdAppQ4HJpmKBo93Ij/
# ur4ClszU7YtUs53un8qWuozDlk+tGR3yDotFhQiV/IA/C3WgMYIEDTCCBAkCAQEw
# gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT
# B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
# AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIYJdmSBeLn5eQA
# AQAAAhgwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B
# CRABBDAvBgkqhkiG9w0BCQQxIgQg0aUfxkmPJt9gCtwCPpVfdd2O4HkTUk1Zh8Iz
# GKhjEhUwgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCCZE9yJuOTItIwWaES6
# lzGKK1XcSoz1ynRzaOVzx9eFajCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w
# IFBDQSAyMDEwAhMzAAACGCXZkgXi5+XkAAEAAAIYMCIEIKEuKyoM8AL1FqzedI/2
# re/iCNW7j+n00r49pH98tIygMA0GCSqGSIb3DQEBCwUABIICAI9gAg2ngFpgPpm3
# h5LbsWzIxVnWYR40n7KG6EZs+qjxZ55iHSSRhjc8rKxECHNN1V9MJNlMLcIVnBbe
# rGKLDk3rDL1UcWsYeVYGoTB9OSGwOUW9drxX0juxSIVhfFXa2TV1jAgmFIJdssfZ
# z1SIDIFTpa7m9B7GsVYROzCjF8iiVyTuG0XS51wYcswTz28+wFg2DFdVtF1o/FT6
# Ae08rApnBGwjfyjI8Do3KAWQiVozCsdcFNDxqDP0+FA7KdpLEHthOjupDF84sTQk
# rQkMmfQA3RYCQK576JF19M9fWCP+n8Be1VZi0+5N4MRHdH4eJHKFdtSlafKzixHk
# r7QX6IvOjXMaqUiCT4br11hUmq3PRcjrGbUUxZcokztQd4emXj+yHPT72DsixHoN
# 3DqdODcAXQqYpRWoqOa0Cu0soHN76K7TOnDdkeXdtEa8jVKzRvNKQzHcElW/KkbV
# xSkRgwPbSYul3q0b1kBawlEI41WedrtAulaZ+ptC5LARN1Xidlwt1tD1AQTFRr07
# Ta9vgcW9zloiQE74r360oQfyvjqpTdXhxAx86akmvej8R09z8U4c0/HmR1u1103C
# Zlz6IgXyjnY/iP0ff9R4Wh4rKVZzOlg2sXkwCzRXPQxfS0j6Zw5M08QY6fl/MSve
# Kss5WX4gTZJMCv6SGiC6YBQNwzLW
# SIG # End signature block