Public/Reportings/New-EntraOpsPrivilegedEamDashboardData.ps1

<#
.SYNOPSIS
    Generate (refresh) the embedded dataset for the EntraOps EAM Dashboard static web app.

.DESCRIPTION
    Transforms EntraOps Privileged EAM data into the EAM Dashboard (Enterprise Access
    Model Dashboard) dataset. The dashboard is the static-web counterpart of the
    "EntraOps Privileged EAM - Overview" Azure workbook and reuses the same
    visualizations, filters and drill-downs.

    Generates data/eam-dashboard-data.js exposing `window.ENTRAOPS_EAM_DATA` so the
    static web app works both when served over HTTP (for example Azure Static Web
    Apps) and when opened directly from the file system (no fetch / CORS required).

    Source data is the Privileged EAM export written by Save-EntraOpsPrivilegedEAMJson:
    PrivilegedEAM/<RbacSystem>/<RbacSystem>.json (only JSON files directly in the RBAC
    system folder are read, not the per-object subfolders user/, group/,
    serviceprincipal/, ...).

    Computed columns follow the PrivilegedEAM parsers (Parsers/PrivilegedEAM_WatchLists)
    and the Overview workbook:

      * EligibilityBy - "PIM for Entra ID Roles and Groups", "PIM for Entra ID Roles",
                             "PIM for Azure Roles", "PIM for Groups" or "N/A" derived
                             from RoleSystem, PIMAssignmentType and RoleAssignmentSubType.
      * RestrictedManagement - "Applied", "Conflict", "Not applied" or "Not available"
                             derived from ObjectType, ObjectSubType and the
                             RestrictedManagementByAadRole/RAG/RMAU flags (same case
                             logic as the workbook grid).
      * SyncSource - "Cloud-Only" / "Hybrid" from OnPremSynchronized.
      * PrivilegedType - "Tenant Governance" (foreign object whose role assignments
                             all originate from a Tenant Governance delegation),
                             "Multi-Tenant Apps" (service principal from another tenant),
                             "B2B Collaboration" (external user from another tenant with at
                             least one non-Tenant-Governance role assignment) or
                             "Local Identities" (everything else) derived from
                             ObjectTenantId, ObjectType and RoleAssignmentSubType.
    * scopeReasoning - why an Azure, Entra ID, or Identity Governance assignment
                     scope was classified, sourced from the matching
                     ScopeReasoning_<RbacSystem>.json artifact written by
                     Update-EntraOpsClassificationControlPlaneScope.
    * controlPlaneReasoning - why an object entered the Control Plane input set, sourced
                     from Classification/<TenantName>/ScopeReasoning_ControlPlane.json.

    Change notifications compare with the existing output file. Without one (the reporting
    pipelines never commit report data), they compare with the Privileged EAM export in git
    history: the latest `reporting-*` release tag reachable from HEAD, otherwise the export
    before its latest change.

    This function requires the module to be imported from a repository checkout that
    contains the Reports/EamDashboard folder.

.PARAMETER RepoRoot
    Path to the EntraOps repository root that contains the PrivilegedEAM export folder.
    Defaults to the repository this module lives in.

.PARAMETER ImportPath
    Folder with the Privileged EAM export. Defaults to <RepoRoot>/PrivilegedEAM.

.PARAMETER AppRoot
    Path to the EamDashboard app folder (where the generated content is written).
    Defaults to Reports/EamDashboard in the EntraOps repository.

.PARAMETER OutFile
    Output file. Defaults to <AppRoot>/data/eam-dashboard-data.js.

.PARAMETER TenantId
    Home tenant id used to detect foreign objects for the PrivilegedType column
    (Multi-Tenant Apps, B2B Collaboration, Tenant Governance). Defaults to the most
    common ObjectTenantId in the export among objects that are neither guest users
    nor Tenant Governance delegated admins.

.PARAMETER ResolveLinkedIdentityObjectIds
    Resolve linked-identity object IDs outside the Privileged EAM export to display
    names with batched Microsoft Graph getByIds requests. Defaults to the
    EamDashboard.ResolveLinkedIdentityObjectIds config setting, or $true.

.PARAMETER PassThru
    Emit the generated payload object to the pipeline.

.EXAMPLE
    New-EntraOpsPrivilegedEamDashboardData

    Regenerates the EAM Dashboard dataset from the PrivilegedEAM folder of this repository.

.EXAMPLE
    New-EntraOpsPrivilegedEamDashboardData -ImportPath "C:\Exports\PrivilegedEAM" -Verbose -WhatIf

    Shows what would be generated from an explicit Privileged EAM export without changing any files.
#>


function New-EntraOpsPrivilegedEamDashboardData {

    [CmdletBinding(SupportsShouldProcess = $true)]
    param (
        [Parameter(Mandatory = $false)]
        [System.String]$RepoRoot,

        [Parameter(Mandatory = $false)]
        [System.String]$ImportPath,

        [Parameter(Mandatory = $false)]
        [System.String]$AppRoot,

        [Parameter(Mandatory = $false)]
        [System.String]$OutFile,

        [Parameter(Mandatory = $false)]
        [System.String]$TenantId,

        [Parameter(Mandatory = $false)]
        [System.Boolean]$ResolveLinkedIdentityObjectIds = $true,

        [Parameter(Mandatory = $false)]
        [switch]$PassThru
    )

    # Resolve the app/repository location relative to the module location:
    # <repo>/EntraOps/Public/<subfolder> -> <repo>/Reports/EamDashboard
    # Prefer the module's own ModuleBase (always populated for exported module
    # functions) over $PSScriptRoot, which can be empty depending on how the
    # function was invoked/loaded.
    $ModuleRoot = $MyInvocation.MyCommand.Module.ModuleBase
    if ([string]::IsNullOrWhiteSpace($ModuleRoot) -and -not [string]::IsNullOrWhiteSpace($PSScriptRoot)) {
        $ModuleRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
    }
    if ([string]::IsNullOrWhiteSpace($ModuleRoot)) {
        throw "Unable to resolve the EntraOps module location. Import the module with 'Import-Module <path-to-EntraOps> -Force' and try again."
    }
    $RepositoryRoot = if (-not [string]::IsNullOrWhiteSpace($Global:EntraOpsBaseFolder)) { $Global:EntraOpsBaseFolder } else { Split-Path -Parent $ModuleRoot }

    if ([string]::IsNullOrWhiteSpace($RepoRoot)) { $RepoRoot = $RepositoryRoot }
    if ([string]::IsNullOrWhiteSpace($AppRoot)) { $AppRoot = Join-Path $RepoRoot 'Reports/EamDashboard' }
    if (-not (Test-Path -LiteralPath $AppRoot -PathType Container)) {
        throw "EAM Dashboard app folder not found: $AppRoot. Import the EntraOps module from a repository checkout that contains Reports/EamDashboard, or run Install-EntraOpsReportingFolder to download the Reports folder."
    }
    if ([string]::IsNullOrWhiteSpace($ImportPath)) { $ImportPath = Join-Path $RepoRoot 'PrivilegedEAM' }
    if ([string]::IsNullOrWhiteSpace($OutFile)) { $OutFile = Join-Path $AppRoot 'data/eam-dashboard-data.js' }

    if (-not (Test-Path -LiteralPath $ImportPath)) {
        throw "Privileged EAM import path not found: $ImportPath. Run Save-EntraOpsPrivilegedEAMJson first or pass -ImportPath."
    }

    if (-not $PSBoundParameters.ContainsKey('ResolveLinkedIdentityObjectIds')) {
        $EamDashboardConfigFilePath = Join-Path $RepoRoot 'EntraOpsConfig.json'
        if (Test-Path -LiteralPath $EamDashboardConfigFilePath -PathType Leaf) {
            try {
                $EamDashboardConfig = Get-Content -LiteralPath $EamDashboardConfigFilePath -Raw | ConvertFrom-Json
                if ($null -ne $EamDashboardConfig.EamDashboard -and $null -ne $EamDashboardConfig.EamDashboard.ResolveLinkedIdentityObjectIds) {
                    $ResolveLinkedIdentityObjectIds = [bool]$EamDashboardConfig.EamDashboard.ResolveLinkedIdentityObjectIds
                }
            } catch {
                Write-Warning "Failed to read EamDashboard settings from ${EamDashboardConfigFilePath}: $($_.Exception.Message). Defaulting -ResolveLinkedIdentityObjectIds to `$true."
            }
        }
    }

    # Change notification baseline: the existing dataset (local runs), otherwise the previous
    # Privileged EAM export from git history (the reporting pipelines never commit report data).
    $previousPayload = $null
    $previousObjectList = $null
    if (Test-Path -LiteralPath $OutFile -PathType Leaf) {
        try {
            $previousText = Get-Content -LiteralPath $OutFile -Raw -Encoding UTF8
            $previousJson = $previousText -replace '(?s)^.*?window\.ENTRAOPS_EAM_DATA\s*=\s*', '' -replace ';\s*$', ''
            $previousPayload = $previousJson | ConvertFrom-Json -Depth 15 -ErrorAction Stop
            if ($null -ne $previousPayload.objects) { $previousObjectList = @($previousPayload.objects) }
        } catch {
            Write-Warning "Existing EAM Dashboard dataset could not be used as a notification baseline; change notifications will not be generated for this run: $($_.Exception.Message)"
        }
    } else {
        $previousObjectList = Get-EntraOpsPrivilegedEamGitBaselineObjects -ImportPath $ImportPath -TenantId $TenantId
    }

    $sourceFilesRef = [ref]@()
    $scopeReasoningDetails = Import-EntraOpsDashboardScopeReasoning -RepoRoot $RepoRoot
    $controlPlaneReasoningDetails = Import-EntraOpsControlPlaneReasoning -RepoRoot $RepoRoot
    $objects = Get-EntraOpsPrivilegedEamDashboardObjects -ImportPath $ImportPath -TenantId $TenantId -ScopeReasoningDetails $scopeReasoningDetails -ControlPlaneReasoningDetails $controlPlaneReasoningDetails -SourceFiles $sourceFilesRef
    $files = $sourceFilesRef.Value

    $roleDefinitions = [System.Collections.Generic.List[object]]::new()
    # The classified directory roles file lives in the AzurePrivilegedIAM repository, so it is
    # not found under the default -RepoRoot (the EntraOps repository). Probe the explicit
    # -RepoRoot first, then the temporary sparse AzurePrivilegedIAM checkout used by the
    # Push-EntraOpsPrivilegedReporting workflow (.reporting/AzurePrivilegedIAM).
    $directoryRoleClassificationCandidates = @(
        (Join-Path $RepoRoot 'Classification/Classification_EntraIdDirectoryRoles.json'),
        (Join-Path (Join-Path $RepoRoot '.reporting/AzurePrivilegedIAM') 'Classification/Classification_EntraIdDirectoryRoles.json')
    )
    $directoryRoleClassificationPath = @($directoryRoleClassificationCandidates | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1)[0]
    if (-not $directoryRoleClassificationPath) {
        # Last resort: the AzurePrivilegedIAM file downloaded into the EntraOps cache folder.
        $catalogCacheRoot = Get-EntraOpsClassificationSourceCache -FileName 'Classification_EntraIdDirectoryRoles.json'
        if ($catalogCacheRoot) {
            $directoryRoleClassificationPath = Join-Path $catalogCacheRoot 'Classification/Classification_EntraIdDirectoryRoles.json'
            Write-Verbose "Using the cached directory role classification $directoryRoleClassificationPath"
        }
    }
    if ($directoryRoleClassificationPath) {
        try {
            foreach ($role in @([System.IO.File]::ReadAllText($directoryRoleClassificationPath) | ConvertFrom-Json)) {
                try {
                    $classifications = @($role.Classification | Where-Object { $_ -and $_.EAMTierLevelName } | Sort-Object { Get-EntraOpsTierSortOrder -TierValue $_.EAMTierLevelTagValue })
                    $effective = $classifications | Select-Object -First 1
                    if (-not $role.RoleId -or -not $effective) { continue }
                    $roleDefinitions.Add([ordered]@{
                            roleDefinitionId = "$($role.RoleId)"
                            displayName      = "$($role.RoleName)"
                            tierName        = "$($effective.EAMTierLevelName)"
                            service         = "$($effective.Category)"
                            classifications = @($classifications | ForEach-Object {
                                    [ordered]@{ tierName = "$($_.EAMTierLevelName)"; service = "$($_.Category)" }
                                })
                        }) | Out-Null
                } catch {
                    Write-Warning "Skipping directory role classification '$($role.RoleId)' ($($role.RoleName)): $($_.Exception.Message)"
                }
            }
        } catch {
            Write-Warning "Could not import directory role classifications from ${directoryRoleClassificationPath}: $($_.Exception.Message)"
        }
    } else {
        Write-Warning "Directory role classification file not found; PIM role tiers will use classified assignment evidence only. Paths tried: $($directoryRoleClassificationCandidates -join ', ')"
    }

    $linkedIdentityDisplayNames = @{}
    foreach ($object in @($objects)) {
        if ($object.objectId -and $object.objectDisplayName) {
            $linkedIdentityDisplayNames[$object.objectId] = $object.objectDisplayName
        }
    }
    if ($ResolveLinkedIdentityObjectIds) {
        $GuidPattern = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
        $linkedIds = @($objects | ForEach-Object { @($_.associatedWorkAccount) } | Where-Object { $_ -and $_ -match $GuidPattern } | Sort-Object -Unique)
        $idsToResolve = @($linkedIds | Where-Object { -not $linkedIdentityDisplayNames.ContainsKey($_) })
        if ($idsToResolve.Count -gt 0) {
            Write-Verbose "Resolving $($idsToResolve.Count) linked identity object id(s) outside the Privileged EAM export via Microsoft Graph..."
            $GraphBatchSize = 999 # directoryObjects/getByIds accepts up to 1000 IDs per request.
            for ($index = 0; $index -lt $idsToResolve.Count; $index += $GraphBatchSize) {
                $idBatch = @($idsToResolve[$index..([Math]::Min($index + $GraphBatchSize - 1, $idsToResolve.Count - 1))])
                $body = @{ ids = $idBatch; types = @('user', 'group', 'servicePrincipal') } | ConvertTo-Json
                try {
                    foreach ($resolvedObject in @(Invoke-EntraOpsMsGraphQuery -Method POST -Uri '/v1.0/directoryObjects/getByIds' -Body $body -OutputType PSObject)) {
                        if ($resolvedObject.id -and $resolvedObject.displayName) {
                            $linkedIdentityDisplayNames["$($resolvedObject.id)"] = "$($resolvedObject.displayName)"
                        }
                    }
                } catch {
                    Write-Warning "Failed to resolve $($idBatch.Count) linked identity object id(s) via Microsoft Graph: $($_.Exception.Message)"
                }
            }
        }
    }

    if (-not $files) {
        Write-Warning "No Privileged EAM JSON files found under $ImportPath (expected <RbacSystem>/<RbacSystem>.json). Generating an empty dataset."
    }

    $repoRootFull = (Resolve-Path -LiteralPath $RepoRoot).Path
    $tenantName = Get-EntraOpsReportingTenantName -RepoRoot $RepoRoot
    $generatedAt = (Get-Date).ToUniversalTime().ToString('o')
    if ($null -ne $previousPayload -and -not [string]::IsNullOrWhiteSpace("$($previousPayload.tenantName)") -and
        -not [string]::IsNullOrWhiteSpace("$tenantName") -and "$($previousPayload.tenantName)" -ne "$tenantName") {
        Write-Warning "EAM Dashboard baseline belongs to tenant '$($previousPayload.tenantName)' instead of '$tenantName'; change notifications will not be generated for this run."
        $previousObjectList = $null
    }
    $notifications = [System.Collections.Generic.List[object]]::new()
    if ($null -ne $previousObjectList) {
        $previousObjects = @{}
        $currentObjects = @{}
        $previousAssignments = @{}
        $currentAssignments = @{}

        function Get-AssignmentKey {
            param($Assignment)
            if ($Assignment.roleAssignmentInstanceId) { return "$($Assignment.roleAssignmentInstanceId)" }
            return "$($Assignment.roleAssignmentId)"
        }

        foreach ($object in $previousObjectList) {
            if ($object.objectId -and -not $previousObjects.ContainsKey($object.objectId)) { $previousObjects[$object.objectId] = $object }
            foreach ($assignment in @($object.roleAssignments)) {
                $assignmentKey = Get-AssignmentKey $assignment
                if ($assignmentKey -and -not $previousAssignments.ContainsKey($assignmentKey)) {
                    $previousAssignments[$assignmentKey] = $assignment
                }
            }
        }
        foreach ($object in @($objects)) {
            if ($object.objectId -and -not $currentObjects.ContainsKey($object.objectId)) { $currentObjects[$object.objectId] = $object }
            foreach ($assignment in @($object.roleAssignments)) {
                $assignmentKey = Get-AssignmentKey $assignment
                if ($assignmentKey -and -not $currentAssignments.ContainsKey($assignmentKey)) {
                    $currentAssignments[$assignmentKey] = $assignment
                }
            }
        }

        foreach ($objectId in @($currentObjects.Keys | Sort-Object)) {
            $current = $currentObjects[$objectId]
            if (-not $previousObjects.ContainsKey($objectId)) {
                $notifications.Add([ordered]@{
                        id = "asset-added:$objectId"; kind = 'Asset'; change = 'Added'; severity = 'info'
                        title = "Privileged asset added: $($current.objectDisplayName)"
                        detail = "$($current.objectType) is now classified as $($current.objectAdminTierLevelName)."
                        href = "#asset=$([uri]::EscapeDataString($objectId))"
                    }) | Out-Null
            } elseif ($previousObjects[$objectId].objectAdminTierLevelName -ne $current.objectAdminTierLevelName) {
                $notifications.Add([ordered]@{
                        id = "asset-tier:$objectId"; kind = 'Asset'; change = 'Changed'; severity = 'warning'
                        title = "Asset access level changed: $($current.objectDisplayName)"
                        detail = "$($previousObjects[$objectId].objectAdminTierLevelName) -> $($current.objectAdminTierLevelName)"
                        href = "#asset=$([uri]::EscapeDataString($objectId))"
                    }) | Out-Null
            }
        }
        foreach ($objectId in @($previousObjects.Keys | Where-Object { -not $currentObjects.ContainsKey($_) } | Sort-Object)) {
            $previous = $previousObjects[$objectId]
            $notifications.Add([ordered]@{
                    id = "asset-removed:$objectId"; kind = 'Asset'; change = 'Removed'; severity = 'info'
                    title = "Privileged asset removed: $($previous.objectDisplayName)"
                    detail = 'Open Privilege History to inspect the previous classified resource.'
                    href = '../PrivilegeHistory/index.html'
                }) | Out-Null
        }
        foreach ($assignmentId in @($currentAssignments.Keys | Where-Object { -not $previousAssignments.ContainsKey($_) } | Sort-Object)) {
            $assignment = $currentAssignments[$assignmentId]
            $notifications.Add([ordered]@{
                    id = "assignment-added:$assignmentId"; kind = 'Role assignment'; change = 'Added'; severity = 'info'
                    title = "Role assignment added: $($assignment.roleDefinitionName)"
                    detail = "Scope: $($assignment.roleAssignmentScopeName)"
                    href = "#assignment=$([uri]::EscapeDataString($assignmentId))"
                }) | Out-Null
        }
        foreach ($assignmentId in @($previousAssignments.Keys | Where-Object { -not $currentAssignments.ContainsKey($_) } | Sort-Object)) {
            $assignment = $previousAssignments[$assignmentId]
            $notifications.Add([ordered]@{
                    id = "assignment-removed:$assignmentId"; kind = 'Role assignment'; change = 'Removed'; severity = 'info'
                    title = "Role assignment removed: $($assignment.roleDefinitionName)"
                    detail = 'Open Privilege History to inspect the previous assignment.'
                    href = '../PrivilegeHistory/index.html'
                }) | Out-Null
        }
    }
    # Serialize the linked identity display names with sorted keys so repeated runs produce a
    # stable dataset (plain hashtable enumeration order is nondeterministic).
    $sortedLinkedIdentityDisplayNames = [ordered]@{}
    foreach ($linkedIdentityId in @($linkedIdentityDisplayNames.Keys | Sort-Object)) {
        $sortedLinkedIdentityDisplayNames[$linkedIdentityId] = $linkedIdentityDisplayNames[$linkedIdentityId]
    }

    # Derived from the notification content instead of the run time: the pipelines rebuild the dataset from
    # git history on every run, so a run without new Privileged EAM changes repeats the same notifications
    # and must keep them marked as read in the dashboard.
    $notificationJson = ConvertTo-Json -InputObject @($notifications) -Depth 5 -Compress
    $notificationHash = [System.Security.Cryptography.SHA256]::HashData([System.Text.Encoding]::UTF8.GetBytes("$tenantName|$notificationJson"))
    $changeSetId = [System.Convert]::ToHexString($notificationHash).Substring(0, 16).ToLowerInvariant()

    $payload = [ordered]@{
        tenantName                 = $tenantName
        generatedAt                = $generatedAt
        changeSetId                = $changeSetId
        notifications              = @($notifications)
        generatedFrom              = @(@($files) | ForEach-Object {
                if ($_.FullName.StartsWith($repoRootFull)) {
                    $_.FullName.Substring($repoRootFull.Length).TrimStart('\', '/') -replace '\\', '/'
                } else {
                    $_.Name
                }
            })
        objects                    = $objects
        roleDefinitions            = @($roleDefinitions)
        linkedIdentityDisplayNames = $sortedLinkedIdentityDisplayNames
    }

    $json = $payload | ConvertTo-Json -Depth 12 -Compress
    $content = "// Auto-generated by New-EntraOpsPrivilegedEamDashboardData - do not edit by hand.`n" +
    "window.ENTRAOPS_EAM_DATA = $json;`n"

    if ($PSCmdlet.ShouldProcess($OutFile, 'Write EAM Dashboard dataset')) {
        Save-EntraOpsReportDataFile -Content $content -LiteralPath $OutFile

        $nAssignments = 0
        foreach ($obj in $objects) { $nAssignments += @($obj.roleAssignments).Count }
        Write-Host "Privileged objects: $($objects.Count)"
        Write-Host "Role assignments: $nAssignments"
        Write-Host "Role definitions: $($roleDefinitions.Count)"
        Write-Host "Wrote $OutFile"
    }

    if ($PassThru) { $payload }
}

# SIG # Begin signature block
# MIIniAYJKoZIhvcNAQcCoIIneTCCJ3UCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCC2ldnvsBsozSHa
# WMKtYgjgs2a0gI7zxmBlQPbW9XmnwKCCIDwwggXJMIIEsaADAgECAhAbtY8lKt8j
# 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
# ARUwLwYJKoZIhvcNAQkEMSIEIDFtA8J64LeLx/IZ1MGgsfPIJ+LfWziZfV2bSHqb
# zSXDMA0GCSqGSIb3DQEBAQUABIIBgKI4CGJQD/K3c7x61Bb6b1oVKNu/NaTYxzHG
# acyt9vsPSbzhVdgMUVrpUq308sT5HMBlSGfrHMhxeXYh49aCBoYWeopEfMU4HkEl
# o7Z2UDJWZDfF2yyQDEC5O73+AgbSwYKgKCYXqF1wD2KMlCDpadwHpf7l/vWrcVXI
# Qof2WZ/Dno4IZCBrk5mN0iTUzeKC+5FZbMzdEdoqMeNBkGFXPXmd1xPtsQx4mVXx
# cRKdYS6wtYKHW+TtAR7YbQ2YUp6Z9SlVvjtgjRsdSKhWi6/pcCjlwwj+xyB7kl22
# ENPNtuJQB9iAnFrB6XZ7rVK4U4UHcL/v0YPwc4IZwgW1BukpVR2lfKN6AC7VPgjz
# 4NN1n8agoFaVzS1hJL+V2kBIlLNY/3ggGbTE8D1RDLXjVXZX1t0t9p5dMCDq9a//
# pOPW2Jw21k4jAqoTDmmg5TWFLiwAOBFEf0sp7Eok6YqpsXDAm0stsQAlXk3ebTYK
# uLoQKweRj8+MiSwRgVg7l87BLGYkrKGCBAIwggP+BgkqhkiG9w0BCQYxggPvMIID
# 6wIBATBqMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0
# ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAyMSBDQQIQ
# KPB3wRw2vf5fdDJHcCcuAzANBglghkgBZQMEAgIFAKCCAVYwGgYJKoZIhvcNAQkD
# MQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNjEwMjIxMTQwMjBaMDcG
# CyqGSIb3DQEJEAIvMSgwJjAkMCIEIIW+kOEK0kONfMkotq9IsJqyCBd87PiwEmxY
# 05EFJcQ8MD8GCSqGSIb3DQEJBDEyBDAj7ZS0gmpaZ1kOFn0rl/lOaGeqcT3XcW25
# A3W8Cj9kCdFwAekqgGyUkb4n6WrDyaQwgZ8GCyqGSIb3DQEJEAIMMYGPMIGMMIGJ
# MIGGBBRXFGhBDKha80JO+RZKUTYQ9NONmDBuMFqkWDBWMQswCQYDVQQGEwJQTDEh
# MB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQDExtDZXJ0
# dW0gVGltZXN0YW1waW5nIDIwMjEgQ0ECECjwd8EcNr3+X3QyR3AnLgMwDQYJKoZI
# hvcNAQEBBQAEggIAtXlk1lU7pi2TpXSpJBNpNDA6YiJ1sCVsOXRRFJaqgdZWICBK
# 28eI2Du/iejNNCGVPRZyJiI71vz/I5JpsKrUi4ZV/kvONfqyviSG5tspKcpOLZmj
# kgGeBx6dvw7wZP/H8+poRk2HQz5EgOC7eNjNxxdNYj0+3uda4TZ+nYRH+WfrCUi8
# lGosV7VfY9HgZ6993OB0zQfi58FAGcBUD/pozD/u4GuwvQqFA3r3POpI6xvt7wlz
# /XdHB30E0QDu+6loCdfoPmPLKQmJgpFwXX7q20abnwK+lg82fNNMnTbAp9B8oiTw
# XHc1D3C16jaBh7QVgmFn8qy1Yn1PM9H6rvJdUJeiAwY/fhtNl59+1WoRmwh2lIOs
# PBbph7by87bAHGkkaOeDQzAJdrKJC3kcrjDy2TMbiorEqoISY02xfQpG0WFaAZAz
# ST55hp5QSg7CzZms+n2daEujYoOdZPAoofFvHSRwFVJRH2Z/mYy0cnpmIET12vjH
# JdPiB76qmL/uHJg5ZLXioQlPx/wLXUjOgbZ56WbX+8rwdbKqmJEMaVCqArxYpr2l
# Irz5XH/MNORfqWIvEEEKRauR/lUmRjwf6huyuUjpZG4epP8hPQ9Nxb8QLtLYCGSf
# xm8SEeZL2Kb2W/x4torXWdChH5JNCxB15aISTmISLcv2k21bJTGgVcCaUAI=
# SIG # End signature block